My loss function returns 0 - what I do wrong?

hi all
I’m learning tenserflow and trying to write custom loss and metric functions, but instead of numbers I got 0. Could somebody point me what I do wrong.
Note that my data is # x1, y1 - left top, x2, y2 - right bottom
it looks like iou = tf.math.divide_no_nan(intersect_area, union_area) return 0 but should not.

def iou(y_true, y_pred):
    # x1, y1 - left top, x2, y2 - right bottom
    y_true = tf.cast(y_true, dtype=tf.float32)
    y_pred = tf.cast(y_pred, dtype=tf.float32)

    true_area = (y_true[..., 2] - y_true[..., 0]) * (y_true[..., 3] - y_true[..., 1])
    pred_area = (y_pred[..., 2] - y_pred[..., 0]) * (y_pred[..., 3] - y_pred[..., 1])

    tf.print("(iou)------>true_area:",true_area, output_stream=sys.stdout)
    tf.print("(iou)------>pred_area", pred_area, output_stream=sys.stdout)

    intersect_mins = tf.maximum(y_pred[..., :2], y_true[..., :2])
    intersect_maxes = tf.minimum(y_pred[..., 2:4], y_true[..., 2:4])
    intersect_wh = tf.maximum(intersect_maxes - intersect_mins, 0.)
    intersect_area = intersect_wh[..., 0] * intersect_wh[..., 1]

    union_area = pred_area + true_area - intersect_area
    iou = tf.math.divide_no_nan(intersect_area, union_area)
    tf.print("(iou)------>iou", iou, output_stream=sys.stdout)

    return iou

def iou_loss(y_true, y_pred):
    i = iou(y_true, y_pred)
    l = 1.0 - i
    return l

import tensorflow as tf
from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import Flatten, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dropout

base_model = VGG16(include_top=False, input_shape=(224, 224, 3))
x = base_model.output
x = Flatten()(x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
predictions = Dense(4, activation='relu')(x)

model = Model(inputs=base_model.input, outputs=predictions)
model.compile(optimizer='adam', loss=iou_loss, metrics=[iou, 'accuracy'])
history = model.fit(images_train, boxes_train[:,1], validation_data=(images_val, boxes_val[:, 1]), epochs=10, batch_size=32)

Update:

  1. data which I passed into model.fit function looks ok
  2. data normalization does not help
boxes_train_normalized = boxes_train[:, 1] / [224, 224, 224, 224]
boxes_val_normalized = boxes_val[:, 1] / [224, 224, 224, 224]
history = model.fit(images_train, boxes_train_normalized, validation_data=(images_val, boxes_val_normalized), epochs=10, batch_size=32)
  1. trick with tiny number also does not help
epsilon = 1e-7
union_area = pred_area + true_area - intersect_area + epsilon
iou = tf.math.divide_no_nan(intersect_area, union_area)
  1. changing activation function from relu to sigmoid also do not help

As per my understanding from the above code , the problem is that you are dividing by zero in the iou function. This is because the union_area can be zero if the two boxes do not overlap.

To handle the scenario where the union_area is zero and avoid returning a zero value for the IoU, you can use a conditional statement to handle this case separately or you can add a small epsilon to the union_area before dividing.

Hope this helps.

Thanks.

thanks for reply, but I don’t think it is real cause of my issue because to avoid that divide by 0 I added this code

epsilon = 1e-7
union_area = pred_area + true_area - intersect_area + epsilon
iou = tf.math.divide_no_nan(intersect_area, union_area)

and it doesn’t solve my problem.