Tensorflow占位符,用于单热编码标签

时间:2018-04-21 16:27:48

标签: python tensorflow

我有一个热门的编码标签(11个等级,范围从0到10):

# one-hot encode labels
from sklearn.preprocessing import OneHotEncoder

labels = df.rating.values.reshape([-1, 1])
encoder = OneHotEncoder(sparse=False)
encoder.fit(labels)
labels = encoder.transform(labels)

并拥有以下占位符:

# create the graph object
graph = tf.Graph()
# add nodes to the graph
with graph.as_default():
    inputs_ = tf.placeholder(tf.int32, [None, None], name='inputs')
    labels_ = tf.placeholder(tf.int32, [None, 1], name='labels')
    keep_prob = tf.placeholder(tf.float32, name='keep_prob')

我正在使用sparse_softmax_cross_entropy

with graph.as_default():
    logits = tf.layers.dense(inputs=outputs[:, -1], units=1)
    loss = tf.losses.sparse_softmax_cross_entropy(labels=labels_, logits=logits)        
    optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss)

TF抛出:ValueError: Cannot feed value of shape (500, 1, 11) for Tensor 'labels:0', which has shape '(?, 1)'

我已经尝试了一切,但无法让它发挥作用。单热编码数据的正确占位符是什么?

1 个答案:

答案 0 :(得分:1)

第二个维度应该是你拥有的许多课程。单热编码意味着如果你让10个类,你编码5类,那将产生一个向量[0,0,0,0,0,1,0,0,0,0]这是10长。所以代码应该是:

labels_ = tf.placeholder(tf.int32, [None, ***number of classes***], name='labels')

然后,tf.losses.sparse_softmax_cross_entropy()再次采用 类标签 ,而不是单热编码。因此,您可以使用tf.argmax()对其进行解码,然后再将其提供给tf.losses.sparse_softmax_cross_entropy()

loss = tf.losses.sparse_softmax_cross_entropy(
    labels = tf.argmax( labels_, axis = 1 ), logits = logits )

或真正的问题是,为什么你首先使用ont-hot编码呢?您只需将df.rating.values.reshape([-1, 1])作为labels_提供给图表,并将1保留在第二维中。整个单热编码块是不必要的。

您的代码中存在一些其他问题(原始问题中未显示)会影响此问题。首先,你这样喂网络:

    feed = {inputs_: x,
            labels_: y[:, None],
            keep_prob: 1,
            initial_state: test_state}

为了尝试解决labels_问题,您添加了索引[:, None]。问题是在Numpy中,索引None具有特殊含义:它将插入一个新维度。这就是( 500, 1, 1 )中额外维度的来源。这里不需要索引y,我已将其删除。所以代码应该是:

    feed = {inputs_: x,
            labels_: y,
            keep_prob: 1,
            initial_state: test_state}

然后是另一个问题,一个非常常见的错误,在这一行:

loss, state, _ = sess.run([loss, final_state, optimizer], feed_dict=feed)

您将loss的值分配给loss,因此loss现在是 数字 ,而不是应该是张量 。所以在第二次迭代时代码失败了。我已将其更改为

loss_val, state, _ = sess.run([loss, final_state, optimizer], feed_dict=feed)

但当然您还需要将更改传播到print()

print("Epoch: {}/{}".format(e, epochs),
      "Iteration: {}".format(iteration),
      "Train loss: {:.3f}".format(loss_val))

此外,在您定义日志的地方,您必须有11个单元,因为您有11个类(0 - 10),并且每个类需要一个概率:

logits = tf.layers.dense(inputs=outputs[:, -1], units=11 )

随着这些变化,训练运行,甚至似乎学到了一些东西:

  

('大纪元:0/10','迭代:5','火车损失:1.735')
  ('大纪元:0/10','迭代:10','火车损失:2.092')
  ('大纪元:0/10','迭代:15','火车损失:2.644')
  ('大纪元:0/10','迭代:20','火车损失:1.596')
  ('大纪元:0/10','迭代:25','火车损失:1.759')
  Val acc:0.012
  ('大纪元:0/10','迭代:30','火车损失:1.581')
  ('大纪元:0/10','迭代:35','火车损失:2.213')
  ('大纪元:0/10','迭代:40','火车损失:2.176')
  ('大纪元:0/10','迭代:45','火车损失:1.849')
  ('大纪元:0/10','迭代:50','火车损失:2.474')
  Val acc:0.017