from_logits = True和from_logits = False获得针对UNet的tf.losses.CategoricalCrossentropy的不同训练结果


问题内容

如果我Softmax Activation像这样设置最后一层,我正在用unet进行图像语义分割工作:

...
conv9 = Conv2D(n_classes, (3,3), padding = 'same')(conv9)
conv10 = (Activation('softmax'))(conv9)
model = Model(inputs, conv10)
return model
...

然后使用即使只有一个训练图像loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False) ,训练也 不会收敛

但是,如果我没有Softmax Activation像这样设置最后一层:

...
conv9 = Conv2D(n_classes, (3,3), padding = 'same')(conv9)
model = Model(inputs, conv9)
return model
...

然后使用loss = tf.keras.losses.CategoricalCrossentropy(from_logits=True) 训练将
收敛 为一个训练图像。

我的groundtruth数据集是这样生成的:

X = []
Y = []
im = cv2.imread(impath)
X.append(im)
seg_labels = np.zeros((height, width, n_classes))
for spath in segpaths:
    mask = cv2.imread(spath, 0)
    seg_labels[:, :, c] += mask
Y.append(seg_labels.reshape(width*height, n_classes))

为什么?我的用法有问题吗?

这是我的git实验代码:https :
//github.com/honeytidy/unet
您可以检出并运行(可以在cpu上运行)。您可以更改激活层和CategoricalCrossentropy的from_logits并查看我说的内容。


问题答案:

将“ softmax”激活推入交叉熵损失层可大大简化损失计算并使其在数值上更稳定。
在您的示例中,可能存在这样的情况:数字问题足够严重,导致培训过程对该from_logits=False选项无效。

您可以在此文章中找到交叉熵损失的一种推导(“信息增益”损失的一种特殊情况)。此推导说明了将softmax与交叉熵损失结合使用时避免的数值问题。