让我试着回答你的问题的一部分, 为什么准确率会如此迅速地提高,而骰子系数却越来越慢地上升? 我猜这不是你的模型或实现的问题/错误。事实上,我想说,这根本不是一个“问题”,而是你的指标的一个属性:
-
像素精度衡量的是正确分配的像素数相对于总像素数的比例。因此,从某种意义上说,这是一种将前景和背景像素视为相同值的测量方法。
-
Dice 或 IoU 值仅关注 前景 像素。请注意,您的
dice_coefficients()
和 iou()
实现仅计算前景像素,而从不计算图像中的总像素数。
现在假设您有一个分割掩码,其中前景像素相对于图像大小只有几个;假设您的正确分割掩码是 [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
。如果您的网络预测现在全为零( [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
),则其准确率已经达到 0.8(因为 80% 的像素已正确分配)。但是,Dice 和 IoU 值都将为零,因为尚未 正确分配 前景
下面的示例通过几次迭代证明了这一点(我使用 NumPy 进行计算,但这应该没有什么区别):
import matplotlib.pyplot as plt
import numpy as np
def dice_coefficients(y_true, y_pred, smooth=0):
intersection = np.sum(y_true * y_pred)
union = np.sum(y_true) + np.sum(y_pred)
return (2 * intersection + smooth) / (union + smooth)
def accuracy(y_true, y_pred, threshold=0.5):
y_pred = y_pred > threshold
return (y_true == y_pred).sum() / y_pred.size
y_true = np.asarray([0, 0, 0, 0, 0, 0, 0, 0, 1, 1])
# Round 1: Predict everything as ones
y_pred = np.asarray([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
print("Acc.", a1 := accuracy(y_true, y_pred))
print("Dice", d1 := dice_coefficients(y_true, y_pred))
# Round 2: Predict everything as zeros
y_pred = np.asarray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
print(a2 := accuracy(y_true, y_pred))
print(d2 := dice_coefficients(y_true, y_pred))
# Round 3: Predict one foreground pixel correctly
y_pred = np.asarray([0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
print(a3 := accuracy(y_true, y_pred))
print(d3 := dice_coefficients(y_true, y_pred))
# Round 4: Predict all foreground pixels correctly
y_pred = np.asarray([0, 0, 0, 0, 0, 0, 0, 0, 1, 1])
print(a4 := accuracy(y_true, y_pred))
print(d4 := dice_coefficients(y_true, y_pred))
plt.plot([1, 2, 3, 4], [a1, a2, a3, a4], label="Acc.")
plt.plot([1, 2, 3, 4], [d1, d2, d3, d4], label="Dice")
plt.legend()
plt.show()
对应的图是
底线:尝试理解并感受您使用的指标。如果它们的表现不如您所期望的那样,有时可能不是您的 实现 ,而是您的 期望 .