🧠 第一章 AI入门:认识人工智能模型训练
📄 一句话概括

20 个训练点、12 个参数:训练误差一路降到 0.2597, 测试误差却在 3 次多项式时就到底(0.3571),之后掉头往上, 到 11 次变成 2.4273——是 3 次时的 6.8 倍。训练集误差最低的那个模型,恰恰是最差的。

📝 本节和前面几节的关系

上一节讲清了「训练就是调参数三步循环」,这一节追问:调完了怎么知道自己调对了? 答案是三份数据、三个用途,不能混。

一、模型 = 形状 + 参数

上一节说了参数是什么,还得补上另一半:形状。 用一次多项式还是一次、九次,这个「用什么形状去拟合」是人在训练之前就定下来的。 形状在术语里叫「模型结构」或「假设空间」。 定了形状,参数才有地方放:一次多项式有 2 个参数,九次有 10 个, 一个 784-128-10 的三层网络有十万多个。 所以「训练」严格说只做一件事:在定好的形状里,找一组参数让误差最小。 换形状是人的事,找参数是机器的事。 这两件事经常被混为一谈。 选形状这件事在工程上非常具体:层数、每层宽度、用什么激活函数、要不要加卷积。 第八章会展开讲六种网络各自适合什么形状的数据。

二、三份数据,三个用途

训练集用来调参数——梯度下降看的每一眼都是它。 验证集用来挑形状和超参数——「到底用几次多项式」「学习率多大」这类问题,在验证集上看效果决定。 它不参与调参数。 测试集用来报最终成绩——只在最后用一次。 它存在的意义是给你一个「没见过的新数据上能有多好」的无偏估计。 这三份混用是新手最常犯的错。 比如拿测试集反复试、试到指标好看为止,那一刻测试集就已经变成验证集了,你报的数不再可信。 比例上,数据少的时候常见 6:2:2 或 8:1:1;数据多的时候验证和测试各留几千条就够。 关键不是比例,是三份之间严格不重叠。

三、过拟合:训练误差低从来不等于学对了

Demo 里 20 个训练点,噪声标准差 0.35。多项式从 1 次做到 11 次,训练误差从 0.6389 单调降到 0.2597。 只看这一列,你会觉得 11 次最好。 但测试误差是另一条曲线:1 次 0.4884(欠拟合)、3 次 0.3571(最低)、7 次 0.5594、11 次 2.4273。 最低点和最高点差了 6.8 倍。 为什么会这样? 因为 11 次多项式有 12 个参数、只有 20 个点,它可以把每个点的噪声都当成规律「穿」过去。 穿过去之后,它对这 20 个点的描述是完美的,对第 21 个点就完全是瞎猜。 极端一点看外推:3 次模型在 x = -1.05 处给 +1.03,11 次给 +89.54。 训练区间是 -1 到 1,出了这个区间,高次项会爆炸。它没学过「外面」,只能拿高次项硬撑。 对应的两种毛病,修法相反:欠拟合(1 次那种)要加参数、加特征; 过拟合(11 次那种)要加数据、减参数、加正则。方向搞反了,越调越差。

四、一次完整的训练长什么样

把上面的东西串起来,实际流程是九步:定任务和指标、收数据、划分三份、定模型形状、训练、 在验证集上调超参、回到训练、在测试集上报成绩、最后上线监控。 注意第 5 步和第 7 步之间会来回好几轮。 「训练一次就成功」是不存在的,真实项目里形状和超参数要试几十次。 还有一步容易被跳过:上线监控。 模型上线之后数据分布会变,今天测试集 0.92 的成绩,三个月后可能只剩 0.80。 这不是模型退化,是世界变了。第九章和第十章会专门讲怎么发现这件事。

五、动手 Demo:20 个点配 12 个参数,训练误差还在降,测试误差已经飞了

造 20 个训练点和 80 个测试点,目标函数是 sin(3x),各加 0.35 的噪声。 多项式从 1 次扫到 11 次,每一档都算训练误差和测试误差,看两条曲线在哪里分家。 最后把 3 次和 11 次模型拿到训练区间外去外推,看会发生什么。

def gen(n, seed, nz):
    r = np.random.default_rng(seed)
    x = r.uniform(-1, 1, n)
    return x, np.sin(3.0 * x) + r.normal(0, nz, n)

xtr, ytr = gen(20, 1, 0.35)
xte, yte = gen(80, 2, 0.35)
for deg in range(1, 12):
    c = np.polyfit(xtr, ytr, deg)
    tr = np.sqrt(((np.polyval(c, xtr) - ytr) ** 2).mean())
    te = np.sqrt(((np.polyval(c, xte) - yte) ** 2).mean())
    print(deg, deg + 1, round(tr, 4), round(te, 4))

实跑输出:

