transformer-实现transformer架构

Transformer

  • https://arxiv.org/pdf/1706.03762

    https://arxiv.org/pdf/1706.03762

Transformer结构介绍

  • Transformer是一种基于自注意力机制的神经网络架构,用于序列到序列的转换任务。它由编码器(Encoder)和解码器(Decoder)两部分组成,通过自注意力机制实现对输入和输出序列的有效建模。

    image-20250430140118616

    这里实现完整的Transformer结构,包含编码器和解码器

    主要组件包含:

    1. 编码器(Encoder):处理输入序列并生成上下文表示
    2. 解码器(Decoder):基于编码器输出和已生成的序列预测下一个token
    3. 线性层:将解码器输出映射到目标词表空间

    最后的softmax因为一般都包含在损失函数中计算所有可实现可不实现,不重要


数学流程

  • Transformer的计算过程可形式化为:
    Encoder Output : H e n c = Encoder ( X s r c ) Decoder Output : H d e c = Decoder ( Y d s t , H e n c ) Final Output : P ( y ) = Softmax ( Linear ( H d e c ) ) \begin{aligned} \text{Encoder Output} &: H_{enc} = \text{Encoder}(X_{src}) \\ \text{Decoder Output} &: H_{dec} = \text{Decoder}(Y_{dst}, H_{enc}) \\ \text{Final Output} &: P(y) = \text{Softmax}(\text{Linear}(H_{dec})) \end{aligned} Encoder OutputDecoder OutputFinal Output:Henc=Encoder(Xsrc):Hdec=Decoder(Ydst,Henc):P(y)=Softmax(Linear(Hdec))
    其中:

    1. 编码器处理源序列生成上下文表示
    2. 解码器结合编码器输出和目标序列进行自回归生成
    3. 线性层将解码器输出映射到词表维度,通过Softmax得到概率分布

代码实现

  • 其他层的实现

    层名链接
    PositionEncodinghttps://blog.csdn.net/hbkybkzw/article/details/147431820
    calculate_attentionhttps://blog.csdn.net/hbkybkzw/article/details/147462845
    MultiHeadAttentionhttps://blog.csdn.net/hbkybkzw/article/details/147490387
    FeedForwardhttps://blog.csdn.net/hbkybkzw/article/details/147515883
    LayerNormhttps://blog.csdn.net/hbkybkzw/article/details/147516529
    EncoderLayerhttps://blog.csdn.net/hbkybkzw/article/details/147591824
    Encoderhttps://blog.csdn.net/hbkybkzw/article/details/147616115
    DecoderLayerhttps://blog.csdn.net/hbkybkzw/article/details/147616556
    Decoderhttps://blog.csdn.net/hbkybkzw/article/details/147628354

    下面统一在before.py中导入

  • 实现 Transformer 模型

    import torch
    from torch import nn
    
    from before import Encoder, Decoder
    
    
    class Transformer(nn.Module):
        def __init__(self, encode_vocab_size, decode_vocab_size, padding_idx, d_model,
                     n_heads, ffn_hidden, dropout_prob=0.1, num_layers=6, max_seq_len=512):
            super(Transformer, self).__init__()
            
            # 编码器:处理输入序列
            self.encoder = Encoder(
                vocab_size=encode_vocab_size, 
                padding_idx=padding_idx, 
                d_model=d_model, 
                n_heads=n_heads,
                ffn_hidden=ffn_hidden, 
                dropout_prob=dropout_prob, 
                num_layers=num_layers, 
                max_seq_len=max_seq_len
            )
            
            # 解码器:生成输出序列
            self.decoder = Decoder(
                vocab_size=decode_vocab_size, 
                padding_idx=padding_idx, 
                d_model=d_model, 
                n_heads=n_heads,
                ffn_hidden=ffn_hidden, 
                dropout_prob=dropout_prob, 
                num_layers=num_layers, 
                max_seq_len=max_seq_len
            )
            
            # 输出线性层:映射到目标词表空间
            self.linear = nn.Linear(in_features=d_model, out_features=decode_vocab_size)
            
            self.padding_idx = padding_idx
    
        def generate_mask(self, query, key, is_triu_mask=False):
            """
            生成注意力掩码矩阵
            shape of query,key: [batch_size,seq_len]
            """
            device = query.device
            batch, seq_q = query.shape
            _, seq_k = key.shape
    
            # 创建padding掩码
            mask = (key == self.padding_idx)
            mask = mask.unsqueeze(1).unsqueeze(2)  # [batch,1,1,seq_k]
            mask = mask.expand(batch, 1, seq_q, seq_k).to(device)
            
            # 创建前瞻掩码(解码器中使用)
            if is_triu_mask:
                dst_triu_mask = torch.triu(
                    torch.ones(seq_q, seq_k, dtype=torch.bool),
                    diagonal=1  # 需要往右移动一个,因为第一个单词是开始字符
                )  # [seq_q,seq_k]
                dst_triu_mask = dst_triu_mask.unsqueeze(0).unsqueeze(1).expand(
                    batch, 1, seq_q, seq_k
                ).to(device)
                return mask | dst_triu_mask  # 取并集
                
            return mask
    
        def forward(self, src, dst):
            """
            前向传播过程
            :param src: encoder部分的输入
            :param dst: decoder部分的输出
            """
            # 生成编码器的padding掩码
            src_mask = self.generate_mask(src, src)
            
            # 编码器前向传播
            encoder_out = self.encoder(src, src_mask=src_mask)
            
            # 生成解码器的掩码(包含padding掩码和前瞻掩码)
            dst_mask = self.generate_mask(dst, dst, is_triu_mask=True)
            
            # 生成编码器-解码器的掩码
            src_dst_mask = self.generate_mask(dst, src)
            
            # 解码器前向传播
            decode_out = self.decoder(
                dst, 
                encoder_kv=encoder_out, 
                dst_mask=dst_mask, 
                src_dst_mask=src_dst_mask
            )
            
            # 线性层映射到词表空间
            output = self.linear(decode_out)
    
            return output
    

    关键组件说明

    1. 编码器(Encoder):处理输入序列,生成上下文表示
    2. 解码器(Decoder):结合编码器输出和已生成序列,预测下一个token
    3. 掩码生成(generate_mask):创建三种掩码:
      • 编码器padding掩码:屏蔽填充位置
      • 解码器padding+前瞻掩码:屏蔽填充位置和未来位置
      • 编码器-解码器掩码:屏蔽编码器输出中的填充位置
    4. 线性层:将解码器输出映射到目标词表维度
  • 维度变化

    处理阶段张量形状变化示例
    源序列输入[batch_size, src_seq_len]
    目标序列输入[batch_size, dst_seq_len]
    编码器输出[batch_size, src_seq_len, d_model]
    解码器输出[batch_size, dst_seq_len, d_model]
    线性层输出[batch_size, dst_seq_len, decode_vocab_size]

使用示例

  • 测试用例

    if __name__ == "__main__":
        # 模拟输入:batch_size=4,源序列长度64,目标序列长度32
        src = torch.randint(0, 1000, (4, 64))
        dst = torch.randint(0, 1000, (4, 32))
        
        # 实例化Transformer:源词表1000,目标词表1000,模型维度512,8头,2048前馈维度
        transformer = Transformer(
            encode_vocab_size=1000,
            decode_vocab_size=1000,
            padding_idx=0,
            d_model=512,
            n_heads=8,
            ffn_hidden=2048,
            num_layers=6
        )
        
        # 前向传播
        output = transformer(src, dst)
        
        # 输出形状检查
        print(f"输出形状: {output.shape}")  # 预期: [4, 32, 1000]
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值