(C4 Wk3) Using IoU for Semantic Segmentation

Dear Mentors: Again trying to adapt to other applications the semantic segmentation example in Assignment 2, Wk 3, Course 4.
I have a dataset with two classes ony. The images and masks are of shape (512, 512, 1). The mask pixel values are 0 or 1. When I compile the segmentation model, similar to “Unet” in the Coursera assignment, using BinaryCrossentropy as loss, the model.fit function works well, provided that the metrics are accuracy or BinaryCrossentropy. However, if I attempt to use BinaryIoU as metrics, which seems the most appropriate for a binary segmenter, an error appears.
The error originates at unet.fit

history = unet.fit(train_dataset, epochs=initial_epochs)

and the traceback concludes that

File “C:\Users\erios\Anaconda3b\envs\Tensorflow\Lib\site-packages\keras\src\metrics\iou_metrics.py”, line 140, in update_state
current_cm = tf.math.confusion_matrix(
Node: ‘confusion_matrix/stack_1’
Shapes of all inputs must match: values[0].shape = [4194304] != values[1].shape = [8388608]
[[{{node confusion_matrix/stack_1}}]] [Op:__inference_train_function_24084]

I marked the key issue in boldface. The shape of values [0] and [1] differ by a factor of 2. In my understanding, these are the true and predicted masks. But I may be wrong.
Why doesn’t this work? Please help; thanks in advance.

Hello @EduardoChicago
It seems that you are encountering an issue with the shape of the true and predicted masks when using BinaryIoU as a metric. Based on the information provided, it’s difficult to pinpoint the exact cause of the issue without seeing the code snippet where you define and compile your segmentation model. However, I can provide some general guidance that might help you resolve the issue.

First, ensure that your model’s output layer has a sigmoid activation function, as it is suitable for binary segmentation tasks:

output_layer = tf.keras.layers.Activation('sigmoid')(previous_layer)

Next, when compiling your model, use the BinaryCrossentropy loss and BinaryIoU metric:

unet.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(), metrics=[tf.keras.metrics.BinaryIoU(threshold=0.5)])

Make sure to set an appropriate threshold for the BinaryIoU metric. The default value is 0.5, which means that predicted values above 0.5 will be considered as class 1, and those below 0.5 will be considered as class 0.

If you still encounter issues, you might need to preprocess your input data and ensure that the true and predicted masks have the correct shapes. You can also try using a custom metric that binarizes the output of your network before computing the IoU, as suggested in this Stack Overflow post.

Please provide the code snippet via Direct Message to me where you define and compile your segmentation model if you need further assistance.
Regards,
Can Koz