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


encoder = Seq2SeqEncoder(vocab_size=10, embed_size=8, num_hiddens=16,num_layers=2)encoder.eval()X = torch.zeros((4, 7), dtype=torch.long)output, state = encoder(X)output.shape
嵌入层
在自然语言处理中,嵌入层( Layer)是用于将离散的词汇或字符映射为连续的向量表示的一种常用技术 。嵌入层可以将每个词或字符表示成一个固定长度的向量,这些向量通常被称为嵌入向量或词向量(Word ) 。嵌入向量可以捕捉词汇或字符之间的语义和关联关系,并且可以作为神经网络模型的输入 。
在中,nn.是一个内置的嵌入层类,它可以将整数编码的词汇或字符映射为连续的向量 。nn.的输入是一个形状为(, )的张量,其中每个元素都是一个整数,表示词汇或字符的索引 。nn.的输出是一个形状为(, , )的张量,其中每个元素都是一个向量,表示词汇或字符的嵌入向量 。是指定的嵌入向量的维度 。
在上面的代码中,nn.被用于创建一个嵌入层,将一个大小为的词汇表中的单词编码为一个维的向量表示 。在的方法中,输入序列X被传递到嵌入层中,以便将每个单词的索引编码成一个嵌入向量 。输出的张量形状为(, , ),其中是序列的时间步数,是序列的批量大小 。
嵌入层的实现方式很简单,可以使用一个权重矩阵E ∈ R v × d E \in \{R}^{v \times d} E∈Rv×d,将每个输入单词x i x_i xi? 映射为其对应的嵌入向量e i ∈ R d e_i \in \{R}^d ei?∈Rd 。具体来说,给定一个大小为n × m n \times m n×m 的输入矩阵X X X,其中n n n 表示样本数量,m m m 表示输入的长度,那么嵌入层的输出矩阵E ∈ R n × m × d E \in \{R}^{n \times m \times d} E∈Rn×m×d 可以通过以下方式计算:
E i , j , : = E X i , j E_{i,j,:} = E_{X_{i,j}} Ei,j,:?=EXi,j??
其中E i , j , : E_{i,j,:} Ei,j,:? 表示输出矩阵E E E 中第i i i 个样本、第j j j 个输入位置对应的嵌入向量,X i , j X_{i,j} Xi,j? 表示输入矩阵X X X 中第i i i 个样本、第j j j 个位置对应的单词索引 。
这个公式是在嵌入层中使用的 。假设 E E E是一个形状为 ( V , d ) (V,d) (V,d)的张量,其中 V V V是词汇表的大小,d d d是嵌入向量的维度 。X X X是一个形状为 ( n , m ) (n,m) (n,m)的整数张量,其中 n n n是批量大小,m m m是序列长度 。那么 E i , j , : E_{i,j,:} Ei,j,:?表示词汇表中索引为 X i , j X_{i,j} Xi,j?的单词的嵌入向量 。其中 i i i表示批量中的样本索引,j j j表示序列中的位置索引 。因此,该公式的含义是:对于批量中的第 i i i个样本和序列中的第 j j j个位置,嵌入层将单词的索引 X i , j X_{i,j} Xi,j?转换为该单词的嵌入向量 E X i , j E_{X_{i,j}} EXi,j?? 。
在深度学习模型中,嵌入层通常作为模型的第一层 。在模型的训练过程中,嵌入层的权重矩阵可以通过反向传播进行更新,以最小化模型的损失函数 。同时,在测试时,可以使用预训练的嵌入层,将输入转换为向量表示,然后将其输入到模型中进行预测 。
解码器
class Seq2SeqDecoder(Decoder):"""用于序列到序列学习的循环神经网络解码器"""def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,dropout=0, **kwargs):super(Seq2SeqDecoder, self).__init__(**kwargs)self.embedding = nn.Embedding(vocab_size, embed_size)self.rnn = nn.GRU(embed_size + num_hiddens, num_hiddens, num_layers,dropout=dropout)self.dense = nn.Linear(num_hiddens, vocab_size)def init_state(self, enc_outputs, *args):return enc_outputs[1]def forward(self, X, state):# 输出'X'的形状:(batch_size,num_steps,embed_size)X = self.embedding(X).permute(1, 0, 2)# 广播context,使其具有与X相同的num_stepscontext = state[-1].repeat(X.shape[0], 1, 1)X_and_context = torch.cat((X, context), 2)output, state = self.rnn(X_and_context, state)output = self.dense(output).permute(1, 0, 2)# output的形状:(batch_size,num_steps,vocab_size)# state的形状:(num_layers,batch_size,num_hiddens)return output, state