【NLP】含注意力机制的Seq2Seq模型简介及代码示例

一. Seq2Seq模型

序列到序列(Sequence-to-Sequence,简称Seq2Seq)模型是一种深度学习架构,主要用于处理输入和输出都是变长序列的任务,例如机器翻译、文本摘要、语音识别转文字、聊天机器人对话等自然语言处理任务。Seq2Seq模型的核心思想是使用两个主要部分组成的神经网络框架:编码器(Encoder)和解码器(Decoder)。
seq2seq模型架构

1. 编码器(Encoder)

  • 职责是理解并捕获输入序列的语义信息。
  • 它通常由一个或多层循环神经网络(RNN模型,如LSTM或GRU)构成,也可以是Transformer等结构。
  • 输入序列按照时间步(或单词顺序)依次输入编码器,编码器在每次时间步都会更新其内部状态,最终输出一个固定长度的上下文向量(Context Vector)或一系列上下文向量(在使用双向RNN时会有前后向两个方向的信息),这个向量包含了输入序列的整体信息。

2. 解码器(Decoder)

  • 职责是依据编码器产生的上下文向量生成对应的输出序列。
  • 解码器也是一个RNN模型或使用更高级的Transformer模型,它的工作方式与编码器稍有不同。
  • 解码器首先初始化其隐藏状态,通常会利用编码器输出的、最终的隐藏层状态(last_hidden_state)作为起点。
  • 在生成序列的过程中,解码器每次输出一个元素后,会结合上一次的隐状态和当前时刻的输入(可能是先前生成的词或者特殊标记如起始符号)来更新自身的状态,并基于这个状态预测下一个输出符号的概率分布。

3. 模型训练过程

  • Seq2Seq模型在训练阶段,会根据输入序列和对应的期望输出序列进行学习,优化模型参数使得输出序列尽可能接近真实的目标序列。
  • 使用教师强制(Teacher Forcing)策略,即在训练时,即使模型预测错误,下一轮的输入也会使用正确的前一个预测值,而不是模型实际预测出的值。

二. 注意力机制在Seq2Seq模型中的应用

在Seq2Seq模型中,注意力机制通常被整合到解码器端的设计中,用来解决原始seq2seq模型在处理长输入序列时所遇到的问题:即解码器在生成每个输出元素时只能依赖于编码器输出的一个固定长度的上下文向量(通常是编码器最后一层的隐藏状态),这可能无法充分捕捉到输入序列的所有重要信息。

2.1 解码器端的注意力机制

在解码器端添加注意力机制后,解码器在生成每个输出词时能够动态地关注输入序列的不同部分。具体来说,解码器会在每一步生成过程中根据当前生成的状态和之前的上下文信息计算一个权重分布,这个分布代表了对输入序列各位置的关注程度。通过加权求和的方式,解码器可以根据这些权重实时重新组合编码器的所有隐藏状态,从而得到一个更灵活且针对当前生成步骤更有针对性的上下文向量。

2.2 编码器端的注意力机制

相比之下,将注意力机制放在编码器端并不常见,因为标准的seq2seq模型中编码器的主要职责是,尽可能完整地捕获输入序列的信息并将其压缩进一个或多个固定维度的向量中。如果要在编码器端引入注意力机制,可能是为了增强编码器内部不同时间步之间信息的交互或聚焦,但这并非注意力机制在seq2seq模型中最典型的应用场景。

然而,也有一些研究探索了在编码阶段使用注意力机制的方法,例如自注意力(self-attention,也称为内部注意力),这种机制允许输入序列内的各个元素相互比较和影响彼此的表示,这是Transformer模型等现代架构的核心组件。在这样的情况下,编码器端的注意力机制主要用于改进输入序列的编码过程,使其能够更加有效地提取全局依赖关系,而不是像解码器端那样用于动态参考输入序列。

总结来说,解码器端的注意力机制关注的是如何在生成输出时动态适应输入信息,而编码器端若采用注意力机制则更多是为了改进输入信息的编码质量或捕获输入序列内部复杂的依赖结构。

三. 代码示例

下面使用代码构建了一个由GRU编码器、含注意力的GRU解码器组成的Seq2Seq模型,用于完成机器翻译任务(N vs M类型):

3.1 Encoder部分

# 构建基于GRU的编码器
class GRU_Encoder(nn.Module):
    def __init__(self, vocab_size,embed_dim,hidden_size):
        super().__init__()
        # 初始化属性
        self.vocab_size = vocab_size  # 输入词汇总数
        self.embed_dim = embed_dim  # 输入词汇的词嵌入维度
        self.hidden_size = hidden_size  # 隐藏层向量维度
        # 实例化embed层
        self.embed = nn.Embedding(vocab_size, embed_dim)
        # 实例化GRU层
        self.gru = nn.GRU(embed_dim, hidden_size, num_layers=1, batch_first=True)
    def forward(self, input, hidden):
        # 输入数据经过embed层
        out_embed = self.embed(input)
        # embed处理后的数据经过GRU层
        output, hn = self.gru(out_embed, hidden)
        return output, hn

    def init_hidden(self):
    	# batch_size=1
        hidden = torch.zeros(1, 1, self.hidden_size)
        return hidden

3.2 含注意力的Decoder部分

