【发布时间】:2019-11-04 00:21:25
【问题描述】:
我正在尝试使用generalized dice loss 函数在 TensorFlow 1.10 的 Keras API(使用 Python)中执行语义分割:
def generalized_dice_loss(onehots_true, logits):
smooth = tf.constant(1e-17)
onehots_true, logits = mask(onehots_true, logits) # Not all of my pixels contain ground truth, and I filter those pixels out, which results in shape [num_gt_pixels, num_classes]-shaped labels and logits.
probabilities = tf.nn.softmax(logits)
weights = 1.0 / (tf.reduce_sum(onehots_true, axis=0)**2)
weights = tf.clip_by_value(weights, 1e-17, 1.0 - 1e-7) # Is this the correct way of dealing with inf values (the results of zero divisions)?
numerator = tf.reduce_sum(onehots_true * probabilities, axis=0)
numerator = tf.reduce_sum(weights * numerator)
denominator = tf.reduce_sum(onehots_true + probabilities, axis=0)
denominator = tf.reduce_sum(weights * denominator)
loss = 1.0 - 2.0 * (numerator + smooth) / (denominator + smooth)
return loss
但是,我正在努力获得任何有意义的损失,这并不总是 1。我在这里做错了什么?
在计算初始权重(每个类别一个)后,它们包含许多来自零分割的inf,因为通常样本图像中只有所有类别的一小部分。因此,我将权重剪辑到 [1e-17, 1-1e-17] 范围内(这是个好主意吗?),之后它们看起来像这样:
tf.Tensor(
[4.89021e-05 2.21410e-10 5.43187e-11 1.00000e+00 1.00000e+00 4.23855e-07
5.87461e-09 3.13044e-09 2.95369e-07 1.00000e+00 1.00000e+00 2.22499e-05
1.00000e+00 1.73611e-03 9.47212e-10 1.12608e-05 2.77563e-09 1.00926e-08
7.74787e-10 1.00000e+00 1.34570e-07], shape=(21,), dtype=float32)
这对我来说似乎很好,虽然它们很小。分子(tf.reduce_sum(onehots_true * probabilities, axis=0),在加权之前)如下所示:
tf.Tensor(
[3.42069e+01 0.00000e+00 9.43506e+03 7.88478e+01 1.50554e-02 0.00000e+00
1.22765e+01 4.36149e-01 1.75026e+02 0.00000e+00 2.33183e+02 1.81064e-01
0.00000e+00 1.60128e+02 1.48867e+04 0.00000e+00 3.87697e+00 4.49753e+02
5.87062e+01 0.00000e+00 0.00000e+00], shape=(21,), dtype=float32)
tf.Tensor(1.0, shape=(), dtype=float32)
这看起来也很合理,因为它们基本上是标签各自的大小乘以网络对它们的确定性(在训练开始时可能很低)。分母(tf.reduce_sum(onehots_true + probabilities, axis=0),在加权之前)看起来也不错:
tf.Tensor(
[ 14053.483 25004.557 250343.36 66548.234 6653.863 3470.502
5318.3926 164206.19 19914.338 1951.0701 3559.3235 7248.4717
5984.786 7902.9004 133984.66 41497.473 25010.273 22232.062
26451.926 66250.39 6497.735 ], shape=(21,), dtype=float32)
这些很大,但这是意料之中的,因为像素总和为 1 的类概率,因此这些分母的总和应该或多或少等于具有基本事实的像素数量。
但是,将分子相加得到的总和非常小(~0.001,尽管有时它在一个数字范围内),而分母相加得到非常大的值。这导致我的最终损失完全是 1,或者非常接近。如何减轻这种影响并获得稳定的梯度?我几乎实现了确切的骰子损失公式。我在这里错过了什么?
【问题讨论】:
标签: python tensorflow keras loss-function