Image processing 语义切分Keras的交叉熵损失

Image processing 语义切分Keras的交叉熵损失,image-processing,keras,deep-learning,image-segmentation,Image Processing,Keras,Deep Learning,Image Segmentation,我很确定这是一个愚蠢的问题,但我在其他任何地方都找不到,所以我想在这里问一下 我在keras中使用cnn(unet)和7个标签进行语义图像分割。因此,我使用theano后端为每个图像添加标签(7行,n列)。因此,在每个像素的7层中,它是一个热编码的。在这种情况下,使用分类交叉熵的错误函数是否正确?对我来说似乎是这样,但网络似乎通过二进制交叉熵损失学习得更好。有人能解释一下为什么会这样以及原则目标是什么吗?二进制交叉熵损失应该与最后一层中的sigmod激活一起使用,它会严重惩罚相反的预测。它没有考

我很确定这是一个愚蠢的问题,但我在其他任何地方都找不到,所以我想在这里问一下


我在keras中使用cnn(unet)和7个标签进行语义图像分割。因此,我使用theano后端为每个图像添加标签(7行,n列)。因此,在每个像素的7层中,它是一个热编码的。在这种情况下,使用分类交叉熵的错误函数是否正确?对我来说似乎是这样,但网络似乎通过二进制交叉熵损失学习得更好。有人能解释一下为什么会这样以及原则目标是什么吗?

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

现在,强制执行一个热代码的优先级是使用带有分类交叉熵的
softmax
激活。这是你应该使用的

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

最简单的方法是使用
permute
layer将维度排列为(n行,n列,7),然后使用
restrape
layer将其重塑为(n行*n列,7)。然后可以添加
softmax
激活层并使用crossentopy loss。数据也应相应地重新调整

另一种方法是实现深度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\u dim\u ordering,则可以使用
Permute


更多参考检查。

我测试了@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

该方法预计矩阵的顺序为(高度、宽度、通道)

谢谢你非常详细的回答!我使用了重塑、softmax和分类交叉熵。您认为这两种方法在速度或最终精度方面会有实质性的性能差异吗?再次感谢!我自己还没有研究过这个场景,但是你可以检查这两个场景。您还可以尝试的另一件事是,首先创建一个模型,最后一层为
sigmoid
,二元交叉熵损失,一旦完成训练,就用
softmax
替换顶层,并用分类交叉熵重新训练。第二次训练会很快收敛,但我敢打赌总的来说,训练时间会减少,并且会有更好的准确性。嗨,indraforyou,我也在研究语义分割案例。遮罩图像表示为(1,n_行,n_列)。对于这种情况,我可以使用乙状结肠和二元交叉熵吗?有什么具体的程序要包括吗?@user297850对于单通道,您不需要做任何特殊的事情。您可以简单地使用sigmoid和binary交叉entrophy。@indraforyou我有点被您的函数搞糊涂了
axis=0
表示沿行取和?我假设它将是
axis=-1
,因为您希望沿深度求和(但是,用
axis=0
替换
axis=1
不起作用,它将抛出一个错误)。此外,这是否真的会导致softmax?我假设它是
lambda x:K.exp(x)
。。。