如何在Keras中进行逐点分类的交叉熵损失?

时间:2017-03-26 19:23:34

标签: machine-learning neural-network keras cross-entropy loss-function

我有一个产生4D输出张量的网络,其中空间维度(〜像素)中每个位置的值将被解释为该位置的类概率。换句话说,输出为(num_batches, height, width, num_classes)。我有相同大小的标签,其中真实类被编码为一热。我想用此计算categorical-crossentropy损失。

问题#1: K.softmax函数需要2D张量(num_batches, num_classes)

问题#2 :我不确定每个职位的损失应该如何组合。 reshape张量到(num_batches * height * width, num_classes)然后再调用K.categorical_crossentropy是否正确?或者更确切地说,调用K.categorical_crossentropy(num_batches, num_classes)高度*宽度时间并平均结果?

4 个答案:

答案 0 :(得分:3)

将输出展平为尺寸为(num_batches, height * width * num_classes)的2D张量。您可以使用Flatten图层执行此操作。确保y以相同的方式展平(通常调用y = y.reshape((num_batches, height * width * num_classes))就足够了。)

对于第二个问题,对所有width*height预测使用分类交叉熵与对每个width*height预测的分类交叉熵平均(通过分类交叉熵的定义)基本相同。

答案 1 :(得分:3)

找到this issue来证实我的直觉。

简而言之:softmax将采用2D或3D输入。如果它们是3D keras将采用这样的形状(样本,时间尺度,数字)并在最后一个上应用softmax。出于一些奇怪的原因,它不适用于4D张量。

解决方案:将输出重塑为像素序列

reshaped_output = Reshape((height*width, num_classes))(output_tensor)

然后应用softmax

new_output = Activation('softmax')(reshaped_output) 

然后要么将目标张量重塑为2D,要么将最后一层重塑为(width,height,num_classes)。

否则,如果我现在不在手机上,我会尝试使用时间分配(激活(' softmax'))。但不知道这是否会奏效......稍后再尝试

我希望这会有所帮助:-)

答案 2 :(得分:2)

你也可能reshape无法自行定义softmaxloss。这是softmax,它应用于最后一个输入维度(如tf后端):

def image_softmax(input):
    label_dim = -1
    d = K.exp(input - K.max(input, axis=label_dim, keepdims=True))
    return d / K.sum(d, axis=label_dim, keepdims=True)

在这里你有loss(没有必要重塑任何东西):

__EPS = 1e-5
def image_categorical_crossentropy(y_true, y_pred):
    y_pred = K.clip(y_pred, __EPS, 1 - __EPS)
    return -K.mean(y_true * K.log(y_pred) + (1 - y_true) * K.log(1 - y_pred))

不需要进一步改造。

答案 3 :(得分:1)

现在看来,您现在可以简单地在最后一个softmax层上进行Conv2D激活,然后指定categorical_crossentropy丢失并在图像上进行训练,而无需任何重塑技巧或任何新的丢失功能。我尝试使用虚拟数据集进行过拟合,并且效果很好。试试吧〜!

inp = keras.Input(...)
# define your model here
out = keras.layers.Conv2D(classes, (1, 1), activation='softmax') (...)
model = keras.Model(inputs=[inp], outputs=[out], name='unet')
model.compile(loss='categorical_crossentropy',
                      optimizer='adam',
                      metrics=['accuracy'])
model.fit(tensor4d, tensor4d)

您还可以使用sparse_categorical_crossentropy进行编译,然后训练形状为(samples, height, width)的输出,其中输出中的每个像素对应一个类标签:model.fit(tensor4d, tensor3d)

想法是softmaxcategorical_crossentropy将应用于最后一个轴(您可以查看keras.backend.softmaxkeras.backend.categorical_crossentropy文档)。

PS。我使用keras中的tensorflow.keras(tensorflow 2)

更新:我已经对真实数据集进行了训练,并且它也可以正常工作。