transformer口语化解析

Transformer 是一种基于自注意力机制的深度神经网络模型,常用于处理序列到序列的任务,例如机器翻译、文本摘要、问答系统等。它由 Encoder 和 Decoder 两个主要部分组成,每个部分包含多个相同的 Block。

Transformer 结构图

Transformer 结构

python 复制代码
import torch
import torch.nn as nn

# 定义位置编码类
class PositionalEncoding(nn.Module):
    def __init__(self, d_model, max_len=5000):
        """
        初始化位置编码器。
        
        参数:
        - d_model: 模型维度
        - max_len: 序列的最大长度
        """
        super(PositionalEncoding, self).__init__()
        # 创建一个零张量来存储位置编码
        pe = torch.zeros(max_len, d_model)
        # 生成位置索引张量
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        # 计算除数项
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-torch.log(torch.tensor(10000.0)) / d_model))
        # 填充位置编码张量中的奇数和偶数位置
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        # 添加批次维度并转置以匹配输入形状
        pe = pe.unsqueeze(0).transpose(0, 1)
        # 将位置编码注册为缓冲区,使其不被视为模型参数
        self.register_buffer('pe', pe)

    def forward(self, x):
        """
        在输入序列上应用位置编码。
        
        参数:
        - x: 输入张量,形状为 (seq_len, batch_size, d_model)
        
        返回:
        - 加上位置编码后的输入张量
        """
        x = x + self.pe[:x.size(0), :]
        return x

# 定义Transformer模型类
class Transformer(nn.Module):
    def __init__(self, encoder, decoder, src_vocab_size, tgt_vocab_size, src_pad_idx, tgt_pad_idx, device, d_model):
        """
        初始化Transformer模型。
        
        参数:
        - encoder: 编码器层
        - decoder: 解码器层
        - src_vocab_size: 源语言词汇表大小
        - tgt_vocab_size: 目标语言词汇表大小
        - src_pad_idx: 源语言填充标记索引
        - tgt_pad_idx: 目标语言填充标记索引
        - device: 设备类型(CPU/GPU)
        - d_model: 模型维度
        """
        super(Transformer, self).__init__()
        self.encoder = encoder
        self.decoder = decoder
        self.src_pad_idx = src_pad_idx
        self.tgt_pad_idx = tgt_pad_idx
        self.device = device
        # 初始化源语言词嵌入层
        self.src_token_embedding = nn.Embedding(src_vocab_size, d_model)
        # 初始化目标语言词嵌入层
        self.tgt_token_embedding = nn.Embedding(tgt_vocab_size, d_model)
        # 初始化位置编码器
        self.position_embedding = PositionalEncoding(d_model)
        self.src_mask = None
        self.tgt_mask = None

    def forward(self, src, tgt):
        """
        执行Transformer模型的前向传播。
        
        参数:
        - src: 源语言输入序列,形状为 (src_seq_len, batch_size)
        - tgt: 目标语言输入序列,形状为 (tgt_seq_len, batch_size)
        
        返回:
        - 解码器输出,形状为 (tgt_seq_len, batch_size, tgt_vocab_size)
        """
        # 创建源语言和目标语言的掩码
        src_mask = self.create_padding_mask(src, self.src_pad_idx)
        tgt_mask = self.create_padding_mask(tgt, self.tgt_pad_idx)
        # 对源语言输入进行编码
        memory = self.encoder(self.src_token_embedding(src) + self.position_embedding(src), src_mask)
        # 对目标语言输入进行解码
        outs = self.decoder(self.tgt_token_embedding(tgt) + self.position_embedding(tgt), memory, tgt_mask)
        return outs

    def create_padding_mask(self, src, pad_idx):
        """
        创建填充掩码。
        
        参数:
        - src: 输入序列,形状为 (seq_len, batch_size)
        - pad_idx: 填充标记索引
        
        返回:
        - 掩码张量,形状为 (batch_size, seq_len)
        """
        mask = (src == pad_idx).transpose(0, 1)
        mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0))
        return mask

Encoder 的作用是将输入文本编码成包含上下文信息的向量表示。每个 Block 包含 Multi-Head Attention、Add & Norm 和 Feed Forward 三个子模块。

  • Multi-Head Attention 由多个 Self-Attention 子模块组成,用于提取文本的上下文信息。
  • Add & Norm 用于连接不同模块的输出,并进行残差连接和归一化处理。
  • Feed Forward 是一个两层的全连接网络,进一步学习文本表示。
