Transformer 22. Gemma 1 架构详解:Decoder-only、GeGLU、RoPE 与每一步计算

摘要 :本文在 Decoder Only TransformerLLaMA 架构 的统一框架下,系统介绍 Gemma 1(2B / 7B) 的架构与每一步的矩阵维度与运算 。内容包括:Gemma 1 的定位(与 Gemini 技术同源的开源 Decoder-only 文本模型)、从文本到解码器的数据流(SentencePiece 词表、嵌入、 在嵌入上相加的绝对位置向量)、单层 Decoder 内的 Pre-Norm + RMSNorm带掩码自注意力 (7B 为 MHA ,2B 为 MQA )与 RoPEGeGLU 前馈网络、lm_head 与自回归训练/推理;并在各环节对照 2017 年标准 DecoderLLaMA 说明差异与设计动机。

关键词:Gemma 1;Decoder-only;RMSNorm;Pre-Norm;GeGLU;RoPE;MQA;MHA;掩码自注意力;SentencePiece

参考与引用


💡 理解要点Gemma 1仅 Decoder 的因果语言模型:每层为 因果自注意力 + 前馈 + 残差 + RMSNorm没有 Encoder、没有交叉注意力 。与 LLaMA 同属「现代开源 LLM 配方」(RMSNorm、Pre-Norm、RoPE、门控 FFN),但 FFN 使用 GeGLU(GELU 门控) 而非 SwiGLU;7B 用标准 MHA2B 用 MQA 以换推理效率。与 经典 Transformer Decoder(Post-Norm、嵌入加正弦 PE、ReLU FFN)差异更大。


1. 概述:Gemma 1 在模型家族中的位置

1.1 Decoder-only 与自回归目标

Decoder Only Transformer 一致,Gemma 1 的任务是:给定已出现的 token 序列,预测下一个 token 。训练时对整段序列加因果掩码并行算损失;推理时逐步把预测 token 拼回输入。

Gemma 1 的范围 :公开发布的 2B、7B 权重均为文本进、文本出 的多语模型;上下文长度、GeGLU、RoPE 等细节以官方博文与 config.json 为准。来源:Gemma explained: An overview of Gemma model family architectures

1.2 核心规模对照表

下列为 Google 开发者博文中的 Gemma 1 代表性超参 (便于后文指称;实现上 embed_tokens 行数可能写作 256000,与 256128 有细微差别,以 checkpoint 为准)。

属性 Gemma 1 2B Gemma 1 7B
层数 N N N 18 28
d model d_{\text{model}} dmodel 2048 3072
注意力头数 h h h 8 16
每头维度 d k d_k dk 256 256
KV 头数 1(MQA) 16(MHA)
FFN 中间维(「Feedforward hidden dims」) 32768 49152
词表 V V V 256128(SentencePiece) 同左
训练上下文长度 8192 tokens 同左

注意,层数 N N N 指的是:堆叠的 Decoder 块(Transformer Layer)有多少个------也就是模型里有多少个 GemmaDecoderLayer(或同类的 DecoderLayer) 从输入到输出依次重复。

🔍 实际例子(7B) :若 L = 4096 L=4096 L=4096,则进入每层的张量主形状为 4096 × 3072 4096 \times 3072 4096×3072 ;自注意力中每个头的 Q ( t ) Q^{(t)} Q(t) 为 4096 × 256 4096 \times 256 4096×256 ,打分矩阵 S ( t ) S^{(t)} S(t) 为 4096 × 4096 4096 \times 4096 4096×4096(工程上常用 FlashAttention 等避免物化全矩阵)。

这里附上 Gemma 1 的架构图。第 3 节 对应单层里的 第一子层(自注意力块,含前置 RMSNorm)第 4 节 对应 第二子层(GeGLU 前馈块,含前置 RMSNorm)第 2 节 仍讲堆叠层之前的 Tokenizer / 嵌入 / RoPE 原理


2. 从输入到 Decoder:Token、嵌入与位置信息

2.1 Tokenization:SentencePiece 与子词 ID

什么是 Tokenization?

Tokenization 是把原始字符串变成模型能吃的 离散符号序列 的过程:先切成若干 Token(词元) ,再把每个 Token 映射到词表里的整数 ID 。可以把它想成「把一句话拆成一排带编号的乐高积木」------模型里不出现原始 Unicode 字符,只出现这串 ID,后面的 Embedding 再按 ID 查表成向量。

Decoder Only Transformer 2.1 节 的关系 :那里已经强调「文本 → \to → ID → \to → 矩阵」的整体链路;本节在 Gemma 1 上把 SentencePiece + 256128 词表 说清楚,便于你对着官方权重或 tokenizer.json 核对。

SentencePiece 在做什么?

Gemma 1 使用 SentencePiece 作为分词后端(与早期 Gemma 技术说明一致 来源:Gemma explained 博文)。它通常在海量文本 上先学出一个固定大小的 子词词表 (含单字、多字片段、常见词根等),编码时再按所选算法(SentencePiece 支持 Unigram 语言模型BPE 等)把字符串切成词表内子词 的序列,使 任意新文本 几乎总能被覆盖,从而**显著减轻 OOV(词表外)**问题,对多语、符号、混写(中英夹杂、数字、标点)比较友好。

输出长什么样?

设一段 UTF-8 文本经 Tokenizer 编码后得到长度为 L L L 的序列:

w = ( w 0 ,   w 1 ,   ... ,   w L − 1 ) , 0 ≤ w i < V . \mathbf{w} = (w_0,\, w_1,\, \ldots,\, w_{L-1}), \quad 0 \le w_i < V. w=(w0,w1,...,wL−1),0≤wi<V.

