一句话总结:神经网络本质上就是矩阵乘法加激活函数。理解 Transformer 不需要深入神经网络细节,只需要知道它是一个"输入 → 处理 → 输出"的黑盒子。
7.1 先说结论:你不需要"懂"神经网络
在深入之前,我想先打消你的顾虑:
理解 Transformer 和大模型,不需要成为神经网络专家。
为什么?因为神经网络在 Transformer 中扮演的角色其实很简单——就是一个"处理器",把输入变成输出。你需要知道的是:
- 输入是什么形状
- 输出是什么形状
- 中间有一些可学习的参数
至于里面具体怎么算的?对于理解 Transformer 来说,可以当作黑盒子。
当然,如果你想深入了解,这一章也会给你足够的直觉。
7.2 神经网络的灵感:人脑
7.2.1 生物神经网络
如果只看数量级,人脑大约有:
- 约 860 亿个神经元:这是对成人大脑的实验估计
- 约 10¹⁴ 个突触:也就是约 100 万亿个连接;这个数字是数量级估计,并不精确
神经元通过电信号相互传递信息。当一个神经元接收到足够多的输入信号时,它会"激活"并向下游神经元发送信号。
7.2.2 人工神经网络
人工神经网络(Artificial Neural Network)受到了生物神经网络的启发,但更准确地说,它是一种数学抽象:
- 节点:模拟神经元
- 连接:模拟突触,每个连接有一个"权重"
- 激活函数:把加权结果做一次非线性变换,不一定是“超过阈值才开启”
但请注意:人工神经网络和真正的大脑差别很大。它只是借用了"神经网络"这个名字,实际上是一种数学模型。
7.3 神经网络能做什么?
7.3.1 学习"特征"
神经网络的厉害之处在于:我们不必手写“先找哪条边、再看哪个角”这样的规则,它可以从训练信号中学出有用的特征。
看这张图(MNIST 手写数字的二维概念图):
- 每个点代表一张 28×28 像素、也就是 784 维的图片
- 网络内部的高维表示再用 t-SNE、UMAP 等方法投影到 2D
- 训练良好的分类器里,相同数字的表示往往会靠近;但二维布局会随模型和投影方法改变
0 聚在一起,1 聚在一起,2 聚在一起...
如果训练的是分类器,标签当然会告诉模型“这张是 0、那张是 1”。没有被手工写进去的,是“0 必须由哪几个像素规则组成”。模型通过训练自己学出了能区分数字的表示。
7.3.2 这和 LLM 有什么关系?
同样的原理用在语言上:
- 神经网络学会了哪些词经常一起出现
- 学会了句子的语法结构
- 学会了词语的语义关系
最终,不同 token 在不同上下文中的内部表示会呈现某些语义和语法结构。不过,“两个词一定很近或很远”不是固定规则,因为表示会随着上下文、层数和模型而变化。
7.4 神经网络的基本结构
7.4.1 三层结构
教科书最常画的是“三层结构”:
- 输入层(Input):接收原始数据
- 隐藏层(Hidden Layer):进行中间变换
- 输出层(Output):把隐藏表示变成最终结果
这只是一张方便入门的示意图。网络可以没有隐藏层,也可以有很多隐藏层;而且隐藏层、输出层都可以有可学习的权重。
7.4.2 一个直观的例子
假设输入是一件商品的向量,隐藏层可能学出“防水程度”“保暖程度”“重量”等内部特征,输出层再预测它属于雨衣、冬装还是其他类别。
这就是神经网络的本质:从输入中提取特征,然后做出判断。
7.5 数学本质:矩阵乘法
7.5.1 一切都是矩阵乘法
神经网络的核心计算是仿射变换:矩阵乘法,再加一个偏置。
看图中的例子:
输入向量 × 权重矩阵 = 输出向量
[0.54, 0.84] × [w1 w3] + [b1, b2] = [0.91, 0.90]
[w2 w4]
这里把输入写成行向量,所以形状是 [1, 2] @ [2, 2] = [1, 2]。如果把输入写成列向量,乘法顺序就要反过来:W @ x。两种记法都可以,但不能把 [2,1] @ [2,2] 混在一起。
7.5.2 可视化理解
同样的过程也可以画成“网络图”:
- 左边两个蓝色节点(0.54, 0.84)是输入
- 右边两个粉色节点(0.91, 0.90)是输出
- 中间的线是权重(w1, w2, w3, w4)
每个输出节点的值 = 所有输入 × 对应权重的总和。
7.5.3 多层神经网络
把这样的变换和非线性函数反复堆叠,就得到多层网络:
- Layer 1(蓝色)→ Layer 2(橙色)→ Layer 3(绿色)→ Layer 4(红色)
- 每个可学习层先做一次仿射变换;隐藏层之间再插入非线性函数
- 层数越多,网络越"深"(这就是"深度学习"名字的由来)
7.6 PyTorch 实现
7.6.1 代码示例
# 代码示例
import torch.nn as nn
model = nn.Sequential(
nn.Linear(2, 3), # 输入层到隐藏层:2维 → 3维
nn.ReLU(), # 激活函数
nn.Linear(3, 1) # 隐藏层到输出层:3维 → 1维
)
这段代码定义了一个简单的神经网络:
nn.Linear(2, 3):一个线性层,把 2 维输入变成 3 维输出nn.ReLU():激活函数,增加非线性nn.Linear(3, 1):把 3 维变成 1 维输出
7.6.2 矩阵维度变化
输入 (1,2) → Linear(2,3) → 隐藏层 (1,3) → Linear(3,1) → 输出 (1,1)
理解维度变化是理解神经网络的关键:
- 矩阵乘法规则:
(a,b) @ (b,c) = (a,c)
这里有一个容易踩坑的细节:为了计算方便,我们常把概念公式写成 x @ W,其中 W 是 [in, out]。但 PyTorch 的 nn.Linear(in, out) 实际把 weight 存成 [out, in],前向计算是 x @ weight.T + bias。
7.6.3 激活函数
你可能注意到了 nn.ReLU()。这是激活函数,它的作用是增加"非线性"。
如果没有激活函数,多层矩阵乘法可以合并成一层(线性变换的组合还是线性变换)。激活函数让网络能学习更复杂的模式。
ReLU 是最容易理解的激活函数之一,规则很简单:
ReLU(x) = max(0, x)
正数不变,负数变成 0。
不是每个 Linear 后面都必须接激活函数。传统 FFN 把激活放在两次投影之间;GPT-2 使用 GELU,Llama 2 的门控 FFN 使用 SiLU/SwiGLU。
7.7 在 Transformer 中的神经网络
7.7.1 Feed Forward Network
在 Transformer 中,神经网络层被称为 Feed Forward Network(FFN,前馈网络) 或 全链接网络层。
FFN 接收每个 token 的向量,并返回同样 d_model 宽度的新向量。它不会直接输出“下一个 token 的概率”;那是最后的 LM Head 和解码步骤负责的事。
7.7.2 Transformer Block 结构
图中左下角展示了 Transformer Block 的结构:
Norm(LayerNorm 或 RMSNorm)
↓
Masked Multi-Head Attention
↓
Dropout + 残差连接
↓
Norm(LayerNorm 或 RMSNorm)
↓
Feed Forward(神经网络层)← 就是这里!
↓
Dropout + 残差连接
Feed Forward 是每个 Block 的重要组成部分,和 Attention 交替出现。
7.7.3 两种常见 FFN
原始 Transformer 和 GPT-2 风格的 FFN,通常是两次投影,中间放一个激活函数:
model = nn.Sequential(
nn.Linear(d_model, 4 * d_model),
nn.GELU(),
nn.Linear(4 * d_model, d_model),
)
这里的 4 × d_model 是经典配置,不是铁律。Llama 2 使用 SwiGLU:gate、up、down 三个矩阵共同完成门控变换,d_ff = 11008,并不等于 4 × 4096。
7.8 参数都在哪里?
7.8.1 哪些地方有参数?
沿着 Transformer 走一遍,主要参数会出现在这些地方:
- 文字转数字(Embedding):词表大小 × 向量维度
- 全链接网络层(FFN):两到三个投影矩阵,形状取决于 FFN 设计
- Norm:LayerNorm 通常有
γ、β;RMSNorm 通常只有 scale - Attention:Q、K、V、O 投影;MHA、MQA、GQA 的 K/V 形状并不相同
- LM Head(最终 Linear):向量维度 × 词表大小;有些模型与 Embedding 共享,有些不共享
7.8.2 参数量估算
对于一个典型的 Transformer:
| 组件 | 参数量公式 | Llama 2 7B 示例 |
|---|---|---|
| Embedding | vocab × d_model | 32000 × 4096 ≈ 1.3亿 |
| FFN(每层) | 3 × d_model × d_ff * | 3 × 4096 × 11008 ≈ 1.35亿 |
| Attention(每层) | 4 × d_model² | 4 × 4096² ≈ 0.67亿 |
| RMSNorm(每层) | 2 × d_model | 两个 scale 向量,共 8192 个参数 |
| LM Head | d_model × vocab | 4096 × 32000 ≈ 1.3亿,与输入 Embedding 不共享 |
*Llama 2 使用 SwiGLU,需要 3 个矩阵(gate、up、down),而非传统 FFN 的 2 个矩阵。上表为了看主量级省略了 bias;Llama 2 这些 Linear 本身也不使用 bias。
FFN 占了大部分参数! 这是一个常被忽视的事实。
7.8.3 一个有趣的观察
很多人以为 Attention 是 Transformer 的"主角",参数最多。但实际上:
- 在 Llama 2 7B 这个例子里,FFN 每层约 1.35 亿,MHA 约 0.67 亿,刚好约 2 倍
- 一个好用的直觉是:Attention 负责跨位置路由和混合信息,FFN 负责对每个位置做非线性变换
有研究把 FFN 解释成一种 key-value memory,并在其中观察、编辑过事实关联。这是一个很有用的观察角度,但不能推出“知识只住在 FFN”。Embedding、Attention、FFN 和残差流都共同参与模型行为,知识是分布式的。
7.9 本章总结
7.9.1 核心认知
| 概念 | 解释 |
|---|---|
| 神经网络 | 输入 → 矩阵乘法 → 激活函数 → 输出 |
| 层 | 一次带参数的变换;是否接激活函数要看它在网络中的位置 |
| 参数 | 矩阵中的数字,通过训练学习 |
| FFN | Transformer 中的神经网络层 |
7.9.2 记住这个公式
一个带激活函数的隐藏层:
输出 = 激活函数(输入 × 权重 + 偏置)
用 PyTorch 表示:
nn.Linear(in_features, out_features) # 线性层
nn.ReLU() # 激活函数
7.9.3 你只需要知道的
- 形状变化:FFN 中间扩宽,最后回到
d_model;具体扩宽比例由架构决定 - 可学习参数:权重矩阵是训练出来的
- FFN 的位置:在每个 Transformer Block 中,和 Attention 交替出现
- FFN 很重要:很多 dense Transformer 里,它每层的参数量大约是 MHA 的 2 倍,也承载了大量学到的模式
神经网络就是仿射变换与非线性的堆叠。理解 Transformer 不需要钻进所有细节,把 FFN 当作一个“逐 token 处理器”就够了:输入、输出都是
d_model,中间先扩宽再缩回。
本章交付物
学完这一章,你应该能够:
- 解释神经网络的基本结构(输入层、隐藏层、输出层)
- 理解神经网络本质是矩阵乘法
- 知道 FFN 在 Transformer Block 中的位置
- 了解参数主要分布在哪些组件中
Part 2 总结
恭喜你完成了 Part 2:核心组件!
让我们回顾一下学到的内容:
| 章节 | 组件 | 核心作用 |
|---|---|---|
| 第4章 | Tokenization + Embedding | 文字 → Token ID → 向量 |
| 第5章 | Positional Encoding | 给向量添加位置信息 |
| 第6章 | LayerNorm + Softmax | 数字缩放 + 数字变概率 |
| 第7章 | 神经网络层(FFN) | 逐位置变换 token 表示 |
现在你已经理解了 Transformer 的所有"配件"。下一个 Part,我们将进入最核心的部分:Attention 机制——Transformer 真正的灵魂。
下一章预告
Part 3 的第一章(第 8 章),我们要先补一个数学基础:线性变换的几何意义。
这是理解 Attention 的关键。我们会用可视化的方式,让你真正"看懂"矩阵乘法在做什么。
准备好了吗?让我们进入 Attention 的世界!