python 复制代码
# 定义编码器块类
class EncoderBlock(nn.Module):
    def __init__(self, d_model, n_heads, d_ff, dropout, device):
        """
        初始化编码器块。
        
        参数:
        - d_model: 模型维度
        - n_heads: 多头注意力机制中的头数
        - d_ff: 前馈神经网络中间层的维度
        - dropout: Dropout比例
        - device: 设备类型(CPU/GPU)
        """
        super(EncoderBlock, self).__init__()
        # 初始化多头自注意力机制
        self.self_attn = MultiHeadAttention(d_model, n_heads, device)
        # 初始化前馈神经网络
        self.feed_forward = FeedForward(d_model, d_ff, dropout)
        # 初始化第一层归一化层
        self.layer_norm1 = nn.LayerNorm(d_model)
        # 初始化第二层归一化层
        self.layer_norm2 = nn.LayerNorm(d_model)
        # 初始化Dropout层
        self.dropout = nn.Dropout(dropout)

    def forward(self, src, mask):
        """
        执行编码器块的前向传播。
        
        参数:
        - src: 输入序列,形状为 (seq_len, batch_size, d_model)
        - mask: 掩码张量,形状为 (batch_size, seq_len)
        
        返回:
        - 编码器块的输出,形状为 (seq_len, batch_size, d_model)
        """
        # 层归一化后的输入
        src2 = self.layer_norm1(src)
        # 自注意力机制的查询、键和值均为同一输入
        q = k = v = src2
        # 应用多头自注意力机制
        src2 = self.self_attn(q, k, v, mask)
        # 将自注意力结果与原始输入相加,并应用Dropout
        src = src + self.dropout(src2)
        # 第二次层归一化
        src2 = self.layer_norm2(src)
        # 应用前馈神经网络
        src2 = self.feed_forward(src2)
        # 将前馈网络的结果与之前的输出相加,并应用Dropout
        src = src + self.dropout(src2)
        return src

Decoder 的作用是根据 Encoder 的输出和前一个 token 预测下一个 token,最终生成目标文本。每个 Block 包含 Masked Multi-Head Attention、Cross-Attention、Add & Norm 和 Feed Forward 四个子模块。

  • Masked Multi-Head Attention 用于预测下一个 token,同时屏蔽掉当前 token 之后的信息,避免泄露未来信息。
  • Cross-Attention 将 Encoder 的输出作为 Key 和 Value,Decoder 的输出作为 Query,提取 Encoder 和 Decoder 之间的关联信息,帮助 Decoder 理解输入文本和已有生成文本之间的关系。
  • Add & Norm 用于连接不同模块的输出,并进行残差连接和归一化处理。
  • Feed Forward 是一个两层的全连接网络,进一步学习文本表示。
python 复制代码
class DecoderBlock(nn.Module):
    def __init__(self, d_model, n_heads, d_ff, dropout, device):
        """
        初始化解码器块。
        
        参数:
        - d_model: 模型维度
        - n_heads: 多头注意力机制中的头数
        - d_ff: 前馈神经网络中间层的维度
        - dropout: Dropout比例
        - device: 设备类型(CPU/GPU)
        """
        super(DecoderBlock, self).__init__()
        # 初始化自注意力机制
        self.self_attn = MultiHeadAttention(d_model, n_heads, device)
        # 初始化交叉注意力机制
        self.cross_attn = MultiHeadAttention(d_model, n_heads, device)
        # 初始化前馈神经网络
        self.feed_forward = FeedForward(d_model, d_ff, dropout)
        # 初始化第一层归一化层
        self.layer_norm1 = nn.LayerNorm(d_model)
        # 初始化第二层归一化层
        self.layer_norm2 = nn.LayerNorm(d_model)
        # 初始化第三层归一化层
        self.layer_norm3 = nn.LayerNorm(d_model)
        # 初始化Dropout层
        self.dropout = nn.Dropout(dropout)

    def forward(self, tgt, memory, tgt_mask, src_mask):
        """
        执行解码器块的前向传播。
        
        参数:
        - tgt: 目标语言输入序列,形状为 (tgt_seq_len, batch_size, d_model)
        - memory: 编码器输出的记忆张量,形状为 (src_seq_len, batch_size, d_model)
        - tgt_mask: 目标语言掩码张量,形状为 (batch_size, tgt_seq_len)
        - src_mask: 源语言掩码张量,形状为 (batch_size, src_seq_len)
        
        返回:
        - 解码器块的输出,形状为 (tgt_seq_len, batch_size, d_model)
        """
        # 层归一化后的目标语言输入
        tgt2 = self.layer_norm1(tgt)
        # 自注意力机制的查询、键和值均为同一输入
        q = k = v = tgt2
        # 应用自注意力机制
        tgt2 = self.self_attn(q, k, v, tgt_mask)
        # 将自注意力结果与原始输入相加,并应用Dropout
        tgt = tgt + self.dropout(tgt2)
        # 第二次层归一化
        tgt2 = self.layer_norm2(tgt)
        # 交叉注意力机制的查询为当前目标语言输入,键和值为编码器输出
        q = tgt2
        k = v = memory
        # 应用交叉注意力机制
        tgt2 = self.cross_attn(q, k, v, src_mask)
        # 将交叉注意力结果与之前的输出相加,并应用Dropout
        tgt = tgt + self.dropout(tgt2)
        # 第三次层归一化
        tgt2 = self.layer_norm3(tgt)
        # 应用前馈神经网络
        tgt2 = self.feed_forward(tgt2)
        # 将前馈网络的结果与之前的输出相加,并应用Dropout
        tgt = tgt + self.dropout(tgt2)
        return tgt

