使用 seq2seq API 的 Tensorflow 序列到序列模型(ver 1.1 及以上)

Tensorflow Sequence to sequence model using the seq2seq API ( ver 1.1 and above)

我正在使用 TensorFlow v:1.1,我想使用 sequence to sequence 模型tf.contrib.seq2seq api。 但是,我很难理解如何使用提供的所有函数(BasicDecoder、Dynamic_decode、Helper、Training Helper ...)来构建我的模型。

这是我的设置:我想 "translate" 一系列特征向量:(batch_size, encoder_max_seq_len, feature_dim) 到不同长度的序列 (batch_size, decoder_max_len, 1)

我已经有了 编码器,它是一个带有 LSTM 单元的 RNN,我得到了它的最终状态,我想提供作为初始输入的解码器。 我的解码器 MultiRNNCell LSM 已经有了单元格。 你能帮助我使用 tf.contrib.seq2seq2 和 dynamic_decode 的函数构建最后一部分吗(示例代码解释 将不胜感激)?

这是我的代码:

import tensorflow as tf
from tensorflow.contrib import seq2seq
from tensorflow.contrib import rnn
import math

from data import gen_sum_2b2

class Seq2SeqModel:
def __init__(self,
             in_size,
             out_size,
             embed_size,
             n_symbols,
             cell_type,
             n_units,
             n_layers):
    self.in_size = in_size
    self.out_size = out_size
    self.embed_size = embed_size
    self.n_symbols = n_symbols
    self.cell_type = cell_type
    self.n_units = n_units
    self.n_layers = n_layers

    self.build_graph()

def build_graph(self):
    self.init_placeholders()
    self.init_cells()
    self.encoder()
    self.decoder_train()
    self.loss()
    self.training()

def init_placeholders(self):
    with tf.name_scope('Placeholders'):
        self.encoder_inputs = tf.placeholder(shape=(None, None, self.in_size), 
                                             dtype=tf.float32, name='encoder_inputs')
        self.decoder_targets = tf.placeholder(shape=(None, None),
                                              dtype=tf.int32, name='decoder_targets')
        self.seqs_len = tf.placeholder(dtype=tf.int32)
        self.batch_size = tf.placeholder(tf.int32, name='dynamic_batch_size')
        self.max_len = tf.placeholder(tf.int32, name='dynamic_seq_len')
        decoder_inputs = tf.reshape(self.decoder_targets, shape=(self.batch_size,
                                    self.max_len, self.out_size))
        self.decoder_inputs = tf.cast(decoder_inputs, tf.float32)
        self.eos_step = tf.ones([self.batch_size, 1], dtype=tf.float32, name='EOS')
        self.pad_step = tf.zeros([self.batch_size, 1], dtype=tf.float32, name='PAD')

def RNNCell(self):
    c = self.cell_type(self.n_units, reuse=None)
    c = rnn.MultiRNNCell([self.cell_type(self.n_units) for i in range(self.n_layers)])
    return c

def init_cells(self):
    with tf.variable_scope('RNN_enc_cell'):
        self.encoder_cell = self.RNNCell()  
    with tf.variable_scope('RNN_dec_cell'):
        self.decoder_cell = rnn.OutputProjectionWrapper(self.RNNCell(), self.n_symbols)

def encoder(self):
    with tf.variable_scope('Encoder'):
        self.init_state = self.encoder_cell.zero_state(self.batch_size, tf.float32) 
        _, self.encoder_final_state = tf.nn.dynamic_rnn(self.encoder_cell, self.encoder_inputs,
                                                        initial_state=self.init_state) 

解码层:

解码由两部分组成,因为它们在 traininginference 期间的差异:

The decoder input at a particular time-step always comes from the output of the previous time-step. But during training, the output is fixed to the actual target (the actual target is fed back as input) and this has shown to improve performance.

这两个都是使用 tf.contrib.seq2seq 中的方法处理的。

  1. decoder的主要功能是:seq2seq.dynamic decoder()执行动态解码:

    tf.contrib.seq2seq.dynamic_decode(decoder,maximum_iterations)

    这需要一个 Decoder 实例和 maximum_iterations=maximum seq length 作为输入。

    1.1 Decoder 实例来自:

    seq2seq.BasicDecoder(cell, helper, initial_state,output_layer)

    输入是:cell(一个 RNNCell 实例),helper(辅助实例),initial_state(解码器的初始状态应该是编码器的输出状态) 和 output_layer(一个可选的密集层作为输出进行预测)

    1.2 一个RNNCell实例可以是一个rnn.MultiRNNCell().

    1.3 helper 实例与 traininginference 不同。在 training 期间,我们希望将输入馈送到解码器,而在 inference 期间,我们希望将 time-step (t) 中解码器的输出作为输入传递给 time-step (t) 中的解码器。 =31=]。

    为了训练:我们使用辅助函数: seq2seq.TrainingHelper(inputs, sequence_length),它只是读取输入。

    为了推理:我们调用辅助函数: seq2seq.GreedyEmbeddingHelper() or seqseq.SampleEmbeddingHelper(),这与它是否使用 argmax() or sampling(from a distribution) 的输出和将结果通过嵌入层以获得下一个输入不同。

放在一起:Seq2Seq 模型

  1. encoder layer 获取编码器状态并将其作为 initial_state 传递给解码器。
  2. 使用 seq2seq.dynamic_decoder() 获取 decoder traindecoder inference 的输出。当您调用这两种方法时,请确保共享权重。 (使用 variable_scope 重用权重)
  3. 然后使用损失函数训练网络seq2seq.sequence_loss

给出了示例代码here and here