Tensorflow:Sigmoid交叉熵损失不会强制网络输出为0或1

问题描述 投票:1回答:1

我想学习TensorFlow中的图像分割,其值为{0.0,1.0}。我有两个图像,ground_truthprediction,每个都有形状(120,160)ground_truth图像像素仅包含0.0或1.0的值。

预测图像是解码器的输出,它的最后两层是tf.layers.conv2d_transposetf.layers.conv2d,如下所示:

 transforms (?,120,160,30) -> (?,120,160,15)
outputs = tf.layers.conv2d_transpose(outputs, filters=15, kernel_size=1, strides=1, padding='same')
# ReLU
outputs = activation(outputs)

# transforms (?,120,160,15) -> (?,120,160,1)
outputs = tf.layers.conv2d(outputs, filters=1, kernel_size=1, strides=1, padding='same')

最后一层不带有激活功能,因此它的输出是无界的。我使用以下损失函数:

logits = tf.reshape(predicted, [-1, predicted.get_shape()[1] * predicted.get_shape()[2]])
labels = tf.reshape(ground_truth, [-1, ground_truth.get_shape()[1] * ground_truth.get_shape()[2]])

loss = 0.5 * tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=labels,logits=logits))

这种设置收敛得很好。但是,我已经意识到我在验证时的最后一个NN层的输出似乎在[-inf,inf]中。如果我可视化输出,我可以看到分割的对象没有被分割,因为几乎所有像素都被“激活”。最后一个conv2d层的单个输出的值分布如下所示:

imgur.com/a/kSPJneU

Question:

我是否必须对输出进行后处理(裁剪负值或通过S形激活等运行输出)?如何将输出值强制为{0,1},我需要做什么?

python tensorflow image-segmentation loss-function
1个回答
3
投票

解决了它。问题是tf.nn.sigmoid_cross_entropy_with_logits通过sigmoid运行logits,当然在验证时不使用,因为丢失操作仅在列车时间调用。因此解决方案是:

确保在验证/测试时通过tf.nn.sigmoid运行网络输出,如下所示:

return output if is_training else tf.nn.sigmoid(output)
© www.soinside.com 2019 - 2024. All rights reserved.