如果输出变量是二进制变量,是否需要使用one_hot编码?

时间:2017-08-11 18:55:56

标签: python machine-learning tensorflow one-hot-encoding

我正在开发一个基于MNIST的Tensorflow网络,用于初学者模板。基本上,我试图实现一个简单的逻辑回归,其中10个连续变量预测二进制结果,所以我的输入是介于0和1之间的10个值,我的目标变量(代码中的Y_train和Y_test)是1或0。

我的主要问题是无论我运行多少训练集,准确度都没有变化 - 无论我运行100步还是31240步,都是0.276667。另外,当我从softmax切换到简单matmul以生成我的Y值时,我得到0.0精度,这表明我的x * W + b计算可能有问题。输入读出来就好了。

我想知道的是a)我是否因为代码错误而无法正确计算Y值,b)如果不是这样,我是否可能需要实现one_hot向量 - 即使我的输出已经采用0或1的形式。如果是后者,我在哪里包含one_hot = TRUE函数在我的目标值向量的生成中?谢谢!

import numpy as np
import tensorflow as tf
train_data = np.genfromtxt("TRAINDATA2.txt", delimiter="    ")
train_input = train_data[:, :10]
train_input = train_input.reshape(31240, 10)
X_train = tf.placeholder(tf.float32, [31240, 10])

train_target = train_data[:, 10]
train_target = train_target.reshape(31240, 1)
Y_train = tf.placeholder(tf.float32, [31240, 1])

test_data = np.genfromtxt("TESTDATA2.txt", delimiter = "    ")
test_input = test_data[:, :10]
test_input = test_input.reshape(7800, 10)
X_test = tf.placeholder(tf.float32, [7800, 10])

test_target = test_data[:, 10]
test_target = test_target.reshape(7800, 1)
Y_test = tf.placeholder(tf.float32, [7800, 1])

W = tf.Variable(tf.zeros([10, 1]))
b = tf.Variable(tf.zeros([1]))

Y_obt = tf.nn.softmax(tf.matmul(X_train, W) + b)
Y_obt_test = tf.nn.softmax(tf.matmul(X_test, W) + b)

cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=Y_obt, 
labels=Y_train)
train_step = tf.train.GradientDescentOptimizer(0.05).minimize(cross_entropy)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()

for _ in range(31240):
    sess.run(train_step, feed_dict={X_train: train_input, 
    Y_train:train_target})

correct_prediction = tf.equal(tf.round(Y_obt_test), Y_test)
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
print(sess.run(accuracy, feed_dict={X_test : test_input, Y_test: 
test_target}))

1 个答案:

答案 0 :(得分:2)

由于您使用一个元素将值映射到目标,因此您不应使用softmax交叉熵,因为softmax操作会将输入转换为概率分布,所有概率的总和等于1.因为您的目标只有一个元素,它每次只输出1,因为这是将输入转换为概率分布的唯一可能方法。 您应该使用tf.nn.sigmoid_cross_entropy_with_logits()(用于二进制分类)并从Y_obt中移除softmax并将其转换为tf.sigmoid() Y_obt_test

另一种方法是对目标进行单热编码,并使用具有双元素输出的网络。在这种情况下,您应该使用tf.nn.softmax_cross_entropy_with_logits(),但要从tf.nn.softmax()中移除Y_obt,因为softmax交叉熵需要未缩放的logits(https://www.tensorflow.org/api_docs/python/tf/nn/softmax_cross_entropy_with_logits)。对于Y_obt_test,在这种情况下,您当然不应将其删除。

另一件事:用cross_entropy = tf.reduce_mean(tf.sigmoid_cross_entropy_...)取得交叉熵的平均值也可能有所帮助。