📕 第1章 深度学习与机器学习
📄 一句话概括

机器学习分三路:监督有标准答案、非监督只有数据本身、强化只有事后的奖励。 再加上更早的规则库一路,四条路各有各的适用场合。 不管走哪条路,评估的规矩是一样的:数据切成训练/验证/测试三份,在验证集上选模型, 在测试集上报成绩,一次都不许回头改。 这一节用三个小实验把三件事量出来:过适曲线(15 阶验证误差 0.0060 涨回 0.1935)、 ε-greedy 试错(1000 次里 918 次压在最优臂)、批量与在线的更新次数(54 对 266)。

📝 本节和前面几节的关系

上一节讲了深度学习是什么,这一节先退一步,把它放进整个机器学习的版图里。 这一节的概念后面处处要用:过适在 5.11 节再讲一次(那时有卷积网络), 批量与在线在 4.6 节的梯度下降里会具体成 batch size。 读这一节不需要任何神经网络知识,只需要会算平均值。

一、四条路

书里把「机器学习的基础知识」摊成四块:规则库与知识库、统计机器学习、 以及按「有没有标答」分出来的监督、非监督、强化。前两块是方法,后三块是范式。

范式 你给它什么 它要产出什么 本书例子
监督学习 输入+正确答案 从输入到答案的映射 手写数字辨识
非监督学习 只有输入 数据内部的结构(簇、降维) 聚类、主成分
强化学习 状态+动作+奖励 让长期回报最大的策略 多臂老虎机

规则库与知识库是深度学习之前的主流:把专家的经验写成 IF-THEN,机器照着推。 它的优点是每条结论都能追溯,缺点是规则写不完——「什么是一只手写数字 3」这种事,没人写得完。 统计机器学习换了个思路:不写规则,写一个带参数的函数,让数据把参数定下来。 深度学习是这条路走到「函数有很多层」的那个分支。

二、「学习」到底在做什么

一句话:先假设一个带参数的函数,再找一组让误差最小的参数。 线性回归是 y = wx + b,参数是 w、b;类神经网络是 y = f₃(f₂(f₁(x))),参数是那一堆权重。 找参数的办法是梯度下降——沿着误差变小的方向挪。 所以「训练」不是让机器「理解」,是在一个高维空间里找谷底。 谷底找得对不对,取决于这个函数族能不能表达你要的规律,以及数据够不够把谷底定住。

三、预处理与特征提取

喂进去之前有两件事必做。一是清洗:缺失值、重复、错标。 二是缩放:把各列归一到同一量级(常见是减均值除标准差)。 为什么非要缩放? 因为梯度下降的步子对所有参数是一个学习率,某一列数值大十倍,它的梯度也大十倍,那一维就会来回过冲, 别的维度还在慢慢爬。 特征提取是第三件事,也是深度学习改写的那一件:以前靠人(边缘、直方图、MFCC), 现在靠前面的层自己学。第 5 章的卷积核就是自动学出来的特征提取器。

四、批量学习与线上学习

批量学习要整份数据在手,一次算完全部样本再更新一次参数。稳,但每步贵,而且数据更新了要重训。 线上学习来一个样本更新一次,跟得上变化,但抖动大。 实测这两个词的差别:同一个线性回归目标,批量更新 54 次就到损失 0.30 以下, 在线要 266 次——次数多五倍,但每次只算 1 个点而不是 100 个点。该比的是总计算量,不是次数。

五、效能评估与泛化能力

数据必须切成三份:训练集用来定参数,验证集用来选模型和调超参数,测试集只在最后用一次。 为什么验证集和测试集要分开? 因为你在验证集上反复试,等于把验证集也「学」进去了,它报出来的成绩会偏乐观。 测试集只用一次,那个数才是真话。 泛化能力就是在没见过的数据上还对的能力。 训练误差低而验证误差高,说明模型把训练集背下来了——这叫过适,下面 Demo 里能直接看到它长什么样。

六、动手 Demo:过适、试错、与「什么时候算学完」

三个小实验:① 用 1/3/9/15 阶多项式去拟合 20 个带噪声的 sin 采样点, 看训练误差与验证误差怎么分道扬镳;② 三臂老虎机,ε=0.1,拉 1000 次; ③ 同一个线性回归,批量与在线各要更新多少次才到同一损失。

import numpy as np
rg = np.random.default_rng(20261026)

# 过适:20 个训练点,从 sin 曲线上采,再叠噪声
xt = np.linspace(-3, 3, 20)
yt = np.sin(xt) + rg.normal(0, 0.15, 20)
xv = np.linspace(-3, 3, 40)      # 验证集用干净的 sin,没有噪声
yv = np.sin(xv)
for d in (1, 3, 9, 15):
    c = np.polyfit(xt, yt, d)
    e_tr = np.mean(np.square(np.polyval(c, xt) - yt))
    e_va = np.mean(np.square(np.polyval(c, xv) - yv))

