我很确定这是一个愚蠢的问题,但我无法在其他任何地方找到它,所以我会在这里问它。
我使用带有7个标签的keras中的cnn(unet)进行语义图像分割。所以每个图像的标签是(7,n_rows,n_cols)使用theano后端。因此,对于每个像素,在7个层中,它是单热编码的。在这种情况下,使用分类交叉熵是正确的误差函数吗?这似乎对我来说,但网络似乎更好地学习二进制交叉熵损失。有人可以阐明为什么会这样,以及原则目标是什么?
答案 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
此方法将期望矩阵的顺序为(高度,宽度,通道)。