如果我为最后一层设置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
,如下所示:
然后使用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上运行)。你可以改变激活层和分类交叉熵的逻辑,看看我说了什么。在
我想问题出在softmax激活函数上。查看doc我发现默认情况下sotmax应用于最后一个轴。你能看看
model.summary()
并检查一下这是否是你想要的吗?在将“softmax”激活推到交叉熵损失层可以显著简化损失计算,并使其在数值上更稳定。
在您的例子中,可能是数值问题严重到使
from_logits=False
选项的培训过程无效的情况。在你可以在this post中找到交叉熵损失(信息增益损失的一个特例)的推导。这一推导说明了将softmax与交叉熵损失相结合时避免的数值问题。在
要使
softmax
正常工作,必须确保:您正在使用
'channels_last'
作为Keras的默认通道配置。在(None, height, width, channels)
n_classes
放在最后一个轴上。但这也很奇怪,因为您使用的是Conv2D
,而您的输出{您的
Y
只有0和1(而不是像通常对图像那样的0和255)Y.max() == 1
和{Y = Y / 255.
只有一个类是正确的(您的数据没有多个值为1的路径/通道)。在
(Y.sum(axis=-1) == 1).all()
是否为True
相关问题 更多 >
编程相关推荐