现代循环神经网络实战:机器翻译( 三 )

', ''])tgt_vocab = Vocab(target, min_freq=2,reserved_tokens=['', '', ''])src_array, src_valid_len = build_array_nmt(source, src_vocab, num_steps)tgt_array, tgt_valid_len = build_array_nmt(target, tgt_vocab, num_steps)data_arrays = (src_array, src_valid_len, tgt_array, tgt_valid_len)data_iter = load_array(data_arrays, batch_size)return data_iter, src_vocab, tgt_vocab
train_iter, src_vocab, tgt_vocab = load_data_nmt(batch_size=2, num_steps=8)for X, X_valid_len, Y, Y_valid_len in train_iter:print('X:', X.type(torch.int32))print('X的有效长度:', X_valid_len)print('Y:', Y.type(torch.int32))print('Y的有效长度:', Y_valid_len)break
编码器-解码器架构
正如我们上节中所讨论的,机器翻译是序列转换模型的一个核心问题,其输入和输出都是长度可变的序列 。为了处理这种类型的输入和输出,我们可以设计一个包含两个主要组件的架构: 第一个组件是一个编码器(): 它接受一个长度可变的序列作为输入,并将其转换为具有固定形状的编码状态 。第二个组件是解码器(): 它将固定形状的编码状态映射到长度可变的序列 。这被称为编码器-解码器(-)架构,如下图所示 。
我们以英语到法语的机器翻译为例: 给定一个英文的输入序列:“They”“are”“”“.” 。首先,这种“编码器-解码器”架构将长度可变的输入序列编码成一个“状态”,然后对该状态进行解码,一个词元接着一个词元地生成翻译后的序列作为输出: “Ils”“”“.” 。由于“编码器-解码器”架构是形成后续章节中不同序列转换模型的基础,因此本节将把这个架构转换为接口方便后面的代码实现 。
编码器
from torch import nn#@saveclass Encoder(nn.Module):"""编码器-解码器架构的基本编码器接口"""def __init__(self, **kwargs):super(Encoder, self).__init__(**kwargs)def forward(self, X, *args):raise NotImplementedError
解码器
#@saveclass Decoder(nn.Module):"""编码器-解码器架构的基本解码器接口"""def __init__(self, **kwargs):super(Decoder, self).__init__(**kwargs)def init_state(self, enc_outputs, *args):raise NotImplementedErrordef forward(self, X, state):raise NotImplementedError
合并编码器和解码器
#@saveclass EncoderDecoder(nn.Module):"""编码器-解码器架构的基类"""def __init__(self, encoder, decoder, **kwargs):super(EncoderDecoder, self).__init__(**kwargs)self.encoder = encoderself.decoder = decoderdef forward(self, enc_X, dec_X, *args):enc_outputs = self.encoder(enc_X, *args)dec_state = self.decoder.init_state(enc_outputs, *args)return self.decoder(dec_X, dec_state)
序列到序列学习()
遵循编码器-解码器架构的设计原则,循环神经网络编码器使用长度可变的序列作为输入,将其转换为固定形状的隐状态 。换言之,输入序列的信息被编码到循环神经网络编码器的隐状态中 。为了连续生成输出序列的词元,独立的循环神经网络解码器是基于输入序列的编码信息 和输出序列已经看见的或者生成的词元来预测下一个词元 。下图演示了 如何在机器翻译中使用两个循环神经网络进行序列到序列学习 。
在图中,特定的“”表示序列结束词元 。一旦输出序列生成此词元,模型就会停止预测 。在循环神经网络解码器的初始化时间步,有两个特定的设计决定: 首先,特定的“”表示序列开始词元,它是解码器的输入序列的第一个词元 。其次,使用循环神经网络编码器最终的隐状态来初始化解码器的隐状态 。例如,在 ( et al., 2014)的设计中,正是基于这种设计将输入序列的编码信息送入到解码器中来生成输出序列的 。在其他一些设计中 (Cho et al., 2014),如 图9.7.1所示,编码器最终的隐状态在每一个时间步都作为解码器的输入序列的一部分 。可以允许标签成为原始的输出序列,从源序列词元“”“Ils”“”“.” 到新序列词元 “Ils”“”“.”“”来移动预测的位置 。