具有对数损失的 TensorFlow 单 sigmoid 输出与具有稀疏 softmax 交叉熵损失的两个线性输出,用于二进制分类

Posted

技术标签:

【中文标题】具有对数损失的 TensorFlow 单 sigmoid 输出与具有稀疏 softmax 交叉熵损失的两个线性输出,用于二进制分类【英文标题】:Tensorflow single sigmoid output with log loss vs two linear outputs with sparse softmax cross entropy loss for binary classification 【发布时间】:2018-05-23 04:40:33 【问题描述】:

我正在尝试在 TensorFlow 中实现二进制分类器。如果我在最后一层有两个普通输出(即没有激活)并使用tf.losses.sparse_softmax_cross_entropy,我的网络会按预期进行训练。但是,如果我将输出层更改为使用tf.sigmoid 激活生成单个输出并使用tf.losses.log_loss 作为损失函数,我的网络不会训练(即损失/准确性没有提高)。

这是我的输出层/损失函数在第一个(即工作)案例中的样子:

out = tf.layers.dense(prev, 2)
loss = tf.losses.sparse_softmax_cross_entropy(labels=y, logits=out)

在第二种情况下,我有以下内容:

out = tf.layers.dense(prev, 1, activation=tf.sigmoid)
loss = tf.losses.log_loss(labels=y, predictions=out)

张量y0/1值的向量;它不是单热编码的。在第一种情况下,网络按预期学习,但在第二种情况下则不然。除了这两行之外,其他一切都保持不变。

我不明白为什么第二个设置不起作用。有趣的是,如果我在 Keras 中表达相同的网络并使用第二种设置,它就可以工作。在第二种情况下,我是否使用了错误的 TensorFlow 函数来表达我的意图?我想产生一个单一的 sigmoid 输出并使用二元交叉熵损失来训练一个简单的二元分类器。

我正在使用 Python 3.6 和 TensorFlow 1.4。

Here 是一个小型、可运行的 Python 脚本,用于演示该问题。请注意,您需要从 Kaggle 下载 StatOil/C-CORE 数据集才能按原样运行脚本。

谢谢!

【问题讨论】:

我也遇到了同样的问题。 Sigmoid 和 log_loss 在 keras 中有效,但在 tensorflow 中没有学习发生。但是, sparse_softmax_cross_entropy 似乎有效。你找出问题所在了吗? 很遗憾没有。我仍然有兴趣了解我们为什么会看到这个问题。 【参考方案1】:

在两个输出上使用sigmoid 激活不会给出概率分布:

import tensorflow as tf
import tensorflow.contrib.eager as tfe
tfe.enable_eager_execution()

start = tf.constant([[4., 5.]])
out_dense = tf.layers.dense(start, units=2)
print("Logits (un-transformed)", out_dense)
out_sigmoid = tf.layers.dense(start, units=2, activation=tf.sigmoid)
print("Elementwise sigmoid", out_sigmoid)
out_softmax = tf.nn.softmax(tf.layers.dense(start, units=2))
print("Softmax (probability distribution)", out_softmax)

打印:

Logits (un-transformed) tf.Tensor([[-3.64021587  6.90115976]], shape=(1, 2), dtype=float32)
Elementwise sigmoid tf.Tensor([[ 0.94315267  0.99705648]], shape=(1, 2), dtype=float32)
Softmax (probability distribution) tf.Tensor([[ 0.05623185  0.9437682 ]], shape=(1, 2), dtype=float32)

您也可以在单个 logit 上使用 tf.sigmoid 而不是 tf.nn.softmax,然后将另一个输出设置为减去该值。

【讨论】:

我没有在两个输出上使用tf.sigmoid。我在单个输出上使用它并使用tf.losses.log_loss 计算损失。 哈,没错。所以tf.losses.log_loss 需要一个单热编码向量,但这与标量分布情况的稀疏标记相同。但问题是什么? tf.losses.log_loss(labels=[[label]], predictions=[[prediction_scalar]]) 等同于 sparse_softmax_cross_entropy(labels=[[label]], logits=[[1. - prediction_scalar, prediction_scalar]])label in [0, 1]

以上是关于具有对数损失的 TensorFlow 单 sigmoid 输出与具有稀疏 softmax 交叉熵损失的两个线性输出,用于二进制分类的主要内容,如果未能解决你的问题,请参考以下文章

单变量线性回归:TensorFlow 实战(理论篇)

Pytorch NLLLOSS 的理解

为什么逻辑回归损失函数不用均方损失/二元逻辑回归的损失函数适合采用对数损失函数

自定义损失函数 Tensorflow / Keras 惩罚相对距离

从极大似然到对数损失函数和交叉熵损失函数,以及对数损失优化取值范围

如何使用 TensorFlow 后端屏蔽 Keras 中的损失函数?