Transformer模型demo实现

我来详细对比TransformerDiffusion两种中央深度学习模型

1 基本概念对比

特性

Transformer

Diffusion

模型类型

判别式模型

生成模型

主要应用

NLP,CV 序列建模

图像生成音频生成数据合成

核心思想

注意力机制

渐进式去噪过程

2 架构对比

Transformer架构核心

import torch
import torch.nn as nn
import math
class TransformerBlock(nn.Module):
//Transformer基础
    def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):
        super().__init__()
        #自注意力机制
        self.self_attn = nn.MultiheadAttention(d_mode, nhead, dropout=dropout)
        #前馈神经网络
        self.linear1 = nn.Linear(d_model, dim_feedforward)
        self.linear2 = nn.Linear(dim_feedforward, d_model)
        
        #归一化
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout = nn.Dropout(dropout)
        self.activeation = nn.ReLU()
        
def forward(self, src):
    #注意力 + 参差链接 + 归一化
    src2 = self.self_attn(src, src, src)[0]
    src = self.norm1(src + self.dropout(src2))
    
    #前馈网络 + 参差链接 + 归一化
    src2 = self.linear2(self.dropout(self.activeation(self.linear1(src))))
    src = self.norm2(src + self.dropout(src2))
    return src

Diffusion 架构核心

#导入torch这是主要深度学习框架
import torch
#导入torch.nn模块包含了构建神经网络所需各种类Module, Linear
import torch.nn as nn
#导入math用于数学运算开方对数
import math
#定义位置编码继承nn.Module,使其成为一个Pytorch模块
class PositionalEncoding(nn.Module):
/*
位置编码-为输入序列添加位置信息
Transformer本身没有位置信息需要额外添加
*/

#初始化方法定义模型结构
def __init__(self, d_model, max_len=5000):
#调用父类nn.Module初始化方法
    super(PositionalEncoding, self).__init__()
    #创建一个全零张量形状(最大序列长度,模型特征维度)用于存储位置编码
    pe = torch.zeros(max_len, d_model)
    #生成一个0max_len - 1序列转换服点类型然后增加一个维度使其变为向量
    position - torch.arange(0, max_len, dtype=torch)
    #计算位置编码公式中的除数目的是为不同维度生成不同频率
    #torch.arange(0, d_model, 2) 生成偶数索引[0,2,4,...,d_model-2]
    #公式 exp(-log(10000)/d_model * i) 其中i维度索引
    div_term = torch.exp(torch.aragen(0, d_model, 2).float() * (-math.log(10000)/d_model))
    #偶数维度位置(0,2,4...)使用正弦函数计算位置编码
    pe[:,0::2] = torch.sin(position * div_term) #切片[:,0::2]表示所有0开始步长2
    #奇数维度位置(1,3,5...)使用余弦函数计算位置编码
    pe[:,1::2] = torch.cos(position * div_term) #切片 [:,1::2]表示所有行1开始步长2
    #位置编码张量增加维度转置使其形状(max_len, d_model)变为(max_len, 1, d_model)
    #这样便于后续输入张量进行广播相加
    pe = pe.unsqueeze(0).transpose(0,1)
    #位置编码张量注册模型缓冲区buffer缓冲区模型一部分模型保存加载
    #不被视为可训练参数 既不参与梯度下降更新
    self.register_buffer('pe', pe)
    
#定义前向传播方法描述数据如何通过模块
def forward(self, x):
    #x (seq_len, batch_size, d_model)
    #将位置编码输入张量slef.pe[:x.size(0),:]seq_len位置编码
    #Pytorch自动进行广播位置编码每个batch每个序列位置上
    x = x + self.pe[:x.size(0),:]
    #返回添加了位置信息张量
    return x
#定义简单Transformer编码器模型用于序列分类
class SimpleTransformer(nn.Module):
/*
简单Transformer模型用于序列分类任务    
*/
def __init__(self, input_size, d_model, nhead, nunm_layers, num_classes, max_len=100):
    #调用父类初始化
    super(SimpleTransformer, self).__init__()
    #模型特征维度保存为实例变量后续使用
    self.d_model = d_model
    
    #定义输入嵌入层一个线性输入特征维度input_size)映射模型特征维度d_model
    self.embedding = nn.Linear(input_size, d_model)
    #实例化位置编码层
    self.pos_encoder = PositionalEncoding(d_model, max_len)
    #创建一个Transformer编码器构成Transformer堆叠块基本单元
    encoder_layer = nn.TransformerENcoderLayer(
        d_model = d_model, #输入输出特征维度
        nhead = nhead, #多头注意力机制中头的数量
        dim_feedforward=512, #前馈神经网络中间层维度
        dropout=0.1 #dropout概率用于防止过拟合
        activation='relu' #前馈神经网络中使用激活函数
    )
    #创建完整Transformer编码器多个NUM_LAYERS上述编码器堆叠而成
    self.transformer_encoder = nn.TransformerEncoder(
        encoder_layer,
        num_layers=num_layers #堆叠层数
    )
#定义分类一个线性Transformer输出的特征d_model映射类别数量num_classes 
    self.classifier=nn.Linear(d_model, num_classes)
    #定义Dropout层, 分类随机丢弃一部分神经增强泛化能力
    self.dropout = nn.Dropout(0.3)
