本章前置:读完第 01 章,环境已搭好、跑通过第一段代码。本章不依赖仓库代码,是纯粹的”打地基”,只要你会基本的加减乘除、知道”变量”是什么就行。
你将学到:用最朴素的语言搞懂后面会反复用到的几样东西——标量/向量/矩阵/张量与它们的形状(尤其
(B,T,C))、矩阵乘法的直觉;函数与导数(斜率)、偏导、梯度(指向上升最快的方向)、链式法则(反向传播的核心);概率分布、期望、为什么要用对数和负对数;最后用一个最简单的一维线性回归,完整地走一遍”训练”——亲手推导梯度、用学习率更新参数,第一次直观感受”模型在学习”。👈 上一章:环境搭建与第一次运行 | 返回总览
很多人一听”大模型”,第一反应是”我数学不好,学不来”。别怕。这一章我们只讲真正用得上的那一点点,而且每个公式后面都用大白话拆开讲。你不需要会解微分方程,只需要建立几个直觉:数据长什么样、模型怎么”算错了多少”、又怎么”照着错的方向调一点点”。把这几样想通,后面所有花哨的算法都只是它们的放大版。
读这一章时,请允许自己慢一点。看不懂公式先别慌——先读公式后面的解释,弄明白”它想干嘛”,再回头看符号。
1. 标量、向量、矩阵、张量:数据的形状
机器学习里的数据,本质上都是”一堆数字”。我们按”维度”给它们起名字。
- 标量(scalar):就是一个数。比如温度
36.5、损失值2.31。没有方向、没有排列,孤零零一个。 - 向量(vector):一串排好队的数。比如
[1.0, -0.5, 3.2]。可以把它想成一个箭头,或者”某个东西的一组特征”。我们说它的**长度(维度)**是 3。 - 矩阵(matrix):一个数字表格,有行有列。比如一个 2 行 3 列的矩阵:
这是一个形状为 (2, 3) 的矩阵:2 行、3 列。
- 张量(tensor):把上面的概念推广到任意多维。标量是 0 维张量,向量是 1 维,矩阵是 2 维,再往上就是 3 维、4 维……张量就是”多维数字数组”的统称。PyTorch 里所有数据都是张量,这也是
torch.Tensor名字的由来。
“形状(shape)“是张量最重要的属性,它告诉你”每一维有多大”。形状写成一个括号里的数字元组。比如:
- 形状
():标量。 - 形状
(3,):长度 3 的向量。 - 形状
(2, 3):2×3 的矩阵。 - 形状
(2, 16, 50304):一个 3 维张量——还记得第 01 章那次前向计算的输出吗?就是这个形状。
牢牢记住 (B, T, C)
在这门课里,你会一次又一次看到三维形状 。它几乎是处理文本时的”标准包装”:
- = batch,一批里有几个序列(我们总是一次处理一批,效率高);
- = time / tokens,每个序列有多长(多少个 token);
- = channels / features,每个 token 用多长的向量来表示(也就是第 01 章的
n_embed,或在最后一层是词表大小)。
举个具体例子:(2, 16, 128) 表示”2 个序列,每个序列 16 个 token,每个 token 用一个 128 维向量表示”。现在记住这个记法,等到第 05、06 章讲 Transformer 和注意力时,你会发现所有操作都在跟这三个维度打交道。
2. 矩阵乘法:不只是”乘一乘”
神经网络里最频繁的操作,就是矩阵乘法(matrix multiplication,常记作 @ 或 matmul)。它看起来抽象,直觉其实很简单。
先看规则。两个矩阵 (形状 )和 (形状 )相乘,结果 的形状是 。关键约束: 的列数必须等于 的行数(都是 ),否则乘不了。结果里第 行第 列的元素是:
把它读成大白话: 里位置 的数,等于” 的第 行”和” 的第 列”对应位置相乘再求和。 就是”把 从 1 到 的每一项加起来”。
维度对齐的口诀:把形状写在一起, 乘 ,中间的 必须相同、会”消掉”,剩下外侧的 和 就是结果形状:
这个”中间对齐、两头留下”的口诀,以后看任何网络层的形状变化都用得上。
为什么神经网络爱用它?因为矩阵乘法正好表达了”一组输入特征,经过一层权重,变成一组新特征”。比如一个把 128 维向量变成 512 维向量的”线性层”,本质就是拿输入去乘一个 的权重矩阵。第 03、05 章里的 nn.Linear 干的就是这件事;第 06 章注意力机制里的 、、 计算也全是矩阵乘法。
3. 函数与导数:斜率说明了”往哪调”
函数
函数就是”输入进去,输出出来”的规则。写成 :给一个 ,按规则 算出一个 。比如 ,输入 3 就输出 9。
在机器学习里,我们最关心一类特殊的函数:损失函数。它的输入是”模型的参数”,输出是”模型现在有多差”。我们的全部目标,就是调整参数,让这个输出(损失)尽量小。
导数 = 斜率 = 变化的快慢
导数(derivative) 衡量”当我把输入挪动一点点,输出会变化多少”。它就是函数曲线在某一点的斜率。记作 或 。
直觉:站在一座山的某个点上,导数告诉你”朝某个方向迈一小步,海拔会升还是降、升降多快”。
- 导数为正:输入增大,输出也增大(上坡)。
- 导数为负:输入增大,输出反而减小(下坡)。
- 导数为零:此处是”平地”,可能是山顶或谷底。
举个能手算的例子, 的导数是 。在 处斜率是 6(陡峭地上坡);在 处斜率是 0(谷底)。
为什么这对训练至关重要? 因为如果损失函数对某个参数的导数是正的,就说明”把这个参数调大,损失会变大”——那我们就该反着来,把它调小;反之亦然。导数,就是模型告诉我们”该往哪个方向调参数”的指南针。这个思想下一节、以及第 4 节的线性回归里就会用到。
偏导:多个变量时,“只动一个”
真实模型有成千上万、甚至上亿个参数,不止一个 。当函数有多个输入,比如 ,我们就用偏导(partial derivative):只动其中一个变量、把其它都当常数不动,看输出怎么变。记作 (读作”L 对 w 的偏导”)。
这个符号(读”偏”)就是在提醒你:这是”只看 这一个方向”的斜率,别的变量先按住不动。
梯度:所有偏导打包,指向”上升最快”的方向
把一个函数对它所有参数的偏导,排成一个向量,就叫梯度(gradient),记作 (那个倒三角读作”nabla”):
大白话:梯度是一个”方向箭头”,它指向让损失上升最快的方向。
这有个绝妙的推论:既然梯度指向”上升最快”,那么它的反方向 就是”下降最快”的方向。我们想让损失变小,所以就沿着梯度的反方向走一小步。这就是大名鼎鼎的梯度下降(gradient descent),是几乎所有深度学习训练的核心。第 4 节我们就亲手走一遍。
链式法则:反向传播的引擎
最后一块拼图。神经网络是”一层套一层”的——输出是 这样复合起来的。要算最终损失对最里层某个参数的导数,得用链式法则(chain rule):
大白话:一连串变化的总斜率,等于每一段斜率相乘。好比齿轮组,大齿轮带小齿轮——要算最末端转多快,就把每一级的传动比乘起来。
为什么重要?因为神经网络有很多层,损失要”沿着层一路传回去”才能算出每层参数的梯度。这个”从输出端把梯度一层层乘回输入端”的过程,就叫反向传播(backpropagation),而它的数学本质就是链式法则。好消息是:你几乎永远不用亲手做这件事——第 03 章你会看到,PyTorch 的 autograd 会自动、精确地替你完成所有链式求导。你只需理解”它在做什么”,并相信它。
4. 概率、期望、对数:语言模型的语言
大模型本质上是个”猜下一个词”的概率机器,所以我们得熟悉几个概率概念。
概率分布
概率(probability) 是 0 到 1 之间的数,表示某件事发生的可能性,0 是不可能、1 是必然。概率分布(probability distribution) 则是”把所有可能结果各自的概率列出来”,并且它们加起来等于 1。
比如掷一个公平骰子,分布是”1 点到 6 点各 1/6”;加起来 。
在语言模型里,模型对”下一个 token 是什么”给出一个分布:词表里 50304 个 token 各有一个概率,全部加起来是 1。第 01 章那个 (2, 16, 50304) 的 logits,经过一个叫 softmax 的操作(第 05、07 章细讲)就变成这样的概率分布。
期望:概率加权的平均
期望(expectation) 是”考虑了概率之后的平均值”,记作 。对一个能取值 、对应概率 的随机量:
大白话:把每个可能取值,按它出现的概率加权,再求和。掷公平骰子点数的期望是 。强化学习章节(第 15、16 章)里反复出现的”期望奖励”,就是这个意思:把每种可能结果的奖励按其概率加权平均。
为什么处处用对数?
接下来你会在损失函数里频繁见到对数(logarithm,记作 )。对数有两个我们极其看重的好处。
好处一:把乘法变成加法。 对数有个性质:
为什么需要?因为一句话的概率,是它每个 token 概率的连乘。比如一句 100 个 token 的话,概率是 100 个小数相乘——每个都小于 1,乘到后面会变成一个小得可怕的数(比如 ),计算机根本存不下(这叫”数值下溢”)。取对数后,连乘变成连加,小数变成”一串负数相加”,计算机算起来又稳又准。
好处二:数值稳定 + 单调。 对数是单调递增的: 越大, 也越大。所以”让概率最大”和”让对数概率最大”是等价的目标,但后者算起来稳定得多。
负对数:损失登场
还有个细节:概率在 0 到 1 之间,它的对数是负数或 0(比如 ,)。而我们习惯让”损失”是个越小越好的正数。于是只要在前面加个负号,得到负对数(negative log):
大白话:模型对正确答案给的概率 越高(越接近 1), 就越接近 0(损失越小); 越低(模型越离谱), 就越大(惩罚越重)。 这正是我们想要的”打分尺”。第 07 章你会看到,语言模型的核心损失——交叉熵(cross-entropy)——本质就是”对正确 token 的负对数概率取平均”。现在埋下这个伏笔即可。
5. 机器学习的核心循环:用一个一维线性回归全程走一遍
概念铺垫够了,现在把它们串起来,看看”训练”到底是怎么一回事。我们用最简单的模型:一维线性回归。
模型、参数、损失:三个核心名词
- 模型(model):一个带”可调旋钮”的函数。这里就是一条直线 。给一个输入 ,它预测一个输出 (读作”y hat”,表示”预测值”,区别于真实值 )。
- 参数 / 权重(parameter / weight):模型里那些可以调整的数,这里是斜率 和截距 。训练,就是不断调整参数的过程。
- 损失函数(loss function):衡量”预测有多差”的数值,越小越好。
任务设定
假设我们有一堆数据点 ,想找一条直线尽量穿过它们。我们用均方误差(Mean Squared Error, MSE) 当损失:把每个点的”预测值减真实值”平方,再求平均。设共有 个数据点:
大白话:对每个点,算”我猜的 “和”真值 “差多少,平方一下(让正负差都变成正、且差得越多惩罚越狠),所有点求平均。 平方还有个好处:让这个损失对 而言是个平滑的”碗形”,有唯一的谷底,正好用梯度下降去找。
手推梯度
要”下山”,得先知道坡度——也就是损失对 和对 的偏导。我们一步步推,用到的就是第 3 节的求导和链式法则。
为了少写求和号,先看单个点的损失 。令中间量 (这就是这个点的”误差”),于是 。
对 求偏导,用链式法则(,而 ):
对 求偏导():
把所有点平均起来,就得到整体损失的梯度:
大白话:每个点”误差 输入”的平均,告诉我们 该怎么调;每个点”误差”本身的平均,告诉我们 该怎么调。误差越大、方向越一致,梯度就越大,该调的幅度也越大。
用学习率更新参数
有了梯度,就能沿”下降最快”的方向(梯度反方向)迈一步。每一步这样更新:
这里 (希腊字母,读 “eta”)是学习率(learning rate),一个我们自己设的小正数(比如 0.01),控制每步迈多大。
- 太大:步子迈太猛,可能”一步跨过谷底”甚至越走越高,训练不稳定;
- 太小:走得太慢,要很多步才到谷底。
箭头 表示”用右边算出的新值,覆盖左边的旧值”。注意那个减号:它正是”沿梯度反方向走”的体现——梯度指向上坡,我们减去它,就往下坡走。
走一个具体的数字例子
来感受一下”训练真的在学习”。假设真实规律是 (我们假装不知道,要让模型自己学出来)。只用一个数据点 ,初始参数 ,学习率 。
第 1 步:当前预测 。误差 。
梯度:
更新:
第 2 步:新预测 。比起第一步的 0,离目标 2 更近了! 误差从 缩小到 。
继续算下去:误差 ,梯度 ,更新 ,,预测变成 ……
你看到了吗?每一步预测都在向 2 靠近,损失在减小。这就是”训练”——没有魔法,就是”算损失 → 算梯度 → 沿反方向挪一小步”,重复很多很多次。一个有上亿参数的大模型,训练的内核和这个例子一模一样,只是参数多得多、损失函数复杂得多、梯度由 PyTorch 自动算而已。
埋个伏笔:你刚才”手算梯度”很辛苦吧?在真实模型里,谁来算这成千上万个偏导?答案是 PyTorch 的 autograd——下一章(第 03 章)你会亲眼看到,它自动算出的梯度,和你这里手推的完全一致。而”算损失→反向求梯度→更新参数”这套循环,正是第 03 章要你亲手写出来的”训练循环五件套”,也是后面预训练、SFT、PPO 等所有阶段共用的骨架。
小结
- 数据都是张量,核心属性是形状;文本处理里最常见的是 :批大小、序列长度、特征维度。
- 矩阵乘法是网络的基本动作,口诀”中间维度对齐、两头维度留下”;它表达”一组特征经过一层权重变成新特征”。
- 导数 = 斜率,告诉我们”该往哪调”;偏导是”只动一个变量”的斜率;梯度把所有偏导打包,指向上升最快方向,所以我们沿反方向走;链式法则是反向传播的数学引擎。
- 概率分布各项加起来为 1;期望是概率加权平均;用对数是为了把连乘变连加、保证数值稳定;负对数 天然适合当损失(预测越准、损失越小)。
- 训练的核心循环:定义模型(带参数)→ 用损失函数打分 → 求梯度 → 用学习率沿梯度反方向更新参数 → 重复。我们用一维线性回归亲手走通了全程。
自测题
-
一个张量形状是
(8, 64, 256),放在 NLP 语境里,这三个数最可能各代表什么?提示 / 答案
`8` = batch 大小 `B`(一批 8 个序列);`64` = 序列长度 `T`(每序列 64 个 token);`256` = 特征维度 `C`(每个 token 用 256 维向量表示)。即 `(B, T, C)`。 -
两个矩阵形状分别是
(4, 32)和(32, 10),能相乘吗?结果形状是多少?如果第二个是(10, 32)呢?提示 / 答案
`(4, 32) @ (32, 10)` 可以乘(中间的 32 对齐),结果 `(4, 10)`。换成 `(10, 32)` 就不能乘了,因为第一个的列数 32 ≠ 第二个的行数 10。 -
梯度指向”上升最快”的方向,那我们想让损失变小,该往哪个方向更新参数?为什么更新公式里有个减号?
提示 / 答案
往**梯度的反方向**走(下降最快)。更新公式 $w \leftarrow w - \eta \nabla L$ 里的减号,正是"减去梯度=朝反方向走"的体现。 -
语言模型的损失里为什么常用”负对数概率”而不直接用概率?说出两个理由。
提示 / 答案
(a) 对数把"许多概率连乘"变成"连加",避免极小数下溢、数值更稳定;(b) 加负号后,模型给正确答案的概率越高,损失 $-\log p$ 越小(趋近 0),概率越低损失越大——正好是个"越小越好"的打分尺。 -
沿用正文例子:真实规律 ,单点 ,当前 ,学习率 。手算这一步之后的 和 。
提示 / 答案
预测 $\hat y = 0.4\cdot1+0.4 = 0.8$,误差 $e = 0.8-2 = -1.2$。$\frac{\partial L}{\partial w} = 2ex = -2.4$,$\frac{\partial L}{\partial b} = 2e = -2.4$。更新:$w \leftarrow 0.4 - 0.1\cdot(-2.4) = 0.64$,$b \leftarrow 0.64$。预测变为 $1.28$,更接近 2。
深入参考
- 训练目标(最大似然 → 负对数似然 → 交叉熵 → 困惑度)的完整推导,见本教程 第 07 章。
- 优化方法(梯度下降 → Adam → AdamW、学习率调度)的展开,见 第 08 章。
- 工程速查参考:
../foundations/下的基础文档与../07_objectives_zh.md、../08_optimization_zh.md(随课程推进逐步对照)。
地基打好了。下一章我们把这些数学直觉落到真实代码上——用 PyTorch 创建张量、让 autograd 自动算出你刚才手推的那些梯度,并亲手写一个能跑的最小训练循环。
下一章 👉 第 03 章:PyTorch 极简入门