我正在尝试使用带有keras实现的u-net,我使用以下repo https://github.com/zhixuhao/unet它运行良好,但我的问题是两类分段问题,所以我想将精度度量设置为jaccard,还有损失函数
我试着定义函数:
def Jac(y_true, y_pred):
y_pred_f = K.flatten(K.round(y_pred))
y_true_f = K.flatten(y_true)
num = K.sum(y_true_f * y_pred_f)
den = K.sum(y_true_f) + K.sum(y_pred_f) - num
return num / den
并在编译中调用它:
model.compile(optimizer = Adam(lr = 1e-4), loss = ['binary_crossentropy'], metrics = [Jac])
当我这样做时,每次迭代中的jaccard准确度会降低,直到达到ZERO!任何解释为什么会发生?
P.S:同样的事情发生在骰子上 .
P.S:输出层是带有S形激活函数的conv 1 * 1
更新:
在二进制精度的keras中附加原始实现:
def binary_accuracy(y_true, y_pred):
return K.mean(K.equal(y_true, K.round(y_pred)), axis=-1)
我可以看到它也使用舍入来获得输出预测 .
2 回答
你正在完成你的功能(
K.round
) .这导致两个问题:
(实际问题)该函数不可微分,不能作为损失函数(将显示错误"None values not supported")
每当您的网络不确定并且任何值低于0.5时,这些值将被视为零 .
如果
y_true
中的黑色(零)像素量大于白色(1)像素,则会发生这种情况:你的网络将倾向于首先将所有内容预测为零,这确实会导致更好的二进制交叉熵损失!
如果不是圆形的话,还有一个更好的Jaccard
但如果是圆形则为零Jaccard
并且仅在稍后,当学习率更精细地调整时,它将开始将白色像素带出它们应该的位置 .
出于上述两个原因,您应该使用非舍入函数 .
并有时绘制你的输出,看看发生了什么:)
请注意,如果您将其用作损失函数,请将其乘以-1(因为您希望它减少,而不是增加)
请尝试以下函数,从github复制 . 在keras指标中使用jacard_coef,如果你想让jacard_coef_loss keras丢失