目前我正在处理一个文本分类问题,但我甚至无法在TensorFlow中设置我的模型。我有一批长度为70的句子(使用填充),并且我使用了一个嵌入大小为300的embedding_lookup。这里是嵌入的代码:
embedding = tf.constant(embedding_matrix, name="embedding")inputs = tf.nn.embedding_lookup(embedding, input_.input_data)
所以现在inputs的形状应该是[batch_size, sentence_length, embedding_size],这并不奇怪。但遗憾的是,我的LSTMCell出现了ValueError,因为它期望ndim=2,而显然inputs是ndim=3。我还没有找到一种方法来改变LSTM层的预期输入形状。这里是我LSTMCell初始化的代码:
for i in range(num_layers): cells.append(LSTMCell(num_units, forget_bias, state_is_tuple, reuse=reuse, name='lstm_{}'.format(i))cell = tf.contrib.rnn.MultiRNNCell(cells, state_is_tuple=True)
错误是在单元的调用函数中触发的,看起来像这样:
for step in range(self.num_steps): if step > 0: tf.get_variable_scope().reuse_variables() (cell_output, state) = cell(inputs[:, step, :], state)
相似的问题但没有帮助: 理解TensorFlow LSTM输入形状
回答:
我自己解决了这个问题。看起来,LSTMCell的实现更手动和基础,关于LSTM实际的工作方式。Keras的LSTM层处理了我使用TensorFlow时需要考虑的事项。我使用的例子来自于以下官方TensorFlow示例:
https://github.com/tensorflow/models/tree/master/tutorials/rnn/ptb
因为我们希望用一个序列来喂养我们的LSTM层,我们需要一个接一个地将每个单词输入到单元中。因为单元的调用会创建两个输出(单元输出和单元状态),我们使用一个循环来处理所有句子中的所有单词,以此来喂养单元并重用我们的单元状态。这样我们为我们的层创建了输出,我们可以然后用于进一步的操作。这段代码看起来像这样:
self._initial_state = cell.zero_state(config.batch_size, data_type())state = self._initial_stateoutputs = []with tf.variable_scope("RNN"): for time_step in range(self.num_steps): if time_step > 0: tf.get_variable_scope().reuse_variables() (cell_output, state) = cell(inputs[:, time_step, :], state) outputs.append(cell_output)output = tf.reshape(tf.concat(outputs, 1), [-1, config.hidden_size])
num_steps代表我们将要使用的句子中的单词数量。