transformer--解码器

在编码器中实现了编码器的各种组件,其实解码器中使用的也是这些组件,如下图:

解码器组成部分:

  1. 由N个解码器层堆叠而成
  2. 每个解码器层由三个子层连接结构组成
  3. 第一个子层连接结构包括一个多头自注意力子层和规范化层以及一个残差连接
  4. 第二个子层连接结构包括一个多头注意力子层和规范化层以及一个残差连接
  5. 第三个子层连接结构包括一个前馈全连接子层和规范化层以及一个残差连接 

解码器层code

# 解码器层的类实现
class DecoderLayer(nn.Module):
    def __init__(self, size, self_attn, src_attn, feed_forward,dropout) -> None:
        """
        size : 词嵌入维度
        self_attn:多头自注意对象,需要Q=K=V
        src_attn:多头注意力对象,这里Q!=K=V
        feed_forward: 前馈全连接层对象
        """
        super(DecoderLayer,self).__init__()

        self.size = size
        self.self_attn = self_attn
        self.src_attn = src_attn
        self.feed_forward = feed_forward
        # 根据论文图使用clones克隆三个子层对象
        self.sublayer = clones(SublayerConnection(size,dropout), 3)

    def forward(self, x, memory, source_mask, target_mask):
        """
        x : 上一层的输入
        memory: 来自编码器层的语义存储变量
        source_mask: 源码数据掩码张量,针对就是输入到解码器的数据
        target_mask: 目标数据掩码张量,针对解码器最后生成的数据,一个一个的推理生成的词
        """

        m = memory

        # 将x传入第一个子层结构,第一个子层结构输入分别是x和self_attn函数,因为是自注意力机制,所以Q=K=V=x
        # 最后一个参数是目标数据掩码张量,这时要对目标数据进行掩码,因为此时模型可能还没有生成任何目标数据,
        # 比如在解码器准备生成第一个字符或词汇时,我们其实已经传入第一个字符以便计算损失
        # 但是我们不希望在生成第一个字符时模型能利用这个信息,因为我们会将其遮掩,同样生成第二个字符或词汇时
        # 模型只能使用第一个字符或词汇信息,第二个字符以及以后得信息都不允许被模型使用
        x = self.sublayer[0](x, lambda x: self.self_attn(x,x,x,target_mask))

        # 紧接着第一层的输出进入第二个子层,这个子层是常规的注意力机制,但是q是输入x;k、v是编码层输出memory
        # 同样也传入source_mask, 但是进行源数据遮掩的原因并非是抑制信息泄露,而是遮蔽掉对结果没有意义的的字符而产生的注意力
        # 以此提升模型的效果和训练速度,这样就完成第二个子层的处理
        x = self.sublayer[1](x, lambda x: self.src_attn(x,m,m,source_mask))

        # 最后一个子层就是前馈全连接子层,经过他的处理后就可以返回结果,这就是解码器层的结构
        return self.sublayer[2](x,self.feed_forward)

测试代码全放到最后

测试结果:

embr.shape =  torch.Size([2, 4, 512])
pe_result.shape =  torch.Size([2, 4, 512])
en_result.shape :  torch.Size([2, 4, 512])
en_result :  tensor([[[-1.039
### Transformer 编码器-解码器架构详解 #### 概述 Transformer 是一种基于注意力机制的神经网络模型,专为处理序列数据而设计。该架构由编码器和解码器两部分构成,在机器翻译等任务中表现出色[^1]。 #### 编码器结构 编码器负责接收输入序列并将其转换成上下文表示向量。具体来说: - **嵌入 (Embedding Layer)** 输入序列中的每个词会被映射到高维空间中的稠密向量形式。为了保留位置信息,还会加入位置编码(Position Encoding),使得模型能够区分不同顺序下的相同词语组合[^4]。 ```python import torch.nn as nn class Embeddings(nn.Module): def __init__(self, d_model, vocab_size): super(Embeddings, self).__init__() self.lut = nn.Embedding(vocab_size, d_model) self.d_model = d_model def forward(self, x): return self.lut(x) * math.sqrt(self.d_model) def positional_encoding(max_len, d_model): pe = torch.zeros(max_len, d_model) position = torch.arange(0., max_len).unsqueeze(1) div_term = torch.exp(torch.arange(0., d_model, 2) * -(math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) return pe.unsqueeze(0) ``` - **多头自注意模块 (Multi-head Self-attention Module)** 自注意力机制允许模型关注整个句子的不同部分,从而更好地理解语义关系。通过多个平行运行的关注头可以捕捉更丰富的特征模式。 - **前馈全连接 (Feed-forward Neural Network Layers)** 经过自注意力计算后的输出会经过两个线性变换以及ReLU激活函数组成的简单MLP进一步加工处理[^3]。 #### 解码器结构 解码器的任务是从编码器产生的中间表征重建目标序列。其工作方式类似于编码器,但在每一步都会额外考虑之前已生成的内容作为条件约束: - **掩蔽多头自注意子 (Masked Multi-head Self-Attention Sublayer)** 这里采用了一种特殊的“未来遮挡”策略来防止当前位置看到后续的信息,保证预测过程符合因果律[^2]。 - **跨编码器-解码器注意力子 (Encoder-Decoder Cross Attention Sub-layer)** 利用来自编码端的状态指导当前时刻应该聚焦哪些源侧元素上,实现有效的信息传递。 - **最终投影与Softmax操作** 将最后一轮FFN的结果投射回词汇表维度,并应用softmax得到概率分布用于采样下一个token。 #### 总结 整体来看,Transformer 的 Encoder-Decoder 结构不仅简化了传统 RNN/LSTM 类方法中存在的梯度消失等问题,还凭借强大的全局依赖建模能力成为自然语言处理领域的重要里程碑之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值