输入和输出都可以是不定长序列,例如机器翻译、图像描述
在训练数据集中,我们可以在每个句子后附上特殊符号“”(end of sequence)表示序列的终止。
编码器
编码器的作用是把一个不定长的输入序列变换成一个定长的背景变量 c,并在该背景变量中编码输入序列信息。常用的编码器是循环神经网络。
循环神经网络隐藏层的变换:
通过自定义函数 q 将各个时间步的隐藏状态变换为背景变量:
例如,当选择 q(h1,…,hT)=hT q ( h 1 , … , h T ) = h T 时,背景变量是输入序列最终时间步的隐藏状态 hT h T
编码器也可以时双向RNN,需要注意的是,编码器和解码器通常需要使用多层循环神经网络。(可以是多种多样的,网络结构以及自定义函数q)
class Encoder(nn.Block):
def __init__(self, num_inputs, embed_size, num_hiddens, num_layers,
drop_prob, **kwargs):
super(Encoder, self).__init__(**kwargs)
self.embedding = nn.Embedding(num_inputs, embed_size)
self.dropout = nn.Dropout(drop_prob)
self.rnn = rnn.GRU(num_hiddens, num_layers, dropout=drop_prob,
input_size=embed_size)
def forward(self, inputs, state):
embedding = self.embedding(inputs).swapaxes(0, 1)
embedding = self.dropout(embedding)
output, state = self.rnn(embedding, state)
return output, state
def begin_state(self, *args, **kwargs):
return self.rnn.begin_state(*args, **kwargs)
解码器
解码器的最初时间步输入来自“”符号。对于一个输出中的序列,当解码器在某一时间步搜索出“”符号时,即完成该输出序列。
编码器输出的背景变量 c c 编码了整个输入序列 的信息。给定训练样本中的输出序列 y1,y2,…,yT' y 1 , y 2 , … , y T ′ ,对每个时间步 t' t ′ ,解码器输出 yt' y t ′ 的条件概率将基于之前的输出序列 y1,…,yt'−1 y 1 , … , y t ′ − 1 和背景变量 c c ,即