--------------------------------------------------------------------
什么叫训练:20 个点配 12 个参数,训练误差还在降,测试误差已经飞了
--------------------------------------------------------------------
  次数   参数个数   训练集误差   测试集误差   判断
  -------------------------------------------------
     1          2       0.6389       0.4884   欠拟合
     2          3       0.6164       0.5217   欠拟合
     3          4       0.3717       0.3571   合适
     4          5       0.3414       0.3835   合适
     5          6       0.3205       0.4076   合适
     6          7       0.3040       0.5177   合适
     7          8       0.3013       0.5594   过拟合
     8          9       0.2902       0.7773   过拟合
     9         10       0.2890       0.5769   过拟合
    10         11       0.2770       1.0655   过拟合
    11         12       0.2597       2.4273   过拟合

  训练集误差最小           11 次(0.2597)
  测试集误差最小           3 次(0.3571)

  **这两个数不是同一个。** 参数从 2 个加到 12 个,训练误差一路降到 0.2597,但测试误差在 3 次时就到底了,之后掉头往上,到 11 次变成 2.4273——是 3 次时的 6.8 倍。
  参数最多的那个模型,把 20 个点的噪声也当成规律背下来了。这就是过拟合。

  12 个参数拟合 20 个点,训练集上几乎贴住,但出了训练区间立刻现原形:
  模型    x=-0.95(内)   x=-1.05(外)   x=1.05(外)
  ---------------------------------------------------
  3 次            +0.19           +1.03          -0.34
  11 次           +0.90          +89.54        -212.42
  11 次模型在区间外给出的数明显偏大——它没学过「外面」,只能拿高次项硬外推。**训练集误差低,从来不等于模型学对了。**

  所以训练一个模型是三件事,缺一件就不算数:
  ① 训练                   用训练集调参数
  ② 验证                   用验证集挑超参数(上面那个「次数」)
  ③ 测试                   用从没碰过的测试集报最终成绩

表里「判断」那一列是我按两条规则打的:训练误差超过最低值的 1.5 倍算欠拟合, 测试误差超过最低值的 1.5 倍算过拟合,其余算合适。这两条线是经验值,不是定理。 注意第 6 次那行判的是「合适」,第 7 次就跳到「过拟合」——中间并没有一道干净的墙。 真实调参也是这样,边界是模糊的,得靠多看几个点判断趋势,不能盯单个数。 外推那张表更狠:3 次模型在 x = -1.05 给 +1.03,11 次给 +89.54;x = 1.05 处 11 次给 -212.42。 出了训练区间,高次项是在放大噪声,不是在预测。 要诚实说一句:这组实验里测试误差在第 8、9 次有一点回落(0.7773 → 0.5769),不是严格单调。 原因是只有 80 个测试点,本身就有波动。看趋势,别追单点。

30 秒实验

  1. 把训练点从 20 改成 60,看「过拟合」还会不会出现——大概率会推迟到更高的次数,甚至消失。 数据量是治过拟合最直接的一味药。
  2. 把噪声从 0.35 改成 0.05,看测试误差曲线的最低点往哪边移。 噪声小的时候,高次模型不容易把噪声当规律,过拟合就轻。
  3. 把测试集换成训练区间的外推点(x 取 1.1 到 1.5),看 3 次和 11 次的差距变成多少倍。 这个实验会让你对「外推」两个字的危险有生理反应。

常见误区

  1. 「训练集准确率 99% 说明模型很好」。恰恰相反,在数据少的时候,训练集 99% 往往是过拟合的信号。 要看的是验证集和测试集。
  2. 「验证集和测试集是一回事」。不是。验证集参与决策(挑超参数),所以它会「被污染」; 测试集只在最后用一次,才能给无偏估计。
  3. 「参数越多模型越强」。参数多只是「容量大」,容量大容易装下噪声。 能不能用好这个容量,取决于数据量和正则化。
自测三问(点开对答案) 1. 为什么训练误差会单调下降,测试误差却呈 U 形? —— 训练误差是「在见过的点上拟合得多好」,参数越多越能贴; 测试误差是「在没见过的点上有多准」,参数多到开始记噪声时反而变差。 两条曲线方向不同,正因为它们量的不是同一件事。 2. 如果只有一份数据,没法划出验证集,怎么办? —— 用交叉验证:把数据切成 K 份,轮流留一份当验证,其余训练,最后取平均。 第九章的 9.2.2 会算这个过程。代价是要训练 K 次。 3. 模型上线三个月后效果掉了,是过拟合吗? —— 不一定。过拟合是训练时的问题; 上线后掉效果多半是**数据漂移**——输入分布变了,而模型还是按老分布学的。 要先查数据,不是先怀疑模型。

训练和评估的框架讲完了。 下一节讲两个「省」的技术:一个省体积(量化),一个省结构(蒸馏)——顺便说清它们各自省不掉什么。

相关笔记