这里 V = 256128 V=256128 V=256128 是 Gemma 1 公开配置中的词表大小。L L L 就是后续自注意力里序列维的长度:同一段文字,Token 化后 L L L 越小 ,在相同上下文窗口里能塞进的「字数」往往越多,但词表变大也会抬高 Embedding / lm_head 的参数量与显存占用。

Token 与 ID 的直观例子(示意,非你本地 tokenizer 的真实 ID)

文本 可能的子词切分(示意) 说明
我喜欢吃苹果 | 喜欢 | | 苹果 或更细的子词组合 中文常被切成字/多字片,与训练语料统计有关
Hello world Hello | ▁worldHel | lo | ▁world 英文常见子词; 在 SentencePiece 里常表示空格边界(具体以词表为准)
def foo() 代码子词若干段 代码语料训练后会出现专门片段,利于补全

因此:同一句话在不同模型里会得到不同的 ID 序列,因为词表与 merge/训练目标都不同。

Gemma 1 词表规模(256128)带来什么?

  • 多语与稀有词 :比很多早期 32K~50K 词表的模型更有空间容纳多语言子词与符号,同样字符数往往用更少或更稳的切分(具体仍依赖语料)。
  • 特殊 Token :除普通文本子词外,词表里还会占坑 BOS/EOS/PAD/对话模板专用符号 等;实现里常见 padding_idx=0 (见下文 2.2 节),说明 ID 0 往往被保留为 pad ,与「普通词的第一个 ID」要区分开------以 tokenizer_config.json / 文档为准。

与 GPT 系 BPE、LLaMA 等 tokenizer 的差异(概念层)

  • 都是 子词级 :很少整词独占一词表项,而是 词根 + 后缀 等拼接,兼顾词与字符之间粒度。
  • 算法细节不同 :例如 Byte-level BPE 先在字节或字符上再做合并,与 SentencePiece 的「直接训子词表 + 空白处理」在空格是否显式、词表构造流程上并不相同。
  • 结论 :不要把 ChatGPT 里某句话的 token 数,原封不动套到 Gemma 1 上计费或估长;应用侧应以当前模型的 tokenizer.encode 为准

💡 理解要点 :Gemma 1 的 Tokenization = SentencePiece 子词切分 + V = 256128 V=256128 V=256128 查表 ID 。解码器看到的「序列」在数值上就是这串 ( w 0 , ... , w L − 1 ) (w_0,\ldots,w_{L-1}) (w0,...,wL−1),再往后的矩阵形状一律是 L × d model L \times d_{\text{model}} L×dmodel

2.2 Embedding:查表得到 L × d model L \times d_{\text{model}} L×dmodel

2.2.1 数学本质

Embedding 层是一张 可学习的查找表 (lookup table)。词表大小为 V V V,模型隐藏维为 d model d_{\text{model}} dmodel,则权重矩阵为

E ∈ R V × d model . E \in \mathbb{R}^{V \times d_{\text{model}}}. E∈RV×dmodel.

对 Tokenization 得到的 ID 序列中第 i i i 个位置上的 w i w_i wi( 0 ≤ w i < V 0 \le w_i < V 0≤wi<V),嵌入向量是 E E E 的第 w i w_i wi 行(实现里等价于「用整数索引从第一维取值」):

x i = E [ w i ] ∈ R d model . \mathbf{x}i = E[w_i] \in \mathbb{R}^{d{\text{model}}}. xi=E[wi]∈Rdmodel.

把整段序列按行堆叠,得到送入第一层 Decoder 之前的 token 表示矩阵

X = [ x 0 ⊤ ⋮ x L − 1 ⊤ ] ∈ R L × d model . X = \begin{bmatrix} \mathbf{x}0^\top \\ \vdots \\ \mathbf{x}{L-1}^\top \end{bmatrix} \in \mathbb{R}^{L \times d_{\text{model}}}. X= x0⊤⋮xL−1⊤ ∈RL×dmodel.

2.2.2 批处理时的形状

训练常为 batch 大小 B B B 条序列一起算;每条经 pad 到同一 L max ⁡ L_{\max} Lmax 时,嵌入输出为 B × L max ⁡ × d model B \times L_{\max} \times d_{\text{model}} B×Lmax×dmodel 。下文为简洁,多取 B = 1 B=1 B=1 ,写 L × d model L \times d_{\text{model}} L×dmodel

Gemma 1 的矩阵形状与参数量 (取公开配置 V = 256128 V=256128 V=256128 来源:Gemma explained):

型号 d model d_{\text{model}} dmodel 嵌入矩阵 E E E 嵌入权重个数(约)
2B 2048 R 256128 × 2048 \mathbb{R}^{256128 \times 2048} R256128×2048 256128 × 2048 ≈ 5.24 × 10 8 256128 \times 2048 \approx 5.24\times 10^8 256128×2048≈5.24×108
7B 3072 R 256128 × 3072 \mathbb{R}^{256128 \times 3072} R256128×3072 256128 × 3072 ≈ 7.87 × 10 8 256128 \times 3072 \approx 7.87\times 10^8 256128×3072≈7.87×108
2.2.3 输出层 lm_head:未绑权与绑权

从 h \mathbf{h} h 到 logits(预测下一词)

设最后一层 Decoder 输出 H ∈ R L × d model H \in \mathbb{R}^{L \times d_{\text{model}}} H∈RL×dmodel,自回归预测「下一个 token」时常取最后一个有效位置的行向量,记为列向量形式