#定义前向传播
def forward(self, x):
    #x输入形状, batch_size, seq_len, input_size
    #获取输入张量批量大小徐磊长度下划线表示忽略特征维度Input_size
    batch_size, seq_len, _ = x.shape
    #通过嵌入层输入特征投影d_model维度
    x = self.embedding(x * math.sqrt(self.d_model) #乘以sqrt(d_model)是对嵌入进行缩放,有助于稳定训练
    #调整张量维度顺序PyTorchTransformer模块期望输入形状seq_len, batch_size, d_model
    x = x.transpose(0, 1)
    #为序列添加位置编码信息
    x = self.pos_encoder(x)
    #数据通过堆叠Transformer编码器进行处理
    #注意输入形状(seq_len,batch_size, d_model)
    x = self.transformer_encoder(x)
    #输出x形状仍为(seq_len, batch_size,d_model)
    #输出序列中第一个位置 索引0 特征向量作为整个序列聚合表示
    #这类似于BERT[CLS]token, 常用分类任务
    x=x[0,:,:]#输出形状变为 batch_size, d_model
    #应用Dropout
    x = self.dropout(x)
    #通过分类器线性得到最终分类分数logits
    x = self.classifier(x)
    #返回输出形状为batch_size, num_classes
    return x
    
#定义序列序列Seq2SeqTransformer模型常用于机器翻译任务
class TransformerForSequenceToSequence(nn.Module):
/*
序列序列Transformer模型 机器翻译
*/            
def __init__(self, src_vocab_size, tgt_vocab_size, d_model, nhead, num_layers):
    super(TransformerForSequenceToSequence, self).__init__()
    #编码器部分
    #源语言词嵌入层语言词汇索引映射d_model向量
    self.encoder_embedding = nn.Embedding(src_vocab_size, d_model)
    #编码器位置编码
    self.pos_encoder = PositionalEncoding(d_model)
    #创建编码器
    encoder_layer = nn.TransformerEncoderLayer(d_model, nhead, 512, 0.1)
    #创建堆叠编码器
    self.encoder = nn.TransformerEncoder(encoder_layer, num_layers)
    #解码器部分
    #目标语言词嵌入层,将目标语言词汇索引映射d_model向量
    self.decoder_embedding = nn.Embedding(tgt_vocab_size, d_model)
    #解码器位置编码
    self.pos_decoder = PositionalEncoding(d_model)
    #创建解码器
    decoder_layer = nn.TransformerDecoderLayer(d_model, nhead, 512, 0.1)
    #创建堆叠解码器
    self.decoder = nn.TransformerDecoder(decoder_layer, num_layers)
    #输出层一个线性解码器输出d_model向量映射目标语言词汇表大小
    #得到每个位置每个词概率
    self.output_layer = nn.Linear(d_model, tgt_vocab_size)
    
def forward(self, src, tgt):
#src 语言序列形状通常seq_len, batch_size
#tgt 目标语言序列形状通常为seq_len, batch_size
#编码器前向传播
#原序列进行嵌入闭并缩放
src_embed = self.encoder_embedding(src) * math.sqrt(self.d_model)
#添加位置编码
src_embed=self.pos_encoder(src_embed)
#通过编码器得到记忆memory,解码器生成时关注
memory = self.encoder(src_embed)
#输出形状src_seq_len, batch_size, d_model
#解码器前向传播
#目标序列进行嵌入缩放注意在训练时tgt完整目标序列偏移
tgt_embed = self.decoder_embedding(tgt) * math.sqrt(self.d_model)
#添加位置编码
tgt_embed = self.pos_decoder(tgt_embed)
#解码器前向传播接收
#1 tgt_embed 目标序列嵌入自注意力部分关注自身历史信息
#2 memory 编码器输出 交叉注意力部分关注语言信息
output = self.decoder(tgt_embed, memory)#输出形状
#输出层
#解码器输出每个位置向量映射词汇表维度得到每个词分数
output = self.output_layer(output) #输出形状tgt_seq_len, batch_size, tgt_vocab_size
return output

#定义演示函数展示如何使用SimpleTransformer模型
def demo_transformer():
#参数设置
    batch_szie=32 #批量大小即一次处理多少样本
    seq_len = 20 #每个样本序列长度
    input_size=16 #输入数据原始特征维度
    d_model=128 #Transformer内部特征维度 模型宽度
    nhead=8 #多头注意力中数量
    num_layers=3 #Transforerm编码器堆叠层数 模型深度
    num_classes = 5 #分类任务类别
    #实例化SimpleTransformer模型
    model = SimpleTransformer(input_size, d_model, nhead, num_layers, num_classes)
    #模拟 随机生成 -一批输入数据
    #形状 batch_size, seq_len, input_size
    x = torch.randn(batch_size, seq_len, input_size)
    
    #输入数据传入模型进行前向传播得到输出
    output = model(x)
    #打印输入和输出张量形状, 便于理解数据
    #返回模型输出外部可能进一步使用
    return mdel, output
#程序入口如果直接运行脚本则执行演示函数
if __name__ == '__main__':
    #运行Transformer示例获取模型输出
    transformer_model, transformer_output = demo_transformer()    
    

    

    

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值