decode_targets int32张量大小[decode_max_time,batch_size] encoder_inputs = tf.placeholder(shape=( None, None), dtype=tf.int32, name= 'encoder_inputs')decoder_targets = tf.placeholder(shape=( None, None), dtype=tf.int32, name= 'decoder_targets')我们额外添加一个节点,在 TensorFlow 中用placeholder 来描述等待输入的节点。 decode_inputs int32张量大小[decode_max_time,batch_size] decoder_inputs = tf.placeholder(shape=( None, None), dtype=tf.int32, name= 'decoder_inputs')我们实际上不想手动输入decode_inputs,它们在升级期间是decode_targets或以前的解码器输出的函数。但是,有不同的方式来构建它们。这可能是说明确指定它们的第一个seq2seq实现。 在训练期间,decode_inputs将包含沿时间轴与decode_target连接的<EOS>标记。以这种方式,我们总是将目标序列作为历史传递给解码器,无需实际输出预测。这可以引导从训练到预测的分配转移。在预测模式下,模型将接收先前生成的指令(通过argmax超过对数),而不是基本真值,这将是不可知的。 请注意,所有形状都用Nones(动态)指定。我们可以使用任意大小的批次和任意数量的时间步长。然而,这是方便和有效的,但是有明显的限制: 所有张量的Feed值应具有相同的batch_size 解码器输入和输出(decode_inputs和decode_target)应该具有相同的decode_max_time 编码(降维) encoder_inputs和decode_inputs是形状为[max_time,batch_size]的int32张量,而编码器和解码器RNN预期字的密集向量表示[max_time,batch_size,input_embedding_size]。 我们通过使用单词嵌入来将它们转换成另一个。 首先我们初始化嵌入矩阵。 初始化是随机的。 我们依靠端到端训练来与编码器和解码器共同学习矢量表示。 embeddings = tf.Variable(tf.random_uniform([vocab_size, input_embedding_size], - 1.0, 1.0), dtype=tf.float32) 我们使用tf.nn.embedding_lookup来索引嵌入矩阵:给定单词4,我们将其表示为第4列嵌入矩阵。 与单热编码字4的替代方法[0,0,0,1,0,0,0,0,0,0](vocab size 10)相比,该操作是轻量级的,然后通过嵌入矩阵。 另外,直播,除了4th之外,我们不需要计算任何列的渐变。 编码器和解码器将共享嵌入。 实际的NLP应用中,嵌入矩阵可以获得非常大的,具有100k甚至1m的列。 encoder_inputs_embedded = tf.nn.embedding_lookup(embeddings, encoder_inputs)decoder_inputs_embedded = tf.nn.embedding_lookup(embeddings, decoder_inputs) 编码器 TensorFlow中所有RNN的核心是RNNCell类及其衍生(如LSTMCell) encoder_cell = tf.contrib.rnn.LSTMCell(encoder_hidden_units)encoder_outputs, encoder_final_state = tf.nn.dynamic_rnn( encoder_cell, encoder_inputs_embedded, dtype=tf.float32, time_major= True,) delencoder_outputs 我们丢弃encoder_outputs,因为我们在seq2seq框架内对它们不感兴趣。 我们实际想要的是encoder_final_state - 在编码器卷展栏最后一刻的LSTM隐藏单元格的状态。 encoder_final_state也称为“思维向量”。 我们将使用它作为解码器的初始状态。 在seq2seq没有注意的情况下,这是编码器将信息传递给解码器的唯一点。 我们希望通过时间的反向传播(BPTT)算法将调整模型以通过思想向量传递足够的信息以进行正确的序列输出解码。 encoder_final_state LSTMStateTuple(c=<tf.Tensor 'rnn/while/Exit_2:0' shape=(?, 20) dtype=float32>, h=<tf.Tensor 'rnn/while/Exit_3:0' shape=(?, 20) dtype=float32>) TensorFlow LSTM实现将状态存储为张量的元组。 encoder_final_state.h是LSTM单元的隐藏层的激活 encoder_final_state.c是最终输出 解码器 decoder_cell = tf.contrib.rnn.LSTMCell(decoder_hidden_units)decoder_outputs, decoder_final_state = tf.nn.dynamic_rnn( decoder_cell, decoder_inputs_embedded, initial_state=encoder_final_state, dtype=tf.float32, time_major= True, scope= "plain_decoder",) 由于我们将encoder_final_state作为initial_state传递给解码器,所以它们应该是兼容的。 这意味着相同的单元格类型(在本例中为LSTMCell),相同数量的hidden_units和相同的图层数量(单层)。 我想这可以放宽,如果我们通过一个单层的MLP通过编码器_final_state。 使用编码器,我们对单元格输出不感兴趣。 但是解码器的输出是我们实际上的输出:我们使用它们来获得输出序列的单词的分布。 (责任编辑:本港台直播) |