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

时间:2017-12-08 21:57:22

标签: machine-learning tensorflow classification

我正在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数据集才能按原样运行脚本。

谢谢!

1 个答案:

答案 0 :(得分: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.nn.softmax,而不是tf.sigmoid,然后将另一个输出设置为减去该值。