如何解决如何创建由骰子损失和焦点损失组成的混合损失 [Python]
我正在尝试在 Python 中实现 Multiclass Hybrid loss 函数,该函数来自以下文章 https://arxiv.org/pdf/1808.05238.pdf,用于解决我使用不平衡数据集的语义分割问题。我设法让我的实现足够正确,可以在训练模型时开始,但结果很差。模型架构 - U-net,Adam 优化器中的学习率为 1e-5。面具形状是 (None,512,3),有 3 个类(在我的例子中是森林、森林砍伐、其他)。我用来实现我的损失的公式:
我创建的代码:
def build_hybrid_loss(_lambda_=1,_alpha_=0.5,_beta_=0.5,smooth=1e-6):
def hybrid_loss(y_true,y_pred):
C = 3
tversky = 0
# Calculate Tversky Loss
for index in range(C):
inputs_fl = tf.nest.flatten(y_pred[...,index])
targets_fl = tf.nest.flatten(y_true[...,index])
#True Positives,False Positives & False Negatives
TP = tf.reduce_sum(tf.math.multiply(inputs_fl,targets_fl))
FP = tf.reduce_sum(tf.math.multiply(inputs_fl,1-targets_fl[0]))
FN = tf.reduce_sum(tf.math.multiply(1-inputs_fl[0],targets_fl))
tversky_i = (TP + smooth) / (TP + _alpha_ * FP + _beta_ * FN + smooth)
tversky += tversky_i
tversky += C
# Calculate Focal loss
loss_focal = 0
for index in range(C):
f_loss = - (y_true[...,index] * (1 - y_pred[...,index])**2 * tf.math.log(y_pred[...,index]))
# Average over each data point/image in batch
axis_to_reduce = range(1,3)
f_loss = tf.math.reduce_mean(f_loss,axis=axis_to_reduce)
loss_focal += f_loss
result = tversky + _lambda_ * loss_focal
return result
return hybrid_loss
模型在epoch结束后的预测(我有交换颜色的问题,所以预测中的红色实际上是绿色的,这意味着森林,所以预测主要是森林而不是森林砍伐):
问题是我的混合损失实现有什么问题,需要进行哪些更改才能使其正常工作?
解决方法
为了简化一些事情,我将混合损失分为四个独立的函数:Tversky 损失、Dice 系数、Dice 损失、混合损失。你可以看到下面的代码。
def TverskyLoss(targets,inputs,alpha=0.5,beta=0.5,smooth=1e-16,numLabels=3):
tversky = 0
for index in range(numLabels):
inputs_fl = tf.nest.flatten(inputs[...,index])
targets_fl = tf.nest.flatten(targets[...,index])
#True Positives,False Positives & False Negatives
TP = tf.reduce_sum(tf.math.multiply(inputs_fl,targets_fl))
FP = tf.reduce_sum(tf.math.multiply(inputs_fl,1-targets_fl[0]))
FN = tf.reduce_sum(tf.math.multiply(1-inputs_fl[0],targets_fl))
tversky_i = (TP + smooth) / (TP + alpha*FP + beta*FN + smooth)
tversky += tversky_i
return numLabels - tversky
def dice_coef(y_true,y_pred,smooth=1e-16):
y_true_f = tf.nest.flatten(y_true)
y_pred_f = tf.nest.flatten(y_pred)
intersection = tf.math.reduce_sum(tf.math.multiply(y_true_f,y_pred_f))
return (2. * intersection + smooth) / (tf.math.reduce_sum(y_true_f) + tf.math.reduce_sum(y_pred_f) + smooth)
def dice_coef_multilabel(y_true,numLabels=3):
dice=0
for index in range(numLabels):
dice -= dice_coef(y_true[...,index],y_pred[...,index])
return numLabels + dice
def build_hybrid_loss(_lambda_=0.5,_alpha_=0.5,_beta_=0.5,C=3):
def hybrid_loss(y_true,y_pred):
tversky = TverskyLoss(y_true,alpha=_alpha_,beta=_beta_)
dice = dice_coef_multilabel(y_true,y_pred)
result = tversky + _lambda_ * dice
return result
return hybrid_loss
在模型编译时添加loss=build_hybrid_loss()
会添加Hybrid loss作为模型的损失函数。
经过简短的研究后,我得出的结论是,在我的特定情况下,带有 _lambda_ = 0.2,_alpha_ = 0.5,_beta_ = 0.5
的混合损失不会比单个 Dice 损失或单个 Tversky 损失好多少。混合损失的 IoU(交集)和标准精度指标都没有好得多。但我认为,这种混合损失在所有情况下都会更糟或与单一损失处于相同的性能水平,这并不是经验法则。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。