好的我们来一场注意力机制 → Transformer的实战向讲解。目标人群定位已经了解过神经网络基本概念MLP、embedding、RNN/LSTM大概知道但对Transformer还处于“听过很多遍但自己写不出来”的阶段。我们今天尽量用最直白 可运行的方式把核心讲透 写出来。一、先把“注意力”这件事彻底想明白核心直觉一句话总结注意力机制最本质的作用让序列中每一个位置都能“按需”去看全序列中所有其他位置的信息而且看多少是由数据自己学出来的。传统RNN/LSTM是按顺序一个一个看注意力是“全局视野 软寻址”。最经典的Scaled Dot-Product Attention 计算公式一定要背下来Attention(Q, K, V) softmax( (Q K^T) / √d_k ) VQQuery 我现在关心什么KKey 别人介绍自己用的标签VValue 别人真正携带的信息类比一次人际关系版你在相亲当前token是Q对面100个人每人举着一张标签K你根据标签跟你需求的相关度打分Q·K然后把打分softmax变成权重最后把每个人的真心话V按权重加权求和 → 得到你听到的“综合意见”。二、最小可运行的单头注意力PyTorchimporttorchimporttorch.nnasnnimporttorch.nn.functionalasFimportmathclassSimpleSelfAttention(nn.Module):def__init__(self,d_model,d_kNone):super().__init__()self.d_modeld_model self.d_kd_kifd_kisnotNoneelsed_model# 三个可学习投影矩阵self.Wqnn.Linear(d_model,self.d_k)self.Wknn.Linear(d_model,self.d_k)self.Wvnn.Linear(d_model,d_model)# V的维度通常保持d_modeldefforward(self,x,maskNone):# x shape: [batch, seq_len, d_model]Qself.Wq(x)# [b, s, d_k]Kself.Wk(x)Vself.Wv(x)# [b, s, d_model]# 核心计算注意力分数scorestorch.matmul(Q,K.transpose(-2,-1))# [b, s, s]scoresscores/math.sqrt(self.d_k)# Scaled# mask可选用于因果/填充ifmaskisnotNone:scoresscores.masked_fill(mask0,-1e9)attn_weightsF.softmax(scores,dim-1)# [b, s, s]outtorch.matmul(attn_weights,V)# [b, s, d_model]returnout,attn_weights测试一下torch.manual_seed(42)xtorch.randn(2,8,64)# batch2, seq8, dim64attnSimpleSelfAttention(64)out,weightsattn(x)print(weights.shape)# torch.Size([2, 8, 8])print(out.shape)# torch.Size([2, 8, 64])三、升级版多头注意力Multi-Head Attention为什么需要多头一句话让模型同时从多个子空间观察关系语法、语义、指代、情感……实现方式把d_model切成h份每份独立算单头最后拼接线性投影。classMultiHeadAttention(nn.Module):def__init__(self,d_model,num_heads):super().__init__()assertd_model%num_heads0self.d_modeld_model self.num_headsnum_heads self.d_kd_model//num_heads self.Wqnn.Linear(d_model,d_model)self.Wknn.Linear(d_model,d_model)self.Wvnn.Linear(d_model,d_model)self.Wonn.Linear(d_model,d_model)# 最后的融合defforward(self,x,maskNone):b,s,dx.shape Qself.Wq(x).view(b,s,self.num_heads,self.d_k).transpose(1,2)Kself.Wk(x).view(b,s,self.num_heads,self.d_k).transpose(1,2)Vself.Wv(x).view(b,s,self.num_heads,self.d_k).transpose(1,2)# 现在形状[b, h, s, d_k]scorestorch.matmul(Q,K.transpose(-2,-1))/math.sqrt(self.d_k)ifmaskisnotNone:# mask要广播到 [b, h, s, s]maskmask.unsqueeze(1)scoresscores.masked_fill(mask0,-1e9)attnF.softmax(scores,dim-1)contexttorch.matmul(attn,V)# [b,h,s,d_k]# 合并多头contextcontext.transpose(1,2).contiguous().view(b,s,d)outself.Wo(context)returnout四、一个最简Transformer Encoder Layer实战最常用classTransformerEncoderLayer(nn.Module):def__init__(self,d_model512,num_heads8,d_ff2048,dropout0.1):super().__init__()self.self_attnMultiHeadAttention(d_model,num_heads)self.feed_forwardnn.Sequential(nn.Linear(d_model,d_ff),nn.ReLU(),nn.Dropout(dropout),nn.Linear(d_ff,d_model))self.norm1nn.LayerNorm(d_model)self.norm2nn.LayerNorm(d_model)self.dropoutnn.Dropout(dropout)defforward(self,x,maskNone):# 子层1自注意力 残差 normattn_outself.self_attn(x,mask)xself.norm1(xself.dropout(attn_out))# 子层2前馈网络 残差 normff_outself.feed_forward(x)xself.norm2(xself.dropout(ff_out))returnx六层堆叠就是经典Transformer Encoder了BERT就是这种结构。五、快速对比三种最常见的注意力mask使用场景2026年仍最主流场景mask类型谁能看到谁典型模型EncoderBERTpadding mask所有有效token互看BERT, RoBERTaDecoder自回归生成causal mask只能看到自己及之前的tokenGPT, LLaMA, QwenEncoder-Decoderpadding crossDecoder每个位置看Encoder全部T5, BART, Transformer翻译因果maskcausal mask代码实现最常用写法defgenerate_causal_mask(seq_len,device):masktorch.triu(torch.ones(seq_len,seq_len,devicedevice),diagonal1)return(mask0).float()# 上三角为0不可见下三角为1可见六、下一阶段推荐动手方向由浅入深用上面代码实现一个小型GPT只用decodercausal mask在tiny Shakespeare上语言建模加入位置编码推荐用Rotary Embedding / RoPE2025-2026主流实现Group Query Attention (GQA)或Multi-Query Attention (MQA)Llama3、Qwen2常用用torch.compile()或 flash-attention-2 加速训练速度可提升2-4倍有想重点深挖的模块吗比如想直接跑一个最小GPT训练想看Rotary位置编码代码想看Flash Attention的原理与降内存方式还是想直接讨论2026年最新的高效注意力变体MLA、Mamba-2、RetNet等告诉我你的具体目标我可以继续陪你写/调/测。