# 强化:三臂老虎机,ε-greedy,ε = 0.1
arms = [0.3, 0.5, 0.7]         # 真实成功率,agent 不知道
q = np.zeros(3)                # 每个臂当前的估值
cnt = np.zeros(3)
for _ in range(1000):
    if rg.random() < 0.1:
        a = int(rg.integers(0, 3))     # 探索
    else:
        a = int(np.argmax(q))          # 利用
    r = 1.0 if rg.random() < arms[a] else 0.0
    cnt[a] += 1
    q[a] += (r - q[a]) / cnt[a]        # 增量平均

实跑输出:

--------------------------------------------------------------------
机器学习的基础知识 —— 过适、试错、与「什么时候算学完」
--------------------------------------------------------------------

  阶数    参数个数  训练误差    验证误差
  ----------------------------------------
  1       2         0.2095      0.1818
  3       4         0.0222      0.0070
  9       10        0.0143      0.0061
  15      16        0.0060      0.1935

  **训练误差一路掉,验证误差在第 9 阶之后反而涨回来,这叫过适。**
  15 阶的曲线会从每个训练点身上穿过去,点与点之间开始乱抖。

  拉杆          真实成功率    被拉动次数
  ----------------------------------------
  第 1 臂       0.3           55
  第 2 臂       0.5           27
  第 3 臂       0.7           918

  **没有标签,只有「拉了之后给不给糖」,试错一千次就能把大多数次数压到最优臂上。**
  非监督连糖都没有;强化有糖,但没人告诉你哪根杆最好。

  方式              更新次数    w         b
  ------------------------------------------------
  批量(一次全看)  54          2.890     1.911
  在线(一次一个)  266         2.892     1.909

  **批量的「一次」算完全部 100 个点,在线的「一次」只算 1 个点,**
  **所以后者次数多得多,但每次便宜——该比的是总计算量,不是次数。**
  这就是批量学习与线上学习:一个要整份数据在手,一个来一个学一个。

训练误差一路掉:0.2095 → 0.0222 → 0.0143 → 0.0060。 验证误差先降后升:0.1818 → 0.0070 → 0.0061 → 0.1935。15 阶那一下涨了 31 倍, 而训练误差还在降——这就是过适的标准形状。 为什么 15 阶会崩? 20 个点配 16 个参数,模型有足够自由度从每个点身上穿过去,点与点之间它没有任何信息,只能乱抖。 参数越多,越容易把噪声当规律。 老虎机那边:第 3 臂真实成功率 0.7,1000 次里被拉了 918 次, 另外两臂合计 82 次——这 82 次就是「探索」的成本。 ε=0.1 意味着约 100 次是随机拉的,剩下 900 次基本都在压注。 批量 54 次、在线 266 次。 注意这两列不能直接比大小:批量的「一次」算 100 个样本,在线的「一次」算 1 个, 换成总样本处理量是 5400 对 266——批量反而贵二十倍。

30 秒实验

  1. 把验证集也加上噪声(rg.normal(0, 0.15)),过适的拐点会往哪边移?
  2. 把 ε 从 0.1 改成 0.01,1000 次里最优臂会被拉多少次?改成 0.5 呢?
  3. 把在线学习的学习率从 0.01 提到 0.1,它会震荡还是收敛得更快?

常见误区

  1. 以为非监督学习「不用标签所以简单」。 没有标答就没有对错, 评估反而更难——聚类出来的两簇到底有没有意义,得靠人看。
  2. 以为训练误差低就是好模型。 15 阶那个模型训练误差 0.0060,比 3 阶还好, 但它在验证集上烂了 27 倍。训练集上的成绩只是「背得熟不熟」。
  3. 用测试集反复调参。 调一次,测试集就被污染一分; 调到满意为止,报出来的数已经不是泛化能力,是「你调了多少次」的记录。
自测三问(点开对答案) 1. 监督、非监督、强化,最根本的区别是什么? —— 看「反馈」长什么样:监督每个样本都带正确答案;非监督什么反馈都没有; 强化只有事后的、延迟的奖励,而且不告诉你这个动作是不是最好的。 2. 为什么必须有验证集,不能只用训练集和测试集? —— 因为选模型、调超参数要反复试。 试的过程本身就在拟合数据,如果在测试集上试,测试集就失去了「没见过」这个性质,成绩不再可信。 3. 过适的典型症状是什么? —— 训练误差继续下降,验证误差开始上升,两者差距越拉越大。 本质是模型把训练集里的噪声也当成了规律。

这一节反复出现「梯度」「范数」「平方误差」,都默认你熟悉。 下一节把这些数学从零过一遍,每个都配一个当场能跑的数值校验。

相关笔记