h = H [ L − 1 ,   : ] ⊤ ∈ R d model \mathbf{h} = H[L-1,\,:]^\top \in \mathbb{R}^{d_{\text{model}}} h=H[L−1,:]⊤∈Rdmodel

语言模型头要把 d model d_{\text{model}} dmodel 维压到 词表维 V V V ,得到 logits s ∈ R V \mathbf{s} \in \mathbb{R}^V s∈RV,再 P = s o f t m a x ( s ) P=\mathrm{softmax}(\mathbf{s}) P=softmax(s)。

未绑权(untied) 时,单独 存放输出权重 W out ∈ R d model × V W_{\text{out}} \in \mathbb{R}^{d_{\text{model}} \times V} Wout∈Rdmodel×V 与(若有)偏置 b out ∈ R V \mathbf{b}_{\text{out}} \in \mathbb{R}^V bout∈RV,常用列向量写法为

s = W out ⊤ h + b out . \mathbf{s} = W_{\text{out}}^\top \mathbf{h} + \mathbf{b}_{\text{out}}. s=Wout⊤h+bout.

等价地,用行向量 h ⊤ \mathbf{h}^\top h⊤(与 PyTorch 里 hidden @ lm_head.weight.T 一致):

s ⊤ = h ⊤ W out + b out ⊤ . \mathbf{s}^\top = \mathbf{h}^\top W_{\text{out}} + \mathbf{b}_{\text{out}}^\top. s⊤=h⊤Wout+bout⊤.

此时 嵌入 E E EW out W_{\text{out}} Wout 无关:输入端「词 w w w 的语义方向」与输出端「给每个词打分的方向」两套参数各自学习 。参数量上,在已有 E ∈ R V × d model E \in \mathbb{R}^{V \times d_{\text{model}}} E∈RV×dmodel 之外,再多约 d model × V d_{\text{model}} \times V dmodel×V 个权重(bias 仅 V V V 维,相对可忽略)。

绑权(weight tying / tied embedding)
绑权在数学上即令

W out = E ⊤ ( 即 W out ∈ R d model × V 与 E ⊤ 共用同一块存储 ) . W_{\text{out}} = E^\top \quad (\text{即 } W_{\text{out}} \in \mathbb{R}^{d_{\text{model}} \times V} \text{ 与 } E^\top \text{ 共用同一块存储}). Wout=E⊤(即 Wout∈Rdmodel×V 与 E⊤ 共用同一块存储).

于是第 w w w 个词元的 logit(无偏置时)为

s w = h ⊤ e w , s_w = \mathbf{h}^\top \mathbf{e}_w, sw=h⊤ew,

其中 e w = E [ w ,   : ] ⊤ \mathbf{e}w = E[w,\,:]^\top ew=E[w,:]⊤ 正是 输入端用来表示 token w w w 的那一行嵌入 (列向量)。也就是说:打分 = 上下文向量 h \mathbf{h} h 与各词嵌入方向的「内积」 ------「从向量回到词表」与「从词表进到向量」在词表维上**共用同一组 V V V 个 d model d{\text{model}} dmodel 维方向** 。若有输出偏置,则 s w = h ⊤ e w + ( b out ) w s_w = \mathbf{h}^\top \mathbf{e}w + (b{\text{out}})w sw=h⊤ew+(bout)w。用同一句式概括:省一整块 d model × V d{\text{model}} \times V dmodel×V 的 W out W_{\text{out}} Wout。

Gemma 1 上如何核对

  • 配置tie_word_embeddings: true绑权false独立 lm_head
  • 实现细节 :绑权时 model.get_input_embeddings().weightlm_head.weight 往往是同一张张量isdata_ptr() 相同);print(model) 仍可能并列 打印 embed_tokenslm_head,容易被误读成「多占了一份参数」。
  • 省参数量级 :当 V = 256128 V=256128 V=256128、7B 的 d model = 3072 d_{\text{model}}=3072 dmodel=3072 时,若从 untied 改为 tied,大约少存 3072 × 256128 ≈ 7.87 × 10 8 3072 \times 256128 \approx 7.87\times 10^8 3072×256128≈7.87×108 个与 W out W_{\text{out}} Wout 对应的权重(与上表「仅嵌入」那一列同量级)。
2.2.4 与 Tokenization 的衔接

多一个空格、换行或不可见字符,ID 序列可能整条变化 ,查到的 E E E 行也不同------提示词里的空白、标点同样影响分布与开销。

🔍 实际例子(7B,长度取预训练上限 8192) :单条序列若 L = 8192 L=8192 L=8192,则 Embedding 输出为 8192×3072 ;若 B = 4 B=4 B=4,则 4×8192×3072 。每一行是一个位置的 d model d_{\text{model}} dmodel 维向量,进入第一层 RMSNorm 与自注意力。
💡 理解要点 :嵌入 = 按 ID 从 E E E 取行 ,得到 X ∈ R L × d model X \in \mathbb{R}^{L \times d_{\text{model}}} X∈RL×dmodel行下标 只表示 token 在序列中的先后相对/绝对位置信息 由后续 RoPE 写入注意力,不在此处 给 X X X 加正弦或可学习位置向量。

2.3 位置编码:RoPE,不在嵌入上「加 PE」

2.3.1 为什么需要位置信息?

自注意力对序列是置换敏感 的:若不加任何位置线索,调换两个位置的 token,单看注意力子层 得到的加权和可能完全不变 (因为「谁和谁相似」的关系集合没有改变)。但自然语言里 「猫咬狗」≠「狗咬猫」 ,顺序决定语义。因此必须在模型某处注入 位置信息Decoder Only Transformer 2.3 节 给出的经典做法是:在嵌入上再加一个只依赖位置的向量 ;Gemma 1 走的是另一条路:不把位置向量加在 X X X 上 ,而是写进 Q , K Q,K Q,K 的几何关系里(RoPE)。

