我正在尝试使用具有三个标签的数据集训练序列到序列的LSTM模型: [1, 0] 用于检测第1类, [0, 1] 用于检测第2类,而 [0, 0] 用于检测无任何标记 . 从LSTM网络获取输出后,我通过以下方式将完全连接的层应用于每个单元的输出:

outputs, state = tf.nn.dynamic_rnn(cell, input)
# Shape of outputs is [batch_size, n_time_steps, n_hidden]

# As matmul works only on matrices, reshape to get the
# time dimension into the batch dimension
outputs = tf.reshape(outputs, [-1, n_hidden])
# Shape is [batch_size * n_time_steps, n_hidden]

w = tf.Variable(tf.truncated_normal(shape=[n_hidden, 2], stddev=0.1))
b = tf.Variable(tf.constant(0.1, shape=[2]))
logit = tf.add(tf.matmul(outputs, w), b, name='logit')

# Reshape back to [batch_size, n_time_steps, 2]
logit = tf.reshape(logit, [batch_size, -1, 2])

在输出中,我应用 tf.nn.sigmoid_cross_entropy_with_logits 并减少平均值 . 该模型似乎可以很好地实现高精度和召回,除了在几乎所有情况下它输出 [0, 0][1, 1] 的事实 . 完全连接层的两个logit输出始终具有非常相似的值(但不相同) . 这有效地将精确度设置为50%,模型收敛于(但不是百分之几的百分之几) .

现在,我的直觉会告诉我,训练步骤一定有问题,并且两个完全连接的输出都在相同的数据上进行训练,但奇怪的是,当我用 tf.contrib 中预先打包的实现替换我自己的实现时:

outputs, state = tf.nn.dynamic_rnn(cell, input)
logit = tf.contrib.layers.fully_connected(outputs, 2, activation_fn=None)

在不改变任何其他事物的情况下,模型开始正确训练 . 现在,显而易见的解决方案是使用该实现,但为什么第一个不起作用呢?