机器学习分三路:监督有标准答案、非监督只有数据本身、强化只有事后的奖励。 再加上更早的规则库一路,四条路各有各的适用场合。 不管走哪条路,评估的规矩是一样的:数据切成训练/验证/测试三份,在验证集上选模型, 在测试集上报成绩,一次都不许回头改。 这一节用三个小实验把三件事量出来:过适曲线(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 秒实验
- 把验证集也加上噪声(rg.normal(0, 0.15)),过适的拐点会往哪边移?
- 把 ε 从 0.1 改成 0.01,1000 次里最优臂会被拉多少次?改成 0.5 呢?
- 把在线学习的学习率从 0.01 提到 0.1,它会震荡还是收敛得更快?
常见误区
- 以为非监督学习「不用标签所以简单」。 没有标答就没有对错, 评估反而更难——聚类出来的两簇到底有没有意义,得靠人看。
- 以为训练误差低就是好模型。 15 阶那个模型训练误差 0.0060,比 3 阶还好, 但它在验证集上烂了 27 倍。训练集上的成绩只是「背得熟不熟」。
- 用测试集反复调参。 调一次,测试集就被污染一分; 调到满意为止,报出来的数已经不是泛化能力,是「你调了多少次」的记录。
自测三问(点开对答案)
1. 监督、非监督、强化,最根本的区别是什么? —— 看「反馈」长什么样:监督每个样本都带正确答案;非监督什么反馈都没有; 强化只有事后的、延迟的奖励,而且不告诉你这个动作是不是最好的。 2. 为什么必须有验证集,不能只用训练集和测试集? —— 因为选模型、调超参数要反复试。 试的过程本身就在拟合数据,如果在测试集上试,测试集就失去了「没见过」这个性质,成绩不再可信。 3. 过适的典型症状是什么? —— 训练误差继续下降,验证误差开始上升,两者差距越拉越大。 本质是模型把训练集里的噪声也当成了规律。这一节反复出现「梯度」「范数」「平方误差」,都默认你熟悉。 下一节把这些数学从零过一遍,每个都配一个当场能跑的数值校验。
- ☐ (本节完,下一节 1.4 机器学习所需的数学)