✍ 在大模型论文学习中,相信很多读者和笔者一样,一开始都会有一种感觉:“现在大模型架构都差不多,主要是数据和算力在堆积。”当笔者慢慢总结llama、qwen、deepseek这些模型架构的时候发现,在 attention、位置编码、ffn 与归一化 上,其实已经悄悄从经典 transformer 走到了另一套“默认配置”。相较于最初的 transformer,现在的主流大模型在架构上,已经逐渐从:
因此,在本文的学习中,我们主要聚焦于目前的大模型”默认配置“的学习,了解现在的”Transformer“!
读者肯定很疑惑,为什么我要把第一章名字起为现如今的”Transformer“,实际上在以前,不管是科研还是工作,大家都会把Transformer作为一个baseline去进行优化,就像BERT、GPT等等,一直沿用的是Transformer的架构。但到了现在,研究者发现其中模块的更替可以达到更好的的效果。因此,现如今的大模型,已经不再直接将以前的Transformer架构作为baseline,而是将更换了模块的Transformer架构作为baseline。那现如今的baseline模块长什么样子呢,笔者统计了比较经典的模块所采用的注意力机制、位置编码、MLP激活层以及归一化的方式:
模型家族 |
注意力 |
位置编码 |
MLP 激活 |
归一化 |
|---|---|---|---|---|
早期 GPT/BERT |
MHA |
绝对 PE / learned pos |
GELU |
LayerNorm |
LLaMA 1/2/3 系列 |
GQA(大模型) |
RoPE |
SwiGLU |
RMSNorm |
Qwen2 / Qwen2.5 |
GQA |
RoPE |
SwiGLU |
RMSNorm |
Mistral 7B |
GQA + sliding window |
RoPE |
SwiGLU |
RMSNorm |
DeepSeek-LLM 等 |
GQA/自研高效注意力 |
RoPE |
SwiGLU |
RMSNorm |
Granite / Gemma 等 |
GQA/MQA |
RoPE |
SwiGLU/GeGLU |
RMSNorm/LN |
如表格所示, 对比早期 GPT/BERT 模型我们就可以发现了,现如今大模型的各个模块都有所改变:
注意力机制:MQA → GQA(Grouped Query Attention)位置编码: 绝对位置编码 → RoPE(Rotary Positional Embedding)MLP 激活层:ReLU / GELU 前馈网络 → SwiGLU 前馈网络归一化: LayerNorm → RMSNorm + Pre-Norm所以如果你能把这四件套讲明白,基本就把现代 LLM 架构里 理清,并且可以快速找到文章的贡献点。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜
首先来回顾一下以前的注意力机制:
\text{Attention}(Q,K,V) = \text{softmax}\left(\frac{QK^\top}{\sqrt{d\_k}}\right)V
在标准的自注意力中,我们通过 $QK^T / \sqrt{d_k}$ 来计算不同 token 之间的注意力权重。但作者发现,仅用一个注意力头往往难以同时捕捉多种语义关系(如词法、语义、句法等)。因此,Transformer 提出了多头注意力机制 (Multi-Head Attention, MHA)。
将输入特征通过不同的线性投影矩阵,映射到多个低维子空间中:
\text{head}\_i = \text{Attention}(QW\_i^Q, \, KW\_i^K, \, VW\_i^V)
然后将所有头拼接(concatenate)再线性变换:
\text{MultiHead}(Q,K,V) = \text{Concat}(\text{head}\_1, \dots, \text{head}\_h) W^O
MHA通过多个小头可以从不同角度捕捉语义信息,增强模型的表达能力和稳定性,比单头更鲁棒。
import torchimport torch.nn as nnimport torch.nn.functional as Fclass MultiHeadAttention(nn.Module): def __init__(self, d_model, num_heads, dropout=0.0): super().__init__() assert d_model % num_heads == 0 self.d_model = d_model self.num_heads = num_heads self.head_dim = d_model // num_heads self.w_q = nn.Linear(d_model, d_model) self.w_k = nn.Linear(d_model, d_model) self.w_v = nn.Linear(d_model, d_model) self.w_o = nn.Linear(d_model, d_model) self.dropout = nn.Dropout(dropout) def forward(self, x, attn_mask=None): """ x: [B, L, d_model] """ B, L, _ = x.size() # 1. 线性投影 Q = self.w_q(x) # [B, L, d_model] K = self.w_k(x) V = self.w_v(x) # 2. reshape 为 [B, H, L, Dh] def reshape_heads(t): return t.view(B, L, self.num_heads, self.head_dim).transpose(1, 2) Q = reshape_heads(Q) K = reshape_heads(K) V = reshape_heads(V) # Q,K,V: [B, H, L, Dh] # 3. 缩放点积注意力 scores = Q @ K.transpose(-2, -1) / (self.head_dim ** 0.5) # [B, H, L, L] if attn_mask is not None: scores = scores.masked_fill(attn_mask == 0, float('-inf')) attn = F.softmax(scores, dim=-1) attn = self.dropout(attn) out = attn @ V # [B, H, L, Dh] # 4. 合并头 out = out.transpose(1, 2).contiguous().view(B, L, self.d_model) return self.w_o(out)有了 MHA 之后,大家第一反应是:头越多越好,越能学到多种语义关系。但在大模型、尤其是 Decoder-Only + 长上下文 + 自回归生成 的场景下,MHA 暴露出了一个非常现实的问题:
KV Cache 太贵了。
在自回归生成过程中,每生成一个新 token,都需要用到历史所有位置的K, V
对于标准 MHA:每个注意力头都维护一份自己的 K\_h, V\_h 如果有 h 个头,那么 KV Cache 的内存开销大致是: \mathcal{O}(h \cdot L \cdot d_{\text{head}})当我们把头数堆到 32、64 甚至更多,再把上下文长度拉到 32K、64K 时,这个开销就会变成显存吞噬怪,直接限制推理速度与可部署性。因此,为了在几乎不损失模型效果的前提下,压缩 KV Cache 和带宽成本,就提出了 Multi-Query Attention(MQA)。
MHA中的每一个头都是独享一份$K, V$,相反的,MQA 提出了所有的头共享同一份$K, V$也就是说,只保留一组 W^K, W^V ,而 W_i^Q 仍然为每个头独立:
于是每个头的注意力就变成:
最后依然是拼接再线性变换:
? 经验发现“多 KV”并没有带来线性收益, Q 仍然是多头的,多头仍能捕捉多种语义关系。
代码手撕class MultiQueryAttention(nn.Module): def __init__(self, d_model, num_heads, dropout=0.0): super().__init__() assert d_model % num_heads == 0 self.d_model = d_model self.num_heads = num_heads self.head_dim = d_model // num_heads self.w_q = nn.Linear(d_model, d_model) # 注意:K/V 只有一组,所以输出维度是 head_dim self.w_k = nn.Linear(d_model, self.head_dim) self.w_v = nn.Linear(d_model, self.head_dim) self.w_o = nn.Linear(d_model, d_model) self.dropout = nn.Dropout(dropout) def forward(self, x, attn_mask=None): """ x: [B, L, d_model] """ B, L, _ = x.size() # 1. 多头 Q Q = self.w_q(x) # [B, L, d_model] Q = Q.view(B, L, self.num_heads, self.head_dim).transpose(1, 2) # Q: [B, H, L, Dh] # 2. 单头 K/V K = self.w_k(x) # [B, L, Dh] V = self.w_v(x) # [B, L, Dh] # 3. 为了和 Q 匹配,将 K/V 在头维上 broadcast K = K.unsqueeze(1) # [B, 1, L, Dh] V = V.unsqueeze(1) # [B, 1, L, Dh] K = K.expand(B, self.num_heads, L, self.head_dim) V = V.expand(B, self.num_heads, L, self.head_dim) # 4. 缩放点积注意力(与 MHA 相同) scores = Q @ K.transpose(-2, -1) / (self.head_dim ** 0.5) # [B, H, L, L] if attn_mask is not None: scores = scores.masked_fill(attn_mask == 0, float('-inf')) attn = F.softmax(scores, dim=-1) attn = self.dropout(attn) out = attn @ V # [B, H, L, Dh] out = out.transpose(1, 2).contiguous().view(B, L, self.d_model) return self.w_o(out)根据前面两节的分析,我们可以总结出:
MHA:每个头都有独立的 K_h, V_h ,表达能力强,但 KV Cache 成本最高;MQA:所有头共享同一份 K, V ,KV Cache 成本最低,但多头之间视角差异弱,表达能力稍打折于是就自然出现了一个折中思路:能不能在 “省 KV” 和 “头之间有点差异” 之间找个平衡?这就是 Grouped-Query Attention(GQA)。GQA 的核心思想:Q 仍然是很多头,但 K/V 的头数减少为更少的组(num_kv_heads),每组 KV 服务若干个 Q 头。
代码手撕class GroupedQueryAttention(nn.Module): def __init__(self, d_model, num_q_heads, num_kv_heads, dropout=0.0): super().__init__() assert d_model % num_q_heads == 0 assert num_q_heads % num_kv_heads == 0 self.d_model = d_model self.num_q_heads = num_q_heads self.num_kv_heads = num_kv_heads self.head_dim = d_model // num_q_heads self.group_size = num_q_heads // num_kv_heads # 每组多少个 Q 头共享一个 KV self.w_q = nn.Linear(d_model, d_model) self.w_k = nn.Linear(d_model, num_kv_heads * self.head_dim) self.w_v = nn.Linear(d_model, num_kv_heads * self.head_dim) self.w_o = nn.Linear(d_model, d_model) self.dropout = nn.Dropout(dropout) def forward(self, x, attn_mask=None): """ x: [B, L, d_model] """ B, L, _ = x.size() # 1. Q: 多头; K/V: 少量头 Q = self.w_q(x) # [B, L, d_model] K = self.w_k(x) # [B, L, num_kv_heads * head_dim] V = self.w_v(x) Q = Q.view(B, L, self.num_q_heads, self.head_dim).transpose(1, 2) K = K.view(B, L, self.num_kv_heads, self.head_dim).transpose(1, 2) V = V.view(B, L, self.num_kv_heads, self.head_dim).transpose(1, 2) # Q: [B, Hq, L, Dh] # K,V: [B, Hkv, L, Dh] # 2. 将每个 KV 头“扩展”为 group_size 个 Q 头使用 # 例如 Hq=8, Hkv=2 -> group_size=4 K = K.repeat_interleave(self.group_size, dim=1) # [B, Hq, L, Dh] V = V.repeat_interleave(self.group_size, dim=1) # 3. 缩放点积注意力 scores = Q @ K.transpose(-2, -1) / (self.head_dim ** 0.5) # [B, Hq, L, L] if attn_mask is not None: scores = scores.masked_fill(attn_mask == 0, float("-inf")) attn = F.softmax(scores, dim=-1) attn = self.dropout(attn) out = attn @ V # [B, Hq, L, Dh] # 4. 合并头 out = out.transpose(1, 2).contiguous().view(B, L, self.d_model) return self.w_o(out)在 Transformer 里,归一化(Normalization)主要解决两个问题:
深层网络训练不稳定:梯度可能爆炸或消失;不同层输出分布漂移,导致学习变慢。最早的 Transformer 使用的是 LayerNorm + Post-Norm 残差结构(指在全连接层后跟上一个归一化层)
但到了 LLaMA、DeepSeek 等大模型时,大家开始逐渐转向:RMSNorm + Pre-Norm(指在全连接层前跟上一个归一化层)
最早的 Transformer 论文(Attention Is All You Need)使用的是 Post-Norm,代码结构类似:
# Post-Norm 结构out = x + sublayer(x)out = layer_norm(out)
大多数现代 LLM(如 LLaMA、DeepSeek 系列)改成了 Pre-Norm:代码结构类似:
# Pre-Norm 结构h = layer_norm(x)out = x + sublayer(h)
? 实践上,Pre-Norm 再配合 RMSNorm,只调节尺度不改均值,在 Decoder-only 结构里训练更稳定、实现也更简单。
Layer Normalization(LN)是在 Transformer 中使用最广的归一化方式之一。给定一个 token 的隐藏表示 x \in \mathbb{R}^{d} ,LayerNorm 对其 特征维度 进行归一化:
其中:
\gamma, \beta \in \mathbb{R}^{d} 是可学习的缩放和平移参数;归一化是在单个样本、单个 token 的通道维度上完成的。? 直觉理解:
在 PyTorch 中,你平时看到的 nn.LayerNorm 就是这个东西:
import torchimport torch.nn as nnx = torch.randn(2, 4, 8) # [B, L, d_model]ln = nn.LayerNorm(8)y = ln(x) # 每个位置的最后一维做 LN
这一问是面试官很喜欢的一个考点,尤其是 Transformer / LLM 岗位。核心区别在于:归一化时用哪些维度来统计均值与方差。
BatchNorm(BN):在 CV 里常用,对 batch 维度 + 空间维度 做统计;对每个通道c,使用整批数据的统计量:mu_c = \mathbb{E}_{N,H,W}x\_{n,c,h,w} LayerNorm(LN):对单个样本、单个 token 的所有特征求均值和方差,不依赖 batch 大小。在 Transformer / LLM 场景中,BN 存在几个问题:
序列长度不固定:BN 在变长序列上不自然,统计维度不好选;推理阶段 batch 很小甚至为 1:BN 的 running mean/var 与训练时差异大,容易分布漂移;自注意力中不同 token 之间差异大:BN 混合不同 token 的统计量,会引入额外噪声。因此,大模型里更偏向用 LayerNorm / RMSNorm 这种“不依赖 batch、只看自己”的归一化方式。
RMSNorm 是基于“层归一化中主要起作用的是缩放因子,而非平移因子”这个发现而提出的归一化方法。在层归一化中需要减去均值,而模型在训练过程中已经学会通过投影矩阵自动调节均值;而 \gamma 的作用是调整每一维的相对 scale,是表达力的核心。给定 x \in \mathbb{R}^d ,RMSNorm 的公式为:
\text{RMS}(x) = \sqrt{\frac{1}{d} \s
um\_{i=1}^{d} x\_i^2 + \epsilon}
\text{RMSNorm}(x) = \frac{x}{\text{RMS}(x)} \cdot \gamma
? 直觉理解:
? 实践上,在 Decoder-only 大模型里:RMSNorm + Pre-Norm 组合在超深层网络(几十层)上表现更稳定,这也是 LLaMA / DeepSeek / Qwen 等系列广泛采用它的原因之一。
代码手撕class RMSNorm(nn.Module): def __init__(self, d_model, eps=1e-8): super().__init__() self.weight = nn.Parameter(torch.ones(d_model)) self.eps = eps def forward(self, x): """ x: [B, L, d_model] """ # 均方根:sqrt(mean(x^2)) rms = x.pow(2).mean(dim=-1, keepdim=True).add(self.eps).sqrt() x_norm = x / rms return self.weight * x_norm
本章我们先把现代大模型里的两块“基础设施”打牢:一块是从 MHA → MQA → GQA 的注意力演化,用更少的 KV 头(甚至共享 KV)在不明显掉点的前提下,大幅降低 KV Cache 与长上下文显存开销;另一块是从 LayerNorm → RMSNorm + Pre-Norm 的归一化升级,用“只归一化能量”的 RMSNorm 配合 Pre-Norm 结构,让超深的 Decoder-only 模型在训练和推理中都更加稳定。后面的章节,我们再把 RoPE / SwiGLU / MoE / MLA 这些“进阶武器”一个个拆开,拼成一整套现代 LLM 的“架构面经图谱”。
# win
# bert
# transformer
# var
# 堆
# Token
# 架构
# batch
# deepseek
# 为什么
# 区别
# 大模型
# pytorch
# gpt
# 编码
# qwen
# 显存
# 仍然是
# 是从
# 多个
# 尤其是
# 是在
# 提出了
# 均值
# 现如今
# 的是
# embedding
# llama
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化91478 】
【
技术知识72672 】
【
云计算0 】
【
GEO优化84317 】
【
优选文章0 】
【
营销推广36048 】
【
网络运营41350 】
【
案例网站102563 】
【
AI智能45237 】
相关推荐:
解密Poppy Playtime怪物:全面解析玩具世界背后的故事
利用 DeepSeek 提高敏捷开发中的 Sprint 规划效率
Zapier MCP:AI赋能工作流,释放Claude强大潜能
豆包 AI 在英语单词高效背诵中的趣味应用
Django与React构建AI音乐推荐:数据库集成实战指南
AI图像生成偏见:克服与优化,打造更真实的数字形象
AI 和 Plagiarism Checker:SEO 内容创作的终极指南
通义千问怎样优化提示词效果_通义千问提示词优化技巧【攻略】
京东旅行AI能否抢返程票_京东AI返程票预约与自动抢购【技巧】
AI驱动的Web应用测试:突破QA挑战,提升用户体验
百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭
AI一键生成原创SEO文章
5分钟教你用AI给黑白老照片上色,让回忆变得鲜活
通义万相做小红书配图怎么用_通义万相做小红书配图使用方法详细指南【教程】
tofai登录入口官网 tofai网页版地址链接
C3.ai深度解析:投资者必知的关键洞察
Jasper AI如何做SEO优化 Jasper AI结合SurferSEO用法【教程】
VHEER AI:免费在线AI图像生成器终极指南
VideoInu AI 动画制作:教程、功能与Pro账户赠送
AI赋能保险销售:提升邮件营销效果的终极指南
快手本地生活AI如何预约景区火车票_快手AI本地生活抢票步骤【步骤】
AI 时代高效开发:版本控制与 AI 协同工作流
AI如何革新心理健康诊断:从症状检查到大脑分析
如何用AI帮你创建自定义表情符号(Emoji)?聊天斗图更有趣
AI Vibe Coding: 快速打造落地页,低代码平台实战教程
寻宝者的发现:古董探测与文物挖掘揭秘
ChatGPT 处理超长 PDF 文件的核心步骤
Google Gemini 处理结构化 XML 数据转换教程
AI Notebooks: 知识工作者的未来?赋能理解与洞察的工具
即梦ai怎样生成插画作品_即梦ai插画生成入口与风格选择【教程】
Microsoft Math Solver:AI数学解题神器深度评测
Codeforces Pair Programming Problem: C 解题思路
钉钉ai划词工具怎么使用划词查词_钉钉ai划词工具查词入口与释义查看【指南】
Xeon E5-2667 V2性能评测:老平台焕发新生,游戏与工作负载表现分析
Avokaado AI:简化合同管理和法律流程的终极指南
使用Go语言构建图像识别系统:完整指南
探索心灵的音乐之旅:Kanwar Garewal的《Ishq Bulleh Nu》
解锁 Gemini Gems 高级用法:打造专属 AI 专家助手
AI一键生成儿童绘本故事
如何用AI根据职位描述(JD)定制你的求职信?
智行ai抢票怎么选优先车次_智行ai抢票车次优先级设置技巧【指南】
AI赋能项目管理:5个实用技巧提升效率
ChatGPT怎样用提示词分步骤提问_ChatGPT分步提问技巧【方法】
网络安全警钟:揭秘“美足”背后隐藏的危机与防范
lovemo手机网页版 lovemo官方入口地址
Removebg怎样快速抠图_Removebg上传图片与自动抠图步骤【教程】
高效赋能:在线健身教练必备的七大工具
2025年度AMD处理器终极评选:年度最佳CPU推荐
Roblox Studio AI 助手:创意构建与无限可能
Notta AI: 提升效率的智能会议纪要工具
2025-11-26
南京市珐之弘网络技术有限公司专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。