I am building my loss function. However, when printing the value of the y_true tensor it is printing values with decimal points (i.e 0.25,0.569,0.958). This should not be true as the y_true should only have two classes 0 or 1. Here is my code:
#tf.function
def weighted_binary_crossentropy(y_true, y_pred):
y_true= K.reshape(y_true, (K.shape(y_true)[0], -1))
tf.print("tensors1:", y_true, output_stream=sys.stdout, summarize=50000)
Any reason why I am getting such an output instead of 0 and 1?
I am able to detect the issue which is from my data generator. When I have rotation_range added it mess up the values of the pixels. This is because on rotation new pixels are created
Related
I am trying to write a custom loss function to use in a Tensorflow 2 model.
def loss(y_true, y_pred):
1. wish to convert y_true and y_pred to numpy array (these are images)
2. After that I wish to carry out some operations (such as binarization of images, some pixel wise AND
or OR operation etc.)
3. Finally get a single floating number as a loss, and feed it to the model and minimize the loss.
can any one please suggest me how to do it? I already tried many of the options given on the internet but I am not able to convert y_true and y_pred into a numpy array.
In Keras I have a target vector of y_true that fits onto a network that has one output neuron. y_true = [0, 1, 0, 1, 1....] and I have some payoffs [1,1,1,-5,1...]
I'm trying to put the payoffs as extra parameters into a custom loss function of keras. Keras only allows two parameters to be passed into it (y_true and y_pred), but I would also like to pass the payoffs that are assigned to each sample. To that end I have added a second column to y_true that contains those values.
I then try to separate the actual y_true (first column) and the payoffs (second column) again in the loss function by doing the following:
def custom_loss(y_true, y_pred)
# y_true has the payoffs in the second row
payoffs = y_true[:, 1]
payoffs = K.expand_dims(payoffs, 1)
y_true = y_true[:, 0]
y_true = K.expand_dims(y_true, 1))
loss = K.binary_crossentropy(y_true, y_pred)
return loss
This is a simplified version of what I want to do (in the real version I will integrate the payoffs into the loss function). But for the example above I would expect the loss function to be identical to just calling binary_cross entropy directly with having y_true only containing y_true (without any payoffs).
However, the result is not as expected as the accuracy values are around half with the custom loss function above.
What could be the cause for this error? Am I not slicing y_true correctly?
The problem is related to what is described in this post (curiale's comment on 12 Dec 2017 suggests to use slice_stack, but the problem is the same).
I think the problem was that I needed to customize the metric function as well.
I want to implement a custom loss function, I read the following links
Implementing custom loss function in keras with different sizes for y_true and y_pred
What is y_true and y_pred when creating a custom metric in Keras?
But when I return the following in the metric function
K.sum(y_true)
it returns a float value.
My label values are all integrals, so why is their sum coming as float value?
I am attempting object segmentation using a custom loss function as defined below:
def chamfer_loss_value(y_true, y_pred):
# flatten the batch
y_true_f = K.batch_flatten(y_true)
y_pred_f = K.batch_flatten(y_pred)
# ==========
# get chamfer distance sum
// error here
y_pred_mask_f = K.cast(K.greater_equal(y_pred_f,0.5), dtype='float32')
finalChamferDistanceSum = K.sum(y_pred_mask_f * y_true_f, axis=1, keepdims=True)
return K.mean(finalChamferDistanceSum)
def chamfer_loss(y_true, y_pred):
return chamfer_loss_value(y_true, y_pred)
y_pred_f is the result of my U-net. y_true_f is the result of a euclidean distance transform on the ground truth label mask x as shown below:
distTrans = ndimage.distance_transform_edt(1 - x)
To compute the Chamfer distance, you multiply the predicted image (ideally, a mask with 1 and 0) with the ground truth distance transform, and simply sum over all pixels. To do this, I needed to get a mask y_pred_mask_f by thresholding y_pred_f, then multiply with y_true_f, and sum over all pixels.
y_pred_f provides a continuous range of values in [0,1], and I get the error None type not supported at the evaluation of y_true_mask_f. I know the loss function has to be differentiable, and greater_equal and cast are not. But, is there a way to circumvent this in Keras? Perhaps using some workaround in Tensorflow?
Well, this was tricky. The reason behind your error is that there is no continuous dependence between your loss and your network. In order to compute gradients of your loss w.r.t. to network, your loss must compute the gradient of indicator if your output is greater than 0.5 (as this is the only connection between your final loss value and output y_pred from your network). This is impossible as this indicator is partially constant and not continuous.
Possible solution - smooth your indicator:
def chamfer_loss_value(y_true, y_pred):
# flatten the batch
y_true_f = K.batch_flatten(y_true)
y_pred_f = K.batch_flatten(y_pred)
y_pred_mask_f = K.sigmoid(y_pred_f - 0.5)
finalChamferDistanceSum = K.sum(y_pred_mask_f * y_true_f, axis=1, keepdims=True)
return K.mean(finalChamferDistanceSum)
As sigmoid is a continuous version of a step function. If your output comes from sigmoid - you could simply use y_pred_f instead of y_pred_mask_f.
I am trying to write a cusom Keras loss function in which I process the tensors in sub-vector chunks. For example, if an output tensor represented a concatenation of quaternion coefficients (i.e. w,x,y,z,w,x,y,z...) I might wish to normalize each quaternion before calculating the mean squared error in a loss function like:
def norm_quat_mse(y_true, y_pred):
diff = y_pred - y_true
dist = 0
for i in range(0,16,4):
dist += K.sum( K.square(diff[i:i+4] / K.sqrt(K.sum(K.square(diff[i:i+4])))))
return dist/4
While Keras will accept this function without error and use in training, it outputs a different loss value from when applied as an independent function and when using model.predict(), so I suspect it is not working properly. None of the built-in Keras loss functions use this per-chunk processing approach, is it possible to do this within Keras' auto-differentiation framework?
Try:
def norm_quat_mse(y_true, y_pred):
diff = y_pred - y_true
dist = 0
for i in range(0,16,4):
dist += K.sum( K.square(diff[:,i:i+4] / K.sqrt(K.sum(K.square(diff[:,i:i+4])))))
return dist/4
You need to know that shape of y_true and y_pred is (batch_size, output_size) so you need to skip first dimension during computations.