语义分割Keras的交叉熵损失

时间:2017-02-08 16:41:06

标签: image-processing deep-learning keras

我很确定这是一个愚蠢的问题,但我无法在其他任何地方找到它,所以我会在这里问它。

我使用带有7个标签的keras中的cnn(unet)进行语义图像分割。所以每个图像的标签是(7,n_rows,n_cols)使用theano后端。因此,对于每个像素,在7个层中,它是单热编码的。在这种情况下,使用分类交叉熵是正确的误差函数吗?这似乎对我来说,但网络似乎更好地学习二进制交叉熵损失。有人可以阐明为什么会这样,以及原则目标是什么?

2 个答案:

答案 0 :(得分:14)

二进制交叉熵损失应该与最后一层中的sigmod激活一起使用,并严重惩罚相反的预测。它没有考虑到输出是一个热门的编码,预测的总和应该是1.但由于错误预测严重惩罚模型,有些学会正确分类。

现在强制执行单热代码的先验是使用softmax激活和分类交叉熵。这是你应该使用的。

现在问题是在你的情况下使用softmax因为Keras不支持每个像素上的softmax。

最简单的方法是使用Permute图层将尺寸置换为(n_rows,n_cols,7),然后使用Reshape图层将其重新整形为(n_rows * n_cols,7)。然后,您可以添加softmax激活图层并使用crossentopy loss。数据也应相应地重新塑造。

另一种方法是实现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

答案 1 :(得分:0)

我测试了@indraforyou的解决方案,并认为所提出的方法有一些错误。由于commentsection不允许适当的代码段,因此我认为这是固定版本:

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

此方法将期望矩阵的顺序为(高度,宽度,通道)。