资讯动态

Transformer架构实战:从零理解自注意力机制到BERT/GPT实现差异

发布时间:2026/8/5 11:47:01 来源:尧图企业网站定制
Transformer架构实战从零理解自注意力机制到BERT/GPT实现差异当你在Colab中运行第一个Transformer模型时是否注意到BERT和GPT对同一段文本的处理方式截然不同这种差异源于Transformer架构中编码器与解码器的精妙设计。本文将用PyTorch代码拆解自注意力机制的核心实现并通过可视化工具揭示BERT和GPT在位置编码、注意力掩码等关键组件上的技术分叉。1. 自注意力机制的数学本质与代码实现自注意力机制的核心在于计算查询Q、键K、值V三个矩阵的交互。假设输入序列长度为n嵌入维度为d则计算过程可分解为import torch import torch.nn.functional as F def self_attention(Q, K, V, maskNone): # Q,K,V shape: (batch_size, seq_len, d_model) d_k Q.size(-1) scores torch.matmul(Q, K.transpose(-2, -1)) / torch.sqrt(torch.tensor(d_k)) if mask is not None: scores scores.masked_fill(mask 0, -1e9) weights F.softmax(scores, dim-1) return torch.matmul(weights, V), weights关键参数对比参数BERT-base典型值GPT-3典型值注意力头数1296隐藏层维度76812288层数1296注意实际实现中会采用多头注意力机制每个头的维度通常为d_model // num_heads在可视化注意力权重时BERT的注意力模式通常呈现对角线分布关注局部上下文而GPT由于因果掩码的限制只能关注当前位置之前的token。使用matplotlib可以直观展示这种差异def plot_attention(weights, title): import matplotlib.pyplot as plt plt.imshow(weights[0, 0].detach().numpy(), cmapviridis) plt.colorbar() plt.title(title) plt.show()2. 位置编码让模型理解顺序的两种范式Transformer架构抛弃RNN的循环结构后必须显式注入位置信息。BERT和GPT采用了完全不同的策略BERT的绝对位置编码class BERTPositionalEncoding(nn.Module): def __init__(self, d_model, max_len512): super().__init__() position torch.arange(max_len).unsqueeze(1) div_term torch.exp(torch.arange(0, d_model, 2) * (-math.log(10000.0) / d_model)) pe torch.zeros(max_len, d_model) pe[:, 0::2] torch.sin(position * div_term) pe[:, 1::2] torch.cos(position * div_term) self.register_buffer(pe, pe) def forward(self, x): return x self.pe[:x.size(1)]GPT的相对位置编码 现代GPT变体如GPT-3更多使用旋转位置编码RoPE其核心是def apply_rotary_pos_emb(q, k, sin, cos): q_embed (q * cos) (rotate_half(q) * sin) k_embed (k * cos) (rotate_half(k) * sin) return q_embed, k_embed位置编码效果对比特性绝对位置编码相对位置编码最大长度限制有如512理论上无限泛化能力对训练长度外位置泛化较差能更好处理长文本计算复杂度O(1)O(n)3. 架构差异编码器与解码器的关键设计BERT的编码器架构允许同时处理整个输入序列而GPT的解码器必须遵循自回归生成模式。这种根本差异体现在BERT的编码器层实现class BERTLayer(nn.Module): def __init__(self, d_model, num_heads): super().__init__() self.attention MultiHeadAttention(d_model, num_heads) self.norm1 nn.LayerNorm(d_model) self.ffn PositionwiseFFN(d_model) self.norm2 nn.LayerNorm(d_model) def forward(self, x, mask): attn_out, _ self.attention(x, x, x, mask) x self.norm1(x attn_out) ffn_out self.ffn(x) return self.norm2(x ffn_out)GPT的解码器层实现class GPTLayer(nn.Module): def __init__(self, d_model, num_heads): super().__init__() self.masked_attention MultiHeadAttention(d_model, num_heads) self.norm1 nn.LayerNorm(d_model) self.cross_attention MultiHeadAttention(d_model, num_heads) # 仅在有encoder时使用 self.norm2 nn.LayerNorm(d_model) self.ffn PositionwiseFFN(d_model) self.norm3 nn.LayerNorm(d_model) def forward(self, x, causal_mask): attn_out, _ self.masked_attention(x, x, x, causal_mask) x self.norm1(x attn_out) # 如果是encoder-decoder架构此处会添加cross attention ffn_out self.ffn(x) return self.norm3(x ffn_out)关键架构对比注意力掩码BERT使用padding mask处理变长输入GPT必须额外使用因果掩码causal maskdef create_causal_mask(size): mask torch.triu(torch.ones(size, size), diagonal1) return mask.masked_fill(mask 1, float(-inf))训练目标BERT采用MLM掩码语言模型目标GPT采用标准语言模型目标预测下一个token4. 实战对比同一任务下的不同表现在文本分类任务中我们可以清晰观察到两种架构的差异。以IMDb影评分类为例BERT实现方案from transformers import BertModel, BertTokenizer tokenizer BertTokenizer.from_pretrained(bert-base-uncased) model BertModel.from_pretrained(bert-base-uncased) inputs tokenizer(This movie was amazing!, return_tensorspt) outputs model(**inputs) cls_embedding outputs.last_hidden_state[:, 0, :] # 取[CLS]标记对应的嵌入GPT实现方案from transformers import GPT2Model, GPT2Tokenizer tokenizer GPT2Tokenizer.from_pretrained(gpt2) model GPT2Model.from_pretrained(gpt2) inputs tokenizer(This movie was amazing!, return_tensorspt) outputs model(**inputs) # 需要取最后一个token的嵌入或做pooling last_embedding outputs.last_hidden_state[:, -1, :]性能对比IMDb测试集指标BERT-baseGPT-2准确率92.3%88.7%训练速度1.2小时0.8小时显存占用3.2GB2.7GB提示实际应用中GPT类模型需要通过添加分类头或prompt tuning来适配分类任务在Colab实操中可以通过以下代码可视化两者的注意力模式差异def compare_attention(text): bert_outs bert_model(**bert_tokenizer(text, return_tensorspt)).attentions gpt_outs gpt_model(**gpt_tokenizer(text, return_tensorspt)).attentions plot_attention(bert_outs[0][0], BERT Attention) plot_attention(gpt_outs[0][0], GPT Attention)

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价