2.3.2 经典绝对位置编码 vs Gemma 1(RoPE)
维度 经典 Transformer(Decoder Only Transformer 2.3 节 Gemma 1(与 LLaMA 2.3 节 同路线)
注入时机 Embedding 之后、进第一层之前,通常 只做一次 每一层 、算 Q K ⊤ QK^\top QK⊤ 之前 ,对当层的 Q , K Q,K Q,K 注入
注入对象 整段序列的隐表示, I n p u t = E m b + P E \mathrm{Input}=\mathrm{Emb}+\mathrm{PE} Input=Emb+PE 只对当前头的 Q , K Q,K Q,K 行向量 施旋转;V V V 一般不做 RoPE
数学形态 P E ( p o s ) \mathrm{PE}(pos) PE(pos) 与词嵌入 相加 块对角旋转矩阵 R p o s R_{pos} Rpos 左乘 到该位置的 Q , K Q,K Q,K 子向量上
进入第一层的 X X X 已含绝对位置 仍仅 embed_tokens,形状 L × d model L \times d_{\text{model}} L×dmodel, PE 相加
位置语义 强调每个 p o s pos pos 的 绝对位置向量 注意力 logits 更可刻画 相对间距 i − j i-j i−j(理论动机见 RoPE 文

Gemma 1 实现侧 :Hugging Face 打印里每层有 rotary_embGemmaRotaryEmbedding),与 当前层 线性投影得到的 Q , K Q,K Q,K 结合后再算 scores 来源:Gemma explained: An overview of Gemma model family architectures

2.3.3 RoPE 在算什么(直觉 + 形状)

直觉 :把每个头的维度 d k d_k dk(Gemma 1 里 256 ,为偶数)看成 d k / 2 d_k/2 dk/2 个互不耦合的 2D 平面 ;位置 m m m 在第 t t t 个平面上转一个角 θ m , t = m ω t \theta_{m,t}=m\omega_t θm,t=mωt。Query 在位置 m m m、Key 在位置 n n n 的两束向量各自旋转后做点积,等价于夹角里携带 m − n m-n m−n 一类信息------故叫 旋转位置编码(RoPE)

单头矩阵形状 (本层输入经 RMSNorm、再乘 W Q , W K W_Q,W_K WQ,WK 之后):

  • Q ,   K ∈ R L × d k Q,\, K \in \mathbb{R}^{L \times d_k} Q,K∈RL×dk。
  • 对第 i i i 行(序列位置 i i i)的 d k d_k dk 维向量分别施加同一套「按位置 i i i 确定的旋转」(实现里常 fused,不显式展开整块旋转矩阵),得到 Q ′ Q' Q′、 K ′ K' K′ 的第 i i i 行;整体 Q ′ ,   K ′ ∈ R L × d k Q',\,K' \in \mathbb{R}^{L \times d_k} Q′,K′∈RL×dk形状不变,只改变数值。

注意力分数与后续(单头;多头时对每个头重复,再拼接):

S = Q ′ ( K ′ ) ⊤ d k ∈ R L × L . S = \frac{Q' (K')^\top}{\sqrt{d_k}} \in \mathbb{R}^{L \times L}. S=dk Q′(K′)⊤∈RL×L.

加因果掩码 M M M(同上三角 − ∞ -\infty −∞), A t t n W e i g h t s = s o f t m a x ( S + M ) \mathrm{AttnWeights}=\mathrm{softmax}(S+M) AttnWeights=softmax(S+M),与 未施 RoPE 的 V V V 相乘(标准实现里 V V V 仍用原投影输出):

h e a d = s o f t m a x ( S + M )   V ∈ R L × d k . \mathrm{head} = \mathrm{softmax}(S+M)\, V \in \mathbb{R}^{L \times d_k}. head=softmax(S+M)V∈RL×dk.

复杂度 :与不做 RoPE 的全长自注意力相同,主项仍是 O ( L 2 ) O(L^2) O(L2) (相对 L L L);RoPE 本身是 按维、按位置的轻量三角函数/旋转 ,相对 Q K ⊤ QK^\top QK⊤ 开销通常较小。

2.3.4 Gemma 1 语境下的小结
  • 预训练长度 公开为 8192 :RoPE 的 基频、缩放 等在该长度附近最优;更长序列是否外推、是否改配置,以 checkpointconfig.json(如 max_position_embeddingsrope_theta 等字段)为准。
  • 7B:16 头 × 256 维2B:8 头 × 256 维 :每个头各自有一组 Q ′ , K ′ Q',K' Q′,K′,RoPE 按头维 d k = 256 d_k=256 dk=256 作用 ,与 d model d_{\text{model}} dmodel 是否为 2048/3072 无矛盾(投影矩阵把 d model d_{\text{model}} dmodel 映到 h ⋅ d k = d model h\cdot d_k=d_{\text{model}} h⋅dk=dmodel)。

🔍 实际例子(7B, L = 4096 L=4096 L=4096) :某头内 Q ′ , K ′ Q',K' Q′,K′ 均为 4096×256 , S S S 为 4096×409628 层 每层都重新对当层 Q , K Q,K Q,K 套 RoPE,不是只在第一层做一次。
💡 理解要点 :Gemma 1 的「位置」不进 X X X不进 V V V 的 RoPE (常见实现);只扭转 Q , K Q,K Q,K 再点积 ,从而在 logits 层之前 就让人头看见顺序。与 LLaMA 在 RoPE 套路上同族;差异主要在 层数、头数、 d model d_{\text{model}} dmodel、FFN(GeGLU vs SwiGLU)、2B 的 MQA ,以及 RoPE 超参 以各自 config 为准。

