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

Tensorflow: Sigmoid cross entropy loss does not force network outputs to be 0 or 1

我想学习使用 {0.0,1.0} 中的值在 TensorFlow 中进行图像分割。我有两个图像,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] 中。如果我可视化输出,我可以看到分割的对象没有被分割,因为几乎所有像素都是 "activated"。最后一个 conv2d 层的单个输出的值分布如下所示:

问题:

我是否必须 post-process 输出(裁剪负值或 运行 通过 sigmoid 激活等输出)?我需要做什么才能将我的输出值强制为 {0,1}?

解决了。问题是 tf.nn.sigmoid_cross_entropy_with_logits 运行 通过 sigmoid 进行对数,这当然不会在验证时使用,因为损失操作仅在训练期间调用。因此解决方案是:

确保 运行 网络在 validation/test 时通过 tf.nn.sigmoid 输出,如下所示:

return output if is_training else tf.nn.sigmoid(output)