- Seq2Seq模型实际上是一个Encoder-Decoder的网络模型,由Encoder将变长的序列编码压缩成固定长度的向量,然后由Decoder将解码成目标序列
Seq2Seq
- [GO] 启动序列的解码,当解码到输出 [EOS] 时结束
- h0 是初始化的隐藏变量,s0 是初始化的解码输出
- 每一个 Input 参与到后一个 Input 的编码过程,使每一个Input的信息累积起来,到最后 Encoder 完成后输出成一个固定长度的向量。
- 向量参与到每一个 Output 的解码过程
- 每一个解码输出参与后一个Output的解码过程,保留这个序列之间每个Output的关联信息
- 训练时通过将前一位解码的输出对应的真实结果添加到当前位置的解码过程可以减少前几位解码过程造成的误差,帮助模型更快收敛
- 用 tensorflow 实现
##########
# encoder
inputs = tf.placeholder([None, ])
# 对于变长的输入序列,要定义好每条序列的长度
inputs_length = tf.placeholder([None,])
encoder_embedding = tf.Variable(tf.random_uniform([input_vocab_size, embedding_dim]))
encoder_input_embedded = tf.nn.embedding_lookup(encoder_embedding, inputs)
# 选用 lstm 作为编码的神经元
encoder_cell = tf.rnn.rnn_cell.LSTMCell(hidden_dim)
encoder_outputs, encoder_final_state = tf.nn.dynamic_rnn(cell=encoder_cell, inputs=encoder_input_embedded, sequence_length=inputs_length)
#########
# decoder
decoder_embedding = tf.Variable(tf.random_uniform([output_vocab_size, embedding_dim]))
labels = tf.placeholder([None, ])
labels_length = tf.placeholder([None, ])
target_embedded = tf.nn.embedding_lookup(decoder_embedding, labels)
decoder_cell = tf.rnn.rnn_cell.LSTMCell(hidden_dim)
# 构造辅助训练的 Decoder Input
GO = tf.zeros([batch_size])
decoder_embedding = tf.Variable(tf.random_uniform([output_vocab_size, embedding_dim]))
decoder_inputs_embedded = tf.nn.embedding_lookup(decoder_embedding, tf.concat([tf.reshape(GO, [-1, 1]), labels[:, :-1]], 1))
helper = tf.contrib.seq2seq.TrainingHelper(decoder_inputs_embedded, labels_length)
decoder_initial_state = tf.clone()
decoder = seq2seq_contrib.BasicDecoder(decoder_cell, helper, decoder_initial_state, output_layer=tf.layers.Dense(config.target_vocab_size))
decoder_outputs, decoder_state, final_sequence_lengths = tf.contrib.seq2seq.dynamic_decode(decoder, maximum_iterations=tf.reduce_max(self.seq_targets_length))
网友评论