更深推导 (相对位置为何出现在点积里、YaRN 等长文外推):见 33_ROPE.md

2.4 小结:进入 Decoder 堆叠层之前的矩阵

  • 输入 : X ∈ R L × d model X \in \mathbb{R}^{L \times d_{\text{model}}} X∈RL×dmodel, 来自 embed_tokens(无正弦 PE 相加)。
  • L L L 与上下文 :预训练序列长度 8192;推理/微调时可按实现与位置编码外推策略截断或扩展。

自本节之后,第 3、4 节GemmaDecoderLayer 内部顺序 拆开:先写 第一子层(自注意力块) ,再写 第二子层(前馈块) ;两者都是 Pre-Norm归一化发生在子层内部最前端 ,再进 self_attnmlp


3. Decoder 单层 · 第一子层:带掩码的多头自注意力(含 Pre-Norm)

GemmaDecoderLayer第一子层 在模块顺序上对应:input_layernormself_attn → 与本子层输入的残差 。不要把 RMSNorm 想成与注意力「无关的另一章」------在 Pre-Norm 里,它是 进入 W Q , W K , W V W_Q,W_K,W_V WQ,WK,WV 与 RoPE 之前必要第一步

整层骨架(预习)

X mid = X + A t t n B l o c k ( X ) ⏟ 第一子层(本节) , X out = X mid + F F N B l o c k ( X mid ) ( 第二子层,见第 4 节 ) . \underbrace{X_{\text{mid}} = X + \mathrm{AttnBlock}(X)}{\text{第一子层(本节)}}, \qquad X{\text{out}} = X_{\text{mid}} + \mathrm{FFNBlock}(X_{\text{mid}}) \quad (\text{第二子层,见第 4 节}). 第一子层(本节) Xmid=X+AttnBlock(X),Xout=Xmid+FFNBlock(Xmid)(第二子层,见第 4 节).

下面把 AttnBlock 从内到外拆成 五步

3.1 第一步:input_layernorm(RMSNorm)

对子层入口 的矩阵 X ∈ R L × d model X \in \mathbb{R}^{L \times d_{\text{model}}} X∈RL×dmodel 逐行 做 RMSNorm,与 LLaMA 3.1 节 相同:对 x ∈ R d model \mathbf{x} \in \mathbb{R}^{d_{\text{model}}} x∈Rdmodel( X X X 的某一行),

R M S ( x ) = ε + 1 d model ∑ j = 1 d model x j 2 , R M S N o r m ( x ) = x R M S ( x ) ⊙ γ . \mathrm{RMS}(\mathbf{x}) = \sqrt{\varepsilon + \frac{1}{d_{\text{model}}} \sum_{j=1}^{d_{\text{model}}} x_j^2}, \qquad \mathrm{RMSNorm}(\mathbf{x}) = \frac{\mathbf{x}}{\mathrm{RMS}(\mathbf{x})} \odot \boldsymbol{\gamma}. RMS(x)=ε+dmodel1j=1∑dmodelxj2 ,RMSNorm(x)=RMS(x)x⊙γ.

记整表输出为 X ~ = R M S N o r m in ( X ) ∈ R L × d model \tilde{X} = \mathrm{RMSNorm}{\text{in}}(X) \in \mathbb{R}^{L \times d{\text{model}}} X~=RMSNormin(X)∈RL×dmodel。形状不变 ;可学习参数只有缩放 γ ∈ R d model \boldsymbol{\gamma} \in \mathbb{R}^{d_{\text{model}}} γ∈Rdmodel, LayerNorm 常见的平移 β \boldsymbol{\beta} β。

与 Post-Norm 对比Decoder Only Transformer 3.3 节 常见写法是先子层再加残差再 LN;Pre-Norm 是 先 LN/RMSNorm 再进子层,深层堆叠往往更稳。

💡 理解要点 :在 Gemma 1 里,第一子层的第一算子 就是 input_layernorm ;它不属于第二子层 (FFN)。Hugging Face 打印里名字带 post_attention 的 RMSNorm 在 下一节(第 4 节) 才出现。

3.2 第二步:线性投影得到 Q、K、V

在 X ~ \tilde{X} X~ 上施加 W Q , W K , W V W_Q,W_K,W_V WQ,WK,WV(7B 可做成三块大矩阵再按头切分;数学上等价于每头一组矩阵)。以 7B 为例, h = 16 h=16 h=16, d k = 256 d_k=256 dk=256,第 t t t 个头:

Q ( t ) = X ~   W Q ( t ) , K ( t ) = X ~   W K ( t ) , V ( t ) = X ~   W V ( t ) , Q^{(t)} = \tilde{X}\, W_Q^{(t)}, \quad K^{(t)} = \tilde{X}\, W_K^{(t)}, \quad V^{(t)} = \tilde{X}\, W_V^{(t)}, Q(t)=X~WQ(t),K(t)=X~WK(t),V(t)=X~WV(t),

W Q ( t ) , W K ( t ) , W V ( t ) ∈ R d model × d k W_Q^{(t)}, W_K^{(t)}, W_V^{(t)} \in \mathbb{R}^{d_{\text{model}} \times d_k} WQ(t),WK(t),WV(t)∈Rdmodel×dk,故 Q ( t ) , K ( t ) , V ( t ) ∈ R L × d k Q^{(t)}, K^{(t)}, V^{(t)} \in \mathbb{R}^{L \times d_k} Q(t),K(t),V(t)∈RL×dk。