# 构建加入attention的GRU解码器
class Attention_GRU_Decoder(nn.Module):
    def __init__(self,vocab_size,embed_dim,encoder_hidden_size,gru_hidden_size,max_length=10):
        super().__init__()
        # 定义一些属性:模型参数
        self.vocab_size = vocab_size                    # 输出词汇总数
        self.embed_dim= embed_dim                       # 输出词汇的词嵌入维度
        self.encoder_hidden_size = encoder_hidden_size  # encoder隐藏层张量维度
        self.gru_hidden_size = gru_hidden_size          # GRU层解码时的隐藏层张量维度,这里使用encoder的最终隐藏状态作为初始化s0
        self.max_length = max_length                    # 翻译语句的最大长度

        # 模型结构
        # 实例化embed层
        self.embed = nn.Embedding(vocab_size ,embed_dim)
        # droupout策略
        self.droupout = nn.Dropout(p=0.1)
        # 注意力计算第1步的线性层:Linear([Q,K])
        self.attn = nn.Linear(embed_dim + encoder_hidden_size,max_length)
        # 注意力计算第3步的线性层:对attn与Q拼接后的张量做线性变换,改变形状,得到对Q的注意力表示
        self.attn_combine = nn.Linear(embed_dim + encoder_hidden_size, gru_hidden_size)
        # 实例化GRU层
        self.gru = nn.GRU(gru_hidden_size,gru_hidden_size,num_layers=1,batch_first=True)
        # 实例化全连接层
        self.out = nn.Linear(gru_hidden_size,vocab_size)
        # 输出层out的softmax激活
        self.softmax = nn.LogSoftmax(dim=-1)
    # 前向传播:定义输入数据Q,K,V的计算过程
    def forward(self,input,hidden,encoder_output_c):
        # input=Q
        # hidden=K
        # encoder_ouput_c=V: 中间语义张量
        # 输入数据进入embed层
        input = self.embed(input)
        # droupout处理:缓解过拟合
        embedded = self.droupout(input)
        # 注意力分配系数计算
        # 1.与K拼接后,经过第一个线性层,再进行softmax激活
        attn_weights = F.softmax(self.attn(torch.cat((embedded[0],hidden[0]),dim=-1)),dim=-1)
        # 2.将attn_weights与V相乘
        attn_applied = torch.bmm(attn_weights.unsqueeze(0),encoder_output_c.unsqueeze(0))
        # 3.将attn_applied与Q拼接,经过线性层输出,准备送入GRU
        gru_input = self.attn_combine(torch.cat((attn_applied,input),dim=-1))
        # 进行relu激活
        gru_input = F.relu(gru_input)

        # gru模型
        gru_output, hn = self.gru(gru_input,hidden)
        # 对gru模型的输出进行分类: 经过out全连接层,并且对分类结果进行softmax激活
        output = self.softmax(self.out(gru_output[0]))
        return output, hn, attn_weights
    # GRU模型测隐藏状态初始化
    # 这里因为直接使用encoder最后输出的隐藏状态作为decoder的初始化隐藏状态,所以这里没有用到
    def init_hidden(self):
        hidden = torch.zeros(1, 1, self.hidden_size, device=device)
        return hidden

3.3 补充说明

上面的代码中,解码器部分使用的注意力机制为 “加型Attention”,除此之外还有一种常用的注意力机制为 “乘型Attention"。“加型Attention”的注意力计算规则如下:
第一步:
A t t e n t i o n ( Q , K , V ) = S o f t m a x ( L i n e a r ( [ Q , K ] ) ) ∗ V Attention(Q, K, V) = Softmax(Linear([Q, K])) * V Attention(Q,K,V)=Softmax(Linear([Q,K]))V
第二步:
Q Q Q 与第一步的计算结果进行拼接。

  • 22
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 基于注意力机制seq2seq模型是在普通seq2seq模型的基础上增加了一种注意力机制来提高模型的效果。 优势: 1. 能够自动学习哪些部分对于预测结果更重要,并为其分配更多的权重。 2. 可以处理句子长度较长的问题,因为它不再依赖于固定的固定长度的编码器和解码器。 3. 能够解决普通seq2seq模型中出现的较差的翻译结果问题。 突出点: 1. 对于长度较长的句子能够很好的维持翻译质量 2. 不容易陷入局部最优,能够较好的处理不完整的信息 3. 在翻译、语音识别、问答等领域都有广泛应用 ### 回答2: 基于注意力机制seq2seq模型相比于普通的seq2seq模型具有很多优势和突出点。 首先,普通的seq2seq模型在生成目标序列时,将源序列信息压缩成一个固定长度的向量作为输入。这个输入向量需要承担所有源序列信息的责任,可能导致信息的丢失或混淆。而基于注意力机制seq2seq模型通过引入注意力机制,可以动态地根据输入序列的不同部分赋予不同的权重,从而更好地捕捉源序列的相关信息。 其次,基于注意力机制seq2seq模型具有更好的对齐能力。普通的seq2seq模型在编码阶段将所有源序列信息转化为一个固定长度的向量,难以处理长度不一致或有较大偏移的输入序列。而引入注意力机制后,模型可以在解码阶段对源序列的不同部分进行不同程度的关注,从而更好地适应不同长度或偏移的输入序列。 此外,基于注意力机制seq2seq模型也能够更好地处理长序列。普通的seq2seq模型在生成长序列时,由于编码阶段只将信息压缩为一个向量,可能导致长期依赖问题和信息的衰减。而基于注意力机制seq2seq模型可以通过不同阶段的注意力分配,更好地维持长序列中的信息,增强了序列到序列模型的记忆能力。 综上所述,基于注意力机制seq2seq模型通过动态分配注意力权重,具有更好的信息抓取能力、对齐能力和长序列处理能力。这使得基于注意力机制seq2seq模型机器翻译、文本摘要、语音识别等任务中取得了更好的性能和效果,成为自然语言处理领域中的研究热点和突出方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值