输入处理

  • 文本首先经过 Token Embedding 和 Position Embedding,然后将两者相加得到最终的输入向量。
  • Token Embedding 将文本转换为向量表示,捕捉文本的基本语义信息。
  • Position Embedding 为每个 token 添加位置信息,使模型能够理解文本中 token 的顺序和位置关系。

Position Embedding

  • Transformer 使用正余弦位置编码,为每个 token 添加位置信息。
  • 奇数位置使用余弦函数,偶数位置使用正弦函数。
  • 这种方式可以有效地捕捉 token 的相对位置信息。

Attention Mechanism

  • Self-Attention 是 Transformer 的核心机制,用于计算文本中不同 token 之间的相关性。
  • Q, K, V 是 Self-Attention 的三个参数矩阵,分别代表 Query, Key 和 Value。
  • Attention Score Matrix 通过 Q 和 K 的转置相乘得到,并经过 Softmax 归一化。
  • Attention Matrix 通过 Attention Score Matrix 和 V 相乘得到,包含上下文信息。

Multi-Head Attention

  • Multi-Head Attention 将输入向量分别输入多个 Self-Attention 子模块,得到多个 Attention Matrix。
  • 将多个 Attention Matrix 拼接并经过全连接层降维,得到最终的输出。
  • 这种方式可以捕捉不同方面的信息,提高模型的表达能力。

Add & Norm

  • Add & Norm 用于连接不同模块的输出,并进行残差连接和归一化处理。
  • 残差连接可以防止信息丢失,归一化可以加快模型收敛。

Feed Forward

  • Feed Forward 是一个两层的全连接网络,第一层使用 ReLU 激活函数,第二层不使用激活函数。
  • 进一步学习文本表示,提高模型的表达能力。

Masking Mechanism

  • Padding Mask 用于屏蔽掉 Padding 位置的信息,避免模型学习到 Padding 位置的特征。
  • Sequence Mask 用于屏蔽掉当前 token 之后的信息,避免模型在预测下一个 token 时使用未来信息。

Softmax Layer

  • Softmax Layer 用于预测输出的单词,根据预测结果生成目标文本。

Transformer 模型通过 Encoder 和 Decoder 的协同工作,实现了序列到序列的转换任务。其核心机制 Self-Attention 能够有效地捕捉文本的上下文信息,Multi-Head Attention 和 Feed Forward 等模块则进一步提高了模型的表达能力。

transformer 论文领读 www.youtube.com/watch?v=nzq...

相关推荐
良木林10 分钟前
2024西游新生赛部分题解
c语言·数据结构·算法
宸码37 分钟前
【机器学习】【无监督学习——聚类】从零开始掌握聚类分析:探索数据背后的隐藏模式与应用实例
人工智能·python·学习·算法·机器学习·数据挖掘·聚类
Kylin5241 小时前
C语言经典代码——part 30
c语言·开发语言·算法
又菜又爱玩的东哥1 小时前
字符串的常见操作【C语言】
c语言·开发语言·算法
Solitudefire1 小时前
蓝桥杯刷题——day1
java·算法·蓝桥杯
TT哇1 小时前
【每日一练 基础题】[蓝桥杯 2022 省 A] 求和
java·算法·蓝桥杯
奶油泡芙9312 小时前
Insert Digit插入数字
c++·算法
两袖清风9982 小时前
【算法】—— 前缀和
java·数据结构·算法
不烦下雨c2 小时前
【优选算法】二分算法(在排序数组中查找元素的第一个和最后一个位置,寻找峰值,寻找排序数组中的最小值)
算法
uhakadotcom2 小时前
杀疯了,90后博士第一次创业,刚成立1年半,融资12亿,估值30亿
后端·算法·架构