Gemma 1 2B(MQA) : Q Q Q 仍为多路头;K , V K,V K,V 只有一组 共享,详情参考 章节3.5

3.3 第三步:RoPE 作用于 Q、K,再算缩放点积与因果掩码

每个头 的 Q ( t ) , K ( t ) Q^{(t)}, K^{(t)} Q(t),K(t) 在算分数前施加 RoPE ,得到 Q ′ ( t ) , K ′ ( t ) Q'^{(t)}, K'^{(t)} Q′(t),K′(t)(形状仍为 L × d k L \times d_k L×dk)。原理与几何直觉见上文第 2.3 节

S ( t ) = Q ′ ( t ) ( K ′ ( t ) ) ⊤ d k + M , M i j = { 0 j ≤ i − ∞ j > i . S^{(t)} = \frac{Q'^{(t)} (K'^{(t)})^\top}{\sqrt{d_k}} + M, \quad M_{ij}=\begin{cases}0 & j\le i \\ -\infty & j>i\end{cases}. S(t)=dk Q′(t)(K′(t))⊤+M,Mij={0−∞j≤ij>i.

h e a d ( t ) = s o f t m a x ( S ( t ) )   V ( t ) ∈ R L × d k . \mathrm{head}^{(t)} = \mathrm{softmax}(S^{(t)})\, V^{(t)} \in \mathbb{R}^{L \times d_k}. head(t)=softmax(S(t))V(t)∈RL×dk.

V ( t ) V^{(t)} V(t) 使用 未乘 RoPE 的投影输出(标准实现),只是 Q , K Q,K Q,K 在进入点积前多了旋转

形状 (7B): S ( t ) ∈ R L × L S^{(t)} \in \mathbb{R}^{L \times L} S(t)∈RL×L;若 L = 4096 L=4096 L=4096,单头注意力矩阵为 4096×4096

3.4 第四步:多头拼接与输出投影 W O W_O WO

C o n c a t = C o n c a t ( h e a d ( 1 ) , ... , h e a d ( h ) ) ∈ R L × d model , A t t n O u t = C o n c a t   W O ,    W O ∈ R d model × d model . \mathrm{Concat} = \mathrm{Concat}(\mathrm{head}^{(1)},\ldots,\mathrm{head}^{(h)}) \in \mathbb{R}^{L \times d_{\text{model}}}, \quad \mathrm{AttnOut} = \mathrm{Concat}\, W_O,\; W_O \in \mathbb{R}^{d_{\text{model}} \times d_{\text{model}}}. Concat=Concat(head(1),...,head(h))∈RL×dmodel,AttnOut=ConcatWO,WO∈Rdmodel×dmodel.

博文 7Bq_proj / k_proj / v_projout_features 均为 4096 = 16 × 256 16 \times 256 16×256o_proj 映回 3072来源:Gemma explained 博文

3.5 Gemma 1:7B(MHA)2B(MQA)

MHA = Multi-Head Attention(多头注意力)MQA = Multi-Query Attention(多查询注意力,多组 Q 共享少量 KV)

7B:MHA --- 每个头自有 一套 K、V 投影;推理 KV cache 随头数 h h h 增长。与 LLaMA-2 7B 同属 MHA 家族(维度不同);不是 GQA(Grouped-Query Attention,分组查询注意力)。

2B:MQA --- 多个 Query 头共享 一组 K、V(博文:k_proj/v_proj out_features=256q_proj 2048=8×256 )。省参、省 KV cache;表达上让多个 Q「看同一套记忆」。

项目 标准描述(10 号文) Gemma 1 7B Gemma 1 2B
头与 KV 常设 MHA MHA(多头注意力) MQA(多查询注意力),单组 KV
位置 嵌入 + PE 或变体 RoPE(Q,K) 同左
掩码 因果 因果 因果

3.6 第五步:残差 --- 第一子层输出

残差连回的是「进入 input_layernorm 之前」的 X X X (不是 X ~ \tilde{X} X~):

X mid = X + A t t n O u t ∈ R L × d model . X_{\text{mid}} = X + \mathrm{AttnOut} \in \mathbb{R}^{L \times d_{\text{model}}}. Xmid=X+AttnOut∈RL×dmodel.

至此,第一子层 结束; X mid X_{\text{mid}} Xmid 作为 第二子层(第 4 节) 的输入。


4. Decoder 单层 · 第二子层:前馈网络 GeGLU(含 Pre-Norm)

第二子层 对应:post_attention_layernormmlp(GeGLU)→ 与 X mid X_{\text{mid}} Xmid 的残差 。顺序上紧接 3.6 节 的输出。

4.1 第一步:post_attention_layernorm(RMSNorm)

对 X mid ∈ R L × d model X_{\text{mid}} \in \mathbb{R}^{L \times d_{\text{model}}} Xmid∈RL×dmodel 再做一次 RMSNorm另一组 γ \boldsymbol{\gamma} γ 参数,与 input_layernorm 不共享):

X ~ ff = R M S N o r m post ( X mid ) ∈ R L × d model . \tilde{X}{\text{ff}} = \mathrm{RMSNorm}{\text{post}}(X_{\text{mid}}) \in \mathbb{R}^{L \times d_{\text{model}}}. X~ff=RMSNormpost(Xmid)∈RL×dmodel.

(下文公式里简记输入为 X ~ ff \tilde{X}_{\text{ff}} X~ff。)

