multi-class 语义分割任务的联合交集 (IOU) 度量
Intersection over union (IOU) metric for multi-class semantic segmentation task
我有一个语义分割任务来使用 UNET 预测 5 通道掩码,例如掩码形状是 (224,244,5)。
我正在使用这个功能来欠条:
def mean_iou(y_true, y_pred):
y_pred = tf.round(tf.cast(y_pred, tf.int32))
intersect = tf.reduce_sum(tf.cast(y_true, tf.float32) * tf.cast(y_pred, tf.float32), axis=[1])
union = tf.reduce_sum(tf.cast(y_true, tf.float32),axis=[1]) + tf.reduce_sum(tf.cast(y_pred, tf.float32),axis=[1])
smooth = tf.ones(tf.shape(intersect))
return tf.reduce_mean((intersect + smooth) / (union - intersect + smooth))
def iou_loss(y_true, y_pred):
y_true = tf.reshape(y_true, [-1])
y_pred = tf.reshape(y_pred, [-1])
intersection = tf.reduce_sum(tf.cast(y_true, tf.float32) * tf.cast(y_pred, tf.float32))
score = (intersection + 1.) / (tf.reduce_sum(tf.cast(y_true, tf.float32)) +
tf.reduce_sum(tf.cast(y_pred, tf.float32)) - intersection + 1.)
return 1 - score`
和UNET模型的输出层:
outputs = tf.keras.layers.Conv2D(5, (1, 1), activation='softmax')(c9)
model = tf.keras.Model(inputs=[input_img], outputs=[outputs])
opti = tf.keras.optimizers.Adam(lr=0.003, clipvalue=0.7)
model.compile(optimizer=opti, loss=iou_loss, metrics=['accuracy',mean_iou])
但我不确定 IOU 函数是否正确实现,
你能澄清一下吗?
让我们把它分成更小的部分来了解发生了什么:
tf.reshape(y_true, [-1])
,y_pred = tf.reshape(y_pred, [-1])
;
预测和基本事实被转换成一维数组。之所以会发生这种情况,是因为从本质上讲,尽管您有多个地面实况掩码,但它们都仅由 1s
和 0s
.
组成
intersection = tf.reduce_sum(tf.cast(y_true, tf.float32) * tf.cast(y_pred, tf.float32))
。我们在这里乘法,因为只有当预测和真实值在某个位置上都为 1 时,乘法才会产生 1...0x1
或 1x0
或 0x0
当然不属于交集.
tf.reduce_sum()
。我们只是对交集的 1 求和。
score = (intersection + 1.) / (tf.reduce_sum(tf.cast(y_true, tf.float32)) + tf.reduce_sum(tf.cast(y_pred, tf.float32)) - intersection + 1.)
。这就是 IoU 的定义。注意分子和分母都加上1,避免被0除。在分母层面,由于Union运算本身已经包含了交集,为了正确计算IoU,我们需要记得减去交集,从而产生正确的 IoU 值。
1 - score
。我们return1-score
,因为如果IoU是0.75,例如loss是0.25(完美IoU == 1
)
我有一个语义分割任务来使用 UNET 预测 5 通道掩码,例如掩码形状是 (224,244,5)。
我正在使用这个功能来欠条:
def mean_iou(y_true, y_pred):
y_pred = tf.round(tf.cast(y_pred, tf.int32))
intersect = tf.reduce_sum(tf.cast(y_true, tf.float32) * tf.cast(y_pred, tf.float32), axis=[1])
union = tf.reduce_sum(tf.cast(y_true, tf.float32),axis=[1]) + tf.reduce_sum(tf.cast(y_pred, tf.float32),axis=[1])
smooth = tf.ones(tf.shape(intersect))
return tf.reduce_mean((intersect + smooth) / (union - intersect + smooth))
def iou_loss(y_true, y_pred):
y_true = tf.reshape(y_true, [-1])
y_pred = tf.reshape(y_pred, [-1])
intersection = tf.reduce_sum(tf.cast(y_true, tf.float32) * tf.cast(y_pred, tf.float32))
score = (intersection + 1.) / (tf.reduce_sum(tf.cast(y_true, tf.float32)) +
tf.reduce_sum(tf.cast(y_pred, tf.float32)) - intersection + 1.)
return 1 - score`
和UNET模型的输出层:
outputs = tf.keras.layers.Conv2D(5, (1, 1), activation='softmax')(c9)
model = tf.keras.Model(inputs=[input_img], outputs=[outputs])
opti = tf.keras.optimizers.Adam(lr=0.003, clipvalue=0.7)
model.compile(optimizer=opti, loss=iou_loss, metrics=['accuracy',mean_iou])
但我不确定 IOU 函数是否正确实现,
你能澄清一下吗?
让我们把它分成更小的部分来了解发生了什么:
组成tf.reshape(y_true, [-1])
,y_pred = tf.reshape(y_pred, [-1])
; 预测和基本事实被转换成一维数组。之所以会发生这种情况,是因为从本质上讲,尽管您有多个地面实况掩码,但它们都仅由1s
和0s
.intersection = tf.reduce_sum(tf.cast(y_true, tf.float32) * tf.cast(y_pred, tf.float32))
。我们在这里乘法,因为只有当预测和真实值在某个位置上都为 1 时,乘法才会产生 1...0x1
或1x0
或0x0
当然不属于交集.tf.reduce_sum()
。我们只是对交集的 1 求和。score = (intersection + 1.) / (tf.reduce_sum(tf.cast(y_true, tf.float32)) + tf.reduce_sum(tf.cast(y_pred, tf.float32)) - intersection + 1.)
。这就是 IoU 的定义。注意分子和分母都加上1,避免被0除。在分母层面,由于Union运算本身已经包含了交集,为了正确计算IoU,我们需要记得减去交集,从而产生正确的 IoU 值。1 - score
。我们return1-score
,因为如果IoU是0.75,例如loss是0.25(完美IoU == 1
)