语义分割 Keras 的交叉熵损失
Cross Entropy Loss for Semantic Segmentation Keras
我很确定这是一个愚蠢的问题,但我在其他地方找不到它,所以我要在这里问。
我正在使用带有 7 个标签的 keras 中的 cnn (unet) 进行语义图像分割。所以我对每张图片的标签是 (7,n_rows,n_cols) 使用 theano 后端。因此,在每个像素的 7 层中,它是单热编码的。在这种情况下,使用分类交叉熵是正确的误差函数吗?对我来说似乎是这样,但网络似乎通过二元交叉熵损失学习得更好。有人可以阐明为什么会这样以及原则性 objective 是什么吗?
二进制 cross-entropy 损失应该与最后一层的 sigmod
激活一起使用,它会严重惩罚相反的预测。它没有考虑到输出是 one-hot 编码的并且预测的总和应该是 1。但是由于 mis-predictions 受到严重惩罚,模型在某种程度上学会了正确分类。
现在执行 one-hot 代码的先验是使用 softmax
激活和分类 cross-entropy。这是你应该使用的。
现在问题是在您的情况下使用 softmax
,因为 Keras 不支持每个像素上的 softmax。
最简单的方法是使用 Permute
图层将尺寸排列为 (n_rows,n_cols,7),然后将其重塑为 (n_rows *n_cols,7) 使用 Reshape
层。然后你可以添加 softmax
激活层并使用交叉熵损失。数据也应该相应地重新整形。
另一种方法是实现 depth-softmax :
def depth_softmax(matrix):
sigmoid = lambda x: 1 / (1 + K.exp(-x))
sigmoided_matrix = sigmoid(matrix)
softmax_matrix = sigmoided_matrix / K.sum(sigmoided_matrix, axis=0)
return softmax_matrix
并将其用作 lambda 层:
model.add(Deconvolution2D(7, 1, 1, border_mode='same', output_shape=(7,n_rows,n_cols)))
model.add(Permute(2,3,1))
model.add(BatchNormalization())
model.add(Lambda(depth_softmax))
如果使用 tf
image_dim_ordering
那么你可以使用 Permute
层。
查看更多参考资料here。
我测试了@indraforyou的解决方案,认为提出的方法有一些错误。由于评论部分不允许适当的代码段,这是我认为的固定版本:
def depth_softmax(matrix):
from keras import backend as K
exp_matrix = K.exp(matrix)
softmax_matrix = exp_matrix / K.expand_dims(K.sum(exp_matrix, axis=-1), axis=-1)
return softmax_matrix
此方法要求矩阵的顺序为(高度、宽度、通道)。
我很确定这是一个愚蠢的问题,但我在其他地方找不到它,所以我要在这里问。
我正在使用带有 7 个标签的 keras 中的 cnn (unet) 进行语义图像分割。所以我对每张图片的标签是 (7,n_rows,n_cols) 使用 theano 后端。因此,在每个像素的 7 层中,它是单热编码的。在这种情况下,使用分类交叉熵是正确的误差函数吗?对我来说似乎是这样,但网络似乎通过二元交叉熵损失学习得更好。有人可以阐明为什么会这样以及原则性 objective 是什么吗?
二进制 cross-entropy 损失应该与最后一层的 sigmod
激活一起使用,它会严重惩罚相反的预测。它没有考虑到输出是 one-hot 编码的并且预测的总和应该是 1。但是由于 mis-predictions 受到严重惩罚,模型在某种程度上学会了正确分类。
现在执行 one-hot 代码的先验是使用 softmax
激活和分类 cross-entropy。这是你应该使用的。
现在问题是在您的情况下使用 softmax
,因为 Keras 不支持每个像素上的 softmax。
最简单的方法是使用 Permute
图层将尺寸排列为 (n_rows,n_cols,7),然后将其重塑为 (n_rows *n_cols,7) 使用 Reshape
层。然后你可以添加 softmax
激活层并使用交叉熵损失。数据也应该相应地重新整形。
另一种方法是实现 depth-softmax :
def depth_softmax(matrix):
sigmoid = lambda x: 1 / (1 + K.exp(-x))
sigmoided_matrix = sigmoid(matrix)
softmax_matrix = sigmoided_matrix / K.sum(sigmoided_matrix, axis=0)
return softmax_matrix
并将其用作 lambda 层:
model.add(Deconvolution2D(7, 1, 1, border_mode='same', output_shape=(7,n_rows,n_cols)))
model.add(Permute(2,3,1))
model.add(BatchNormalization())
model.add(Lambda(depth_softmax))
如果使用 tf
image_dim_ordering
那么你可以使用 Permute
层。
查看更多参考资料here。
我测试了@indraforyou的解决方案,认为提出的方法有一些错误。由于评论部分不允许适当的代码段,这是我认为的固定版本:
def depth_softmax(matrix):
from keras import backend as K
exp_matrix = K.exp(matrix)
softmax_matrix = exp_matrix / K.expand_dims(K.sum(exp_matrix, axis=-1), axis=-1)
return softmax_matrix
此方法要求矩阵的顺序为(高度、宽度、通道)。