💡 理解要点两个 RMSNorm 各司其职:一个 只服务自注意力 ,一个 只服务 FFN ;这是 Pre-Norm Transformer 块的标准拆分,避免把「归一化」写成脱离子层的孤立章节。

4.2 第二步:GeGLU(门控 + 上投影 + 下投影)

GLU 与「门控」在指什么?
GLU(Gated Linear Unit,门控线性单元) 把前馈拆成 两路并行投影 ,再 逐元素相乘 合成一路,形如「一路决定开多大的门 、一路是要通过的内容 」。记号上常写作 G L U ( a , b ) = a ⊙ σ ( b ) \mathrm{GLU}(a,b)=a\odot\sigma(b) GLU(a,b)=a⊙σ(b) 一类变体;哪一路过激活、哪一路当"门" 依具体变体(GEGLU、SwiGLU 等)而定。

GeGLU 里(Gemma 博文与实现命名):

  • up_proj :把 X ~ ff \tilde{X}_{\text{ff}} X~ff 投到中间维,得到 U U U ,可理解为 "候选内容 / 值支路"(value branch)。
  • gate_proj :同样从 X ~ ff \tilde{X}_{\text{ff}} X~ff 投到 同宽 中间维,得到 G G G ,再经 G E L U ( ⋅ ) \mathrm{GELU}(\cdot) GELU(⋅)GELU 是光滑、可导的非线性,输出可看作每个维度的 连续"门限"或增益绝对值大的分量更容易被保留,小的被压小 ,从而 按位置、按维度 决定 U U U 里哪些成分参与后续计算------这就是常说的 门控(gating) :不是标量 0/1,而是 与 U U U 同形状的逐元素权重幕布
  • 合成 H = G E L U ( G ) ⊙ U H = \mathrm{GELU}(G) \odot U H=GELU(G)⊙U 后,再 down_proj 压回 d model d_{\text{model}} dmodel,相当于在「已被门控筛选过的」宽特征上做读出。

🔍 直觉类比 :可以把 G E L U ( G ) \mathrm{GELU}(G) GELU(G) 想成一排 连续可调的百叶窗 :每个维度一扇;U U U 是窗外进来的光,逐元素乘 之后,有的缝开大一点(信息通过多),有的小一点。比单层 ReLU MLP 多了一条 专门学"怎么开闭"的支路 ,表达能力更强。来源:GLU Variants Improve Transformer;Gemma explained 博文对 GeGLU 的说明

全称GeGLU = GELU-Gated Linear Unit(用 GELU 作门控非线性的门控线性单元)

7B 模型

  • gate_proj: Linear(3072, 24576)
  • up_proj: Linear(3072, 24576)
  • down_proj: Linear(24576, 3072)

批量矩阵形式 ( X ~ ff ∈ R L × d model \tilde{X}{\text{ff}} \in \mathbb{R}^{L \times d{\text{model}}} X~ff∈RL×dmodel,intermediate_size 记为 d ff d_{\text{ff}} dff):

U = X ~ ff   W up , G = X ~ ff   W gate , H = G E L U ( G ) ⊙ U , F F N O u t = H   W down . U = \tilde{X}{\text{ff}}\, W{\text{up}}, \quad G = \tilde{X}{\text{ff}}\, W{\text{gate}}, \quad H = \mathrm{GELU}(G) \odot U, \quad \mathrm{FFNOut} = H\, W_{\text{down}}. U=X~ffWup,G=X~ffWgate,H=GELU(G)⊙U,FFNOut=HWdown.

激活在实现中常标 PytorchGELUTanh()形状 : F F N O u t ∈ R L × d model \mathrm{FFNOut} \in \mathbb{R}^{L \times d_{\text{model}}} FFNOut∈RL×dmodel。

博文表 49152 与两路 24576 的对照、2B 的中间维 d ff d_{\text{ff}} dff 等,以 config.json / print(model) 为准。

4.3 与 LLaMA(SwiGLU)的差异

项目 LLaMA(常见) Gemma 1
门控非线性 Swish / SiLU GELU(GeGLU)
结构 gate+up+down gate_proj + up_proj + down_proj

二者均属 GLU 族;差异在门函数与具体中间维。

4.4 第三步:残差 --- 整层输出

X out = X mid + F F N O u t ∈ R L × d model . X_{\text{out}} = X_{\text{mid}} + \mathrm{FFNOut} \in \mathbb{R}^{L \times d_{\text{model}}}. Xout=Xmid+FFNOut∈RL×dmodel.

X out X_{\text{out}} Xout 作为 下一 Decoder 层 的输入;N N N 层 (2B 为 18,7B 为 28)重复 第 3--4 节 所述块。


5. 输出层:lm_head 与 Softmax

最后一层堆叠输出 H ∈ R L × d model H \in \mathbb{R}^{L \times d_{\text{model}}} H∈RL×dmodel。自回归训练/推理常针对「下一个 token」位置取对应行向量 h ∈ R d model \mathbf{h} \in \mathbb{R}^{d_{\text{model}}} h∈Rdmodel(或对所有位置并行算 logits),与 Decoder Only Transformer 第 4 节 一致:

z = h   W lm , W lm ∈ R d model × V , P = s o f t m a x ( z ) . \mathbf{z} = \mathbf{h}\, W_{\text{lm}}, \quad W_{\text{lm}} \in \mathbb{R}^{d_{\text{model}} \times V}, \quad P = \mathrm{softmax}(\mathbf{z}). z=hWlm,Wlm∈Rdmodel×V,P=softmax(z).

博文摘录中 7Blm_headLinear(3072, 256000);实际词表常为 256128 ,以权重为准。是否 tie(与 E E E 共享) 以实现与训练配置为准。

