小熊科技|PyTorch文本:01.聊天机器人教程( 六 )


Sutskever et al.发现通过一起使用两个独立的RNN , 我们可以完成这项任务 。 第一个RNN充当编码 器 , 其将可变长度输入序列编码为固定长度上下文向量 。 理论上 , 该上下文向量(RNN的最终隐藏层)将包含关于输入到机器人的查询语句的 语义信息 。 第二个RNN是一个解码器 , 它接收输入文字和上下文矢量 , 并返回序列中下一句文字的概率和在下一次迭代中使用的隐藏状态 。
小熊科技|PyTorch文本:01.聊天机器人教程图片来源:
4.2 编码器编码器RNN每次迭代中输入一个语句输出一个token(例如 , 一个单词) , 同时在这时间内输出“输出”向量和“隐藏状态”向量 。 然后将隐藏 状态向量传递到下一步 , 并记录输出向量 。 编码器将其在序列中的每一点处看到的上下文转换为高维空间中的一系列点 , 解码器将使用这些点 为给定任务生成有意义的输出 。
我们的编码器的核心是由Cho et al.等人发明的多层门循环单元 。 在2014年 , 我们将使用 GRU的双向变体 , 这意味着基本上有两个独立的RNN:一个以正常的顺序输入输入序列 , 另一个以相反的顺序输入输入序列 。 每个网络的输出在 每个时间步骤求和 。 使用双向GRU将为我们提供编码过去和未来上下文的优势 。
双向RNN:
小熊科技|PyTorch文本:01.聊天机器人教程图片来源:
注意:embedding层用于在任意大小的特征空间中对我们的单词索引进行编码 。 对于我们的模型 , 此图层会将每个单词映射到大小为hidden_size的特征空间 。 训练后 , 这些值会被编码成和他们相似的有意义词语 。
最后 , 如果将填充的一批序列传递给RNN模块 , 我们必须分别使用torch.nn.utils.rnn.pack_padded_sequence和torch.nn.utils.rnn.pad_packed_sequence 在RNN传递时分别进行填充和反填充 。
计算图
1.将单词索引转换为词嵌入 embeddings 。
2.为RNN模块打包填充batch序列 。
3.通过GRU进行前向传播 。
4.反填充 。
5.对双向GRU输出求和 。
6.返回输出和最终隐藏状态 。
输入
input_seq:一批输入句子; shape =(max_length , batch_size
input_lengths:batch中每个句子对应的句子长度列表;shape=(batch_size)
hidden:隐藏状态;shape =(n_layers x num_directions , batch_size , hidden_size)
输出
outputs:GRU最后一个隐藏层的输出特征(双向输出之和);shape =(max_length , batch_size , hidden_size)hidden:从GRU更新隐藏状态;shape =(n_layers x num_directions , batch_size , hidden_size)class EncoderRNN(nn.Module):def __init__(self, hidden_size, embedding, n_layers=1, dropout=0):super(EncoderRNN, self).__init__()self.n_layers = n_layersself.hidden_size = hidden_sizeself.embedding = embedding# 初始化GRU; input_size和hidden_size参数都设置为'hidden_size'# 因为我们的输入大小是一个嵌入了多个特征的单词== hidden_sizeself.gru = nn.GRU(hidden_size, hidden_size, n_layers,dropout=(0 if n_layers == 1 else dropout), bidirectional=True)def forward(self, input_seq, input_lengths, hidden=None):# 将单词索引转换为词向量embedded = self.embedding(input_seq)# 为RNN模块打包填充batch序列packed = nn.utils.rnn.pack_padded_sequence(embedded, input_lengths)# 正向通过GRUoutputs, hidden = self.gru(packed, hidden)# 打开填充outputs, _ = nn.utils.rnn.pad_packed_sequence(outputs)# 总和双向GRU输出outputs = outputs[:, :, :self.hidden_size] + outputs[:, : ,self.hidden_size:]# 返回输出和最终隐藏状态return outputs, hidden


推荐阅读