11.2 线性层:一次矩阵乘法
本节位置:模块 11 · 大模型专题 | 前置:3.3 | 预计:35 分钟
一句话:线性层就是「把每个 token 的向量,用同一个矩阵混合成新向量」;大模型的大部分参数和算力都花在这里。
0. 场景引入
一台 8 GB 内存的轻薄本,离线跑一个 3B 参数的模型,把 40 分钟的会议录音转写稿压成一段摘要。NPU 标称 20 TOPS,机身内存带宽约 50 GB/s。
先看权重。压到 4 bit,模型占 GB。生成每一个 token,都要把这 1.5 GB 从头读一遍: 毫秒。算力那边呢?每个 token 约 GFLOPs,20 TOPS 只要 0.3 毫秒。两者差 100 倍——端侧推理的时间几乎全花在搬权重上,不在算乘加上。
顺带说清参数从哪来:取 的模型,一层 FFN 的形状是 ,参数 ;32 层就是 43 亿,而 embedding 才 5 亿——参数的大头在 FFN 的矩阵里,也正是要反复搬的那些字节。
再看输入。转写稿 6000 汉字,按 1.5 字/token 估约 4000 token,加系统提示共 4200;摘要要求 400 token。
于是要做一个决策:权重用 4 bit 还是 8 bit?4 bit 每 token 30 毫秒、400 token 共 12 秒,但量化会掉点;8 bit 每 token 60 毫秒、共 24 秒,而且 3 GB 权重加 1.4 GB KV 缓存后,机器几乎没有余量再开浏览器。代价必须挑一个:要么接受「摘要里的数字和人名偶尔走样」,要么接受「每次等半分钟」。
还有一笔账要分开算:prefill 那 4200 个 token 是算力瓶颈, FLOPs 按 8 TOPS 估约 3 秒;首 token 的等待和后面 12 秒的生成,堵点根本不在同一处。
读完本节,你能回答的三个问题是:
- 怎么用一行算术判断端侧 decode 卡的是带宽还是算力?
- 偏置只占总参数的万分之一点五,为什么删掉它模型会系统性偏移?
- 同一个线性层,prefill 和 decode 的算术强度差多少倍?
1. 直觉
一个线性层有 个「检测器」。每个检测器是一行权重 ,它和输入 做点积:
点积大,说明输入与这个检测器方向一致——这一维被「激活」。这个「加权和 + 偏置 + 阈值」的单元就是 感知机;线性层是它去掉阶跃、直接输出连续值的版本。
所以线性层在做特征重组:把输入的 个方向,重新组合成 个新方向。
💡 一句话直觉:线性层 = 一组并行的点积 = 把向量投影到 个学到的方向上。
类比边界:单个线性层只能做线性组合,不能做「如果……就……」;非线性来自后面的 GELU/ReLU/SwiGLU。
1.1 它在现实世界里对应什么
物理对应:线性层是一台「多进多出的配料机」—— 个进料口各按一个可调阀门开度(权重)汇进 个出料口,每个出料口都尝一遍所有原料,再各自加一点底味(偏置)。
工程上它只有一个形状:GEMM。判断它卡算力还是卡带宽,算算术强度(每搬 1 字节做几次浮点运算):
单 token()时 ;而一块 GPU 的 roofline 拐点在 200–400 FLOP/byte。也就是说,decode 时这个矩阵的算力利用率只有峰值的 1/300 量级,时间几乎全在等内存。 时 AI 约 227,才刚够到拐点——这就是「batch 越大越划算」的全部数学。
这个类比在哪里失效:配料机是一次投料一次出料,而 decode 是「同一套配方反复执行、每次只投一份料」:权重被反复重读,机器空转,只有把 batch 做大才能摊薄这份浪费。另外阀门开度在训练中每步都变,缓存与预取策略必须跟着变,静态流水线的假设在这里不成立。
2. 定义
2.1 单个向量
按 PyTorch 约定,权重形状为 :
(有的教材写 ,等价,只是行/列约定不同。)
2.2 批量
对 :
框架会把 展平成「行」,做一次大矩阵乘:
2.3 FFN
常见结构:
其中 ,, 是 GELU/ReLU/SiLU。
2.4 参数量与计算量
| 量 | 公式 |
|---|---|
| 参数 | |
| 前向 FLOPs(batch 、序列 ) | |
| 仅推理单 token |
(乘加算 2 次浮点运算。)
3. 为什么这样定义
为什么用矩阵而不是逐元素? 逐元素操作(如乘一个标量)无法混合不同维度;矩阵乘法让每个输出都看到所有输入,实现「特征交叉」。
为什么 FFN 要先升维再降维? 升维提供一个更宽的空间,让非线性(GELU)可以在更高维里「切开」特征,再压回原维度。这类似「在更高维空间做分类再投影回来」。 是 Transformer 定下的经验选择,不是定理。
为什么大模型离不开它? 矩阵乘法可以被 GPU 高效并行(GEMM,第 10.3 节);同样的参数量,用矩阵乘比循环/条件分支快几个数量级。
3.1 反事实:删掉偏置、或把顺序调换会坏在哪
先删偏置。 偏置提供的唯一自由度是「与输入无关的常数」,而它的真实作用是给每个隐藏单元设一个开关点。取 、,输入 ,:
幅度变了不算要害,要害在后面的 GELU。一个通道的线性输出如果是 ,(负值只被保留了一部分);同样这个通道,只要有个 的偏置把它抬到 ,,符号都反了。FFN 有 个这样的通道,每个偏置就是它的开关点。全部抹掉,等于所有通道共用开关点 0,而 LayerNorm 后的输入是零均值的:一半通道永远活在负半轴,哪一半是哪个由初始化随机决定,训练只能靠调 的范数间接挪动开关点。
参数账很不对称:一层 FFN 的偏置是 个,占 的 0.015%。删它省不下存储,却要模型拿隐藏状态的整个方向去重建这个常数。输出层(unembedding)的偏置更不能删:它承载词频先验,没有它,softmax 没有任何办法表达「『的』比『貘』常见一万倍」。
再换顺序。 正确写法是 :先线性,后非线性。若写成 ,取 、:
同一组数,正确顺序下这个检测器沉默(两个特征相消),错误顺序下它一直在开火。原因一句话: 的价值就在于能做减法,而 GELU 不是线性的,。把非线性提前,等于先毁掉「相消」再做加权;堆到 32 层,每层都多注入一点整流后的正偏,误差就不是「小一点」,而是整个输出分布的漂移。
4. 性质与推导
4.1 复合仍是线性(若无非线性)
所以两层线性层等价于一层。非线性是深度有意义的前提。
4.2 参数量估算
FFN:。 Attention 的四个投影:。 每层合计 , 层 。
对 :,即 64 亿参数(不含 embedding)。
4.3 计算量估算
单 token 前向:
对 :约 FLOPs/token。生成 1000 个 token 约 FLOPs。
4.4 初始化
若输入各分量方差为 1、权重方差为 ,输出方差约为 。为了让输出方差保持 1,取
这就是 Xavier 初始化 与 He 初始化 的核心思想(第 10.2、12.2 节)。
5. 例子
5.1 手算: 线性层
5.2 手算:一层 FFN 的参数量
,FFN 为 :
其中 16 个是偏置;相对 的粗估,FFN 部分 ,吻合。
5.3 场景:7B 模型的参数分布
取 :
| 部分 | 参数量 |
|---|---|
| FFN(每层 ) | B |
| Attention(每层 ) | B |
| Embedding(绑定) | B |
| 合计 | 约 6.57B |
实际 7B 模型还会因 GQA、词表大小、层数略有差异。重点不是精确数字,而是「FFN 占大头」这个结构判断。
5.4 场景闭环:4000 token 的会议纪要
输入规模:转写稿 6000 汉字,按 1.5 字/token 估约 4000 token,加系统提示 200,共 4200;输出摘要 400 token。模型 3B 参数、、、FFN 用 SwiGLU 的 。
计算(prefill,):
按 NPU 有效 8 TOPS 估约 3.1 s。这一步的算术强度是 FLOP/byte,远高于拐点——prefill 卡算力。
计算(decode,每 token):
算力上 0.75 ms 就够,读 1.5 GB 却要 30 ms。decode 卡带宽,且卡 40 倍。
输出决策:400 token 摘要;若 logits 熵连续 10 步超过阈值,判定「模型在编」,截断并回退到抽取式摘要(挑原文句子)。
成本:prefill 3.1 s + decode s,合计约 15 s。内存峰值 1.5 GB 权重 + 1.4 GB KV(),int8 KV 后降到 0.7 GB。
失败条件与兜底:
- 内存不足:8 bit 方案 3 GB 权重 + 1.4 GB KV + 运行时约 1.5 GB ≈ 6 GB,在 8 GB 机器上再开浏览器就 OOM。兜底:权重 mmap 分页加载(首 token 慢约 0.5 s),KV 用 int8。
- 有效带宽低于标称:50 GB/s 是峰值,真实随机访问常只有 60%–70%。兜底:按实测带宽重算预算,把「30 ms/token」改成「45 ms/token」再决定摘要长度。
- 4 bit 掉点集中在数字:量化误差对高频数值 token 更敏感。兜底:把金额、日期、人名做后处理校验,与转写稿原文做字符串对齐,对不上就回退长摘要。
6. 常见误区
-
误区: 和 是一回事。 纠正:形状不同。 输出 维列向量; 要求 是行向量,输出行向量。框架内部统一用行向量批量乘 。
-
误区:参数量 = 计算量。 纠正:参数量是存储,计算量还乘 batch/序列长度。推理时每 token 的计算量约 参数量(对线性层)。
-
误区:线性层「存储了知识」。 纠正:知识分布在所有层的权重与非线性交互中,不能简单定位到某一层/某个矩阵;线性层只是变换。
-
误区:FFN 的 是理论最优。 纠正:这是工程经验;不同模型用 、(SwiGLU)、 等,取决于激活函数与效率权衡。
7. 概念网络
- 前置:3.3 矩阵乘法 —— 行乘列/列组合。
- 前置:10.3 GEMM —— 为什么 GPU 快。
- 后续:11.3 Attention QKV —— 四个线性投影。
- 后续:11.8 LoRA —— 用低秩矩阵近似线性层更新。
- 关联:8.5 矩阵求导 —— 反向传播的梯度形状。
8. 通往大模型:线性层出现在哪
| 位置 | 形状 | 说明 |
|---|---|---|
| QKV 投影 | 各一个 | 生成 query/key/value |
| 输出投影 | 合并多头输出 | |
| FFN 上投影 | 升维 | |
| FFN 下投影 | 降维 | |
| LM head | 输出词表 logits | |
| LoRA | 低秩更新 |
GQA/MQA:为了省 KV Cache,让多个 query 头共享一组 key/value 头, 的形状变为 ,。这是「用形状换显存」的典型设计。
可检验结论:对 ,一个 有 个参数,fp16 存储约 32 MiB。四个投影约 128 MiB/层。
算错时用户看到什么:三种错法对应三种症状,可以从输出反推。
- 导出时丢了 :模型不崩,但输出层失去词频先验,罕见词被系统性低估。用户看到「答案越来越模板化」——总用同一批高频词开头,遇到专有名词就含糊其辞。若丢的是 FFN 的 , 个通道的开关点全被钉到 0,表现为「回答变短、细节消失」。
- 非线性放错位置(先 GELU 再投影):小 batch 上 loss 照样降,但「相消」能力没了,输出整体带正偏。用户看到「语气越来越满」——过度自信、爱下结论,长回答比短回答更容易跑偏。
- 累加维度切错(张量并行后忘记 all-reduce):输出幅度按 缩小,经过 LayerNorm 又被重新归一化,形状与量级都「看起来正常」,信息却已丢一半。用户看到「模型像喝了酒」——语法通顺但答非所问。这类错不报 shape mismatch,只让评测分数悄悄掉几个点,最难查。
9. 练习
- 概念:为什么两层线性层叠加等价于一层?这对「深度」意味着什么?
- 计算:,,求参数量、单 token 前向 FLOPs。
- 计算:一个 7B 模型 ,用 估算主体参数量;若 FFN 用 的 SwiGLU,FFN 参数量变为多少?
- 场景:为什么推理时 batch 越大,GPU 利用率越高?用 GEMM 的形状解释。
- 开放:如果去掉所有 FFN,只保留 attention,模型能力会受什么影响?从「特征混合」与「非线性容量」两个角度分析。
参考答案
- ;没有非线性时深度退化为一层,所以必须插入非线性。
- 参数 ;FLOPs 约 M。
- B;SwiGLU 常见总参数量约 每层(三个矩阵、隐藏维 ),约 B(仅 FFN 部分会变,需按具体结构算)。
- GEMM 的 越大,矩阵乘的并行度越高,GPU 越不容易闲置;batch=1 时是「瘦矩阵」,受内存带宽限制。
- 特征混合变弱、非线性容量下降;attention 只做 token 间加权,不做逐 token 的特征变换,表达力显著降低。
10. 一页速记
- 线性层:,批量
[B,T,Din] @ [Din,Dout]。 - 物理意义 / 现实对应:一台可调的加权混合器—— 是配方, 是每个通道的开关点;工程上它就是一次 GEMM,decode 时算术强度约 1 FLOP/byte,卡带宽不卡算力。
- 参数 ;FLOPs 。
- FFN ,每层 ;attention 四个投影 。
- 没有非线性,多层线性坍缩成一层。
- FFN 是参数大户,GEMM 是算力大户。
11. 参考文献与致谢
这一页的知识不是凭空来的。下面列出本页直接借用的原始工作与权威整理;正文中的人名、方法名已链接到对应条目。链接优先指向 DOI、arXiv 或可长期访问的原文存档。
- Vaswani 等(2017):Attention Is All You Need。Transformer 每层由「四个 投影 + FFN 」构成,本页第 4.2 节的 与第 8 节的形状表都是对这套结构的拆解。arXiv:1706.03762
- Rosenblatt(1958):The perceptron: A probabilistic model for information storage and organization in the brain。感知机把输入加权求和、加偏置、再过阈值,是 这种线性单元最早的学习模型。DOI:10.1037/h0042519
- Glorot 与 Bengio(2010):Understanding the difficulty of training deep feedforward neural networks。分析深层前馈网络为何难训练,并给出让各层激活方差保持不变的 Xavier 初始化:权重方差取 ,正是本页第 4.4 节的推导。PMLR v9
- He 等(2015):Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification。针对 ReLU 只保留一半激活的特点,把初始化方差改为 ,即本页提到的 He 初始化。arXiv:1502.01852
下一篇 → 11.3 Attention(上):QKV
随堂测 · 4 题
源文件:11-大模型专题/02-线性层.md