💡 与技术报告 / 实现 :若启用 attention logits soft-capping 等稳定技巧,以对应版本 modeling_gemma 代码为准(非本入门篇展开重点)。


6. 训练与推理流程(简叙)

Decoder Only Transformer 第5节 一致:

  • 训练 :Teacher Forcing + 因果掩码,一次前向可算所有位置的下一词损失。
  • 推理 :自回归循环, L L L 随步数增加;2B(MQA)KV cache 上相对 7B(MHA) 更省。

7. 参数量量级(便于与 LLaMA 文对照)

以下给出常用公式 (Gemma 注意力实现中常 bias=False )。设 d = d model d=d_{\text{model}} d=dmodel, d ff d_{\text{ff}} dff 为 intermediate_size(单路隐藏维,GeGLU 两路同宽再逐元素乘)。

7.1 单层(7B 量级,MHA)

  • 注意力 : W Q , W K , W V W_Q,W_K,W_V WQ,WK,WV 各约 d × d d \times d d×d, W O W_O WO 为 d × d d \times d d×d → 约 4 d 2 4d^2 4d2(与多头切分方式等价)。
  • FFN(GeGLU) : W gate , W up W_{\text{gate}}, W_{\text{up}} Wgate,Wup 各 d × d ff d \times d_{\text{ff}} d×dff, W down W_{\text{down}} Wdown 为 d ff × d d_{\text{ff}} \times d dff×d → 2 d   d ff + d ff   d 2 d\, d_{\text{ff}} + d_{\text{ff}}\, d 2ddff+dffd (与 LLaMA 8 节 SwiGLU 计数同型)。
  • RMSNorm :两处各 γ \boldsymbol{\gamma} γ 维 d d d → 2 d 2d 2d

7.2 单层(2B,MQA)

  • Q :仍可到 d × d d \times d d×d(或等价分头拼接)。
  • K/V :投影到 单组 KV(宽度远小于 2 d 2 2d^2 2d2 的 MHA 情形),显著减少 K/V 侧参数与缓存。

嵌入与 lm_head 各约 V ⋅ d V \cdot d V⋅d 量级(若 tie 则只计一次)。

🔍 实际例子 : d = 3072 d=3072 d=3072,单层 注意力 约 4 d 2 ≈ 3.77 × 10 7 4d^2 \approx 3.77 \times 10^7 4d2≈3.77×107;28 层 堆叠后,主参数体量仍集中在 FFN 与嵌入/输出层


8. 总览对照表:Gemma 1 vs 经典 Decoder vs LLaMA

维度 经典 Decoder-only LLaMA Gemma 1
位置 嵌入 + 正弦/可学习 PE RoPE(Q,K),无嵌入 PE 同 LLaMA
归一化 LayerNorm(Post-Norm 常见) RMSNorm + Pre-Norm 同 LLaMA
FFN ReLU 两段 SwiGLU GeGLU
7B 注意力 多为 MHA MHA(7B) MHA
2B 注意力 --- 依系列而定 MQA
词表 因模型而异 如 32K 256K + SentencePiece
上下文(公开训练) 因模型而异 如 4K/8K+ 8192

9. 小结

  • Gemma 1 = Decoder-only + Pre-Norm RMSNorm + RoPE + GeGLU FFN + 因果掩码自注意力7B 用 MHA2B 用 MQA
  • 每一层 (第 3--4 节):第一子层 = input_layernorm + 掩码多头注意力 + 残差;第二子层 = post_attention_layernorm + GeGLU + 残差。
  • 数据流:SentencePiece ID嵌入 L × d L \times d L×d → 重复 N N N 层上述两块 → lm_headSoftmax
  • LLaMA 最近的差别在 GeGLU vs SwiGLU2B 的 MQA ;与 原版 Transformer Decoder 的差别在 无嵌入绝对 PE、RMSNorm、门控 FFN

结合 Decoder Only Transformer 的矩阵推演与 LLaMA 架构 的 RoPE/RMSNorm 表述阅读本文,可将 Gemma 1 完全纳入同一套「可算、可对表」的知识框架。后续代际(如更长上下文、混合注意力、多模态)见 Gemma 4 架构


💡 总结 :读 Gemma 1 时抓住三条------RoPE 不进嵌入FFN 用 GeGLU小模型用 MQA 省 KV。其余仍是标准自回归 Transformer 的「缩放点积 + 因果掩码 + 残差」故事。

相关推荐
Kel10 分钟前
Claude Code 架构深度剖析:从终端输入到大模型响应的完整过程
人工智能·设计模式·架构
taWSw5OjU23 分钟前
从模型评估、梯度难题到科学初始化:一步步解析深度学习的训练问题
人工智能·深度学习
刘佬GEO24 分钟前
【无标题】
网络·人工智能·搜索引擎·ai·语言模型
用户20187928316731 分钟前
/export之一个程序员与AI的“破案笔记”
人工智能
Ricardo-Yang38 分钟前
SCNP语义分割边缘logits策略
数据结构·人工智能·python·深度学习·算法
新缸中之脑1 小时前
微调BERT进行命名实体识别
人工智能·深度学习·bert
用户2018792831671 小时前
故事:小白的“无限循环”噩梦与大师的 /loop 魔法
人工智能
段小二1 小时前
Token 费用失控、VIP 用户体验一样烂:Context Engineering 才是关键
人工智能·后端
用户2018792831671 小时前
/branch 你点了一份代码,Cli 帮你分成了两碗
人工智能
kishu_iOS&AI1 小时前
机器学习 —— 线性回归
人工智能·机器学习·线性回归