python - Tensorflow:Sigmoid 交叉熵损失不会强制网络输出为 0 或 1
问题描述
我想在 TensorFlow 中使用 {0.0,1.0} 中的值学习图像分割。我有两个图像,ground_truth
每个prediction
都有 shape (120,160)
。ground_truth
图像像素仅包含 0.0 或 1.0 的值。
预测图像是解码器的输出,它的最后两层是 a tf.layers.conv2d_transpose
,tf.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 层的单个输出的值分布如下所示:
问题:
我是否必须对输出进行后处理(裁剪负值或通过 sigmoid 激活等运行输出)?我需要做什么来强制我的输出值为 {0,1}?
解决方案
解决了。问题在于,tf.nn.sigmoid_cross_entropy_with_logits
通过 sigmoid 运行 logits,这在验证时当然不使用,因为仅在训练期间调用损失操作。因此解决方案是:
确保tf.nn.sigmoid
在验证/测试时运行网络输出,如下所示:
return output if is_training else tf.nn.sigmoid(output)
推荐阅读
- python - 如何在熊猫数据框中创建 10k 条记录?
- windows - PathBuf::starts_with 不适用于反斜杠
- ajax - 使用 AJAX 时带有承载令牌的 JWT 可防止 CSRF 和 XSS
- c - 我们可以在使用嵌入式系统时在 C 中使用 exit() 函数吗
- header - Fastify & NestJS - 如何在拦截器中设置响应头
- node.js - 查询 MongoDb 仅一个月,但我的日期是字符串格式“DD/MM/YYYY”使用时刻
- mysql - 为什么即使我的列中的电子邮件地址没有值为 0,我也会在查询中得到结果
- microsoft-graph-api - 尝试通过 Microsoft Graph 创建组时“权限不足,无法完成操作”
- java - Spring中@Bean和@Component在使用@Conditional时有什么区别?
- oauth2-playground - 遇到未捕获的异常类型:Google_Auth_Exception 消息:获取 OAuth2 访问令牌时出错,消息:'invalid_grant: Bad Request'