先假定一个函数形状,再用数据把里面的参数调出来——这就是全部。 演示里机器从 w=0、b=0 出发,500 轮挪到 w=3.0153、b=1.8907,真实值是 3 和 2。 同一个函数形状,w 从 3 改到 6,误差从 0.08 涨到 296。参数决定一切。
第 3 章讲系统撑不住怎么办。这一章讲怎么从数据里找规律。 教材 4.1 节:机器学习——对转换成量的数据进行处理的函数。 这个定义有点绕。它说的其实是:机器学习就是一个函数,喂给它数据,它吐出一个数。 「学习」这个词可以暂时忘掉,把它当成「调参数」就好理解了。
一、先看一百个点
演示造了一百个点:x 从 0 到 9.9,y 差不多是 3 倍的 x 再加 2。 我故意在 y 上叠了 ±0.5 的随机噪声,模拟真实测量的误差。 机器拿到的只有这一百个数对。它不知道「3」和「2」这两个数,也不知道这里应该是一条直线。
所以「学习」要解决两个问题:这条线该长什么样(叫模型),以及它该摆在哪个位置(叫参数)。 前者是人定的,后者是机器算的。这一步分工要分清楚,不然会以为机器学习能「自己发现一切」。
二、从零开始,一点点挪
假设我们先猜 y = w * x + b,w 和 b 都从 0 开始。 这时的预测就是一条躺在 x 轴上的水平线,误差很大——均方误差 39.25。 然后算一件事:w 增大一点,误差会变大还是变小?b 增大一点呢?
这个「往哪个方向改能变小」的信息就是梯度。沿着梯度的反方向挪一小步,误差就会降一点。这叫梯度下降。 演示里每轮挪 0.01 倍,500 轮之后:第 1 轮 w 就到 2.17,第 10 轮 3.22,第 500 轮稳定在 3.0153; b 从 0 挪到 1.8907。 真实值是 3 和 2。误差从 39.25 降到 0.0855。
机器从来没看见过「3」和「2」,它是从一百个点里一点点试出来的。
三、模型就是几个参数
整个模型可以用一句话写完:y = 3.0153 * x + 1.8907。 一共两个参数。存下来只有 16 字节,传给别人也只要一句话。 这就是为什么模型能塞进手机、塞进摄像头——它不是一个程序,它是一组数。
推理的时候也不需要「跑算法」,只要做一次乘法和一次加法。所以模型上线后特别快,慢的是训练。 这一点常被误解:机器学习「算力要求高」说的是训练阶段。 训练好的模型做预测,代价和一行四则运算差不多。
四、参数不对就全错
拿训练好的模型,把 w 改一改,看误差怎么变。 w=1、b=2:误差 131.25。w=3、b=2:误差 0.0815。w=6、b=2:误差 295.85。 同一个函数形状,只改一个参数,误差差三千多倍。
所以训练的全部工作,就是在参数空间里找误差最小的那个点。 但要注意:w=3、b=2 的误差 0.0815 比训练出来的 0.0855 还小一点点。 这说明梯度下降找到的不一定是最优解,只是一个足够好的解。 真实问题里参数成千上万,不可能找到全局最优。够用就行,这是工程态度。
五、跟笨办法比一比
模型误差 0.0855,听起来很小。但它到底有多好? 拿一个最笨的办法对比:不管 x 是多少,一律预测 y 的平均值 16.848。误差 74.88。 训练出来的直线比它好 876 倍。这才说明模型真学到了东西。
如果基线只要 0.09、你的模型 0.08,那就是白干——多花的力气没换来什么。 所以任何模型报效果,都必须带一个基线。没有基线的「准确率 95%」什么也不能说明。 这也是下一篇要讲的:光看训练误差不行,还得看它在没见过的数据上怎么样。
六、动手 Demo:从 w=0、b=0 出发,500 轮以后是多少
造一百个点,规律是 y = 3x + 2 加噪声。 用梯度下降从零开始调参数,每轮打印 w、b 和误差。 最后把参数改错几个值,看误差怎么炸。
w, b, lr = 0.0, 0.0, 0.01
n = len(xs)
for epoch in range(500):
gw = sum(-2 * (y - (w*x + b)) * x for x, y in zip(xs, ys)) / n
gb = sum(-2 * (y - (w*x + b)) for x, y in zip(xs, ys)) / n
w -= lr * gw
b -= lr * gb
print('学到:y = %.4f * x + %.4f' % (w, b))
实跑输出:
--------------------------------------------------------------------
机器学习就是找一个函数:三个数就能学会
--------------------------------------------------------------------
① 先看数据长什么样
--------------------------------------------------------------------
100 个点,x 从 0 到 9.9
前五个:(0.0, 1.54) (0.1, 2.39) (0.2, 2.12) (0.3, 2.91) (0.4, 3.68)
后五个:(9.5, 30.12) (9.6, 30.87) (9.7, 31.24) (9.8, 31.16) (9.9, 31.80)
这组数据是我按 y = 3x + 2 造出来的,再叠了一点噪声。机器不知道这个式子,它只看到这一百个点。
② 从 w=0、b=0 开始,一点点挪
--------------------------------------------------------------------
| 第几轮 | w | b | 误差(均方) |
|---:|---:|---:|---:|
| 1 | 2.1673 | 0.3370 | 39.2507 |
| 10 | 3.2167 | 0.5645 | 0.6174 |
| 50 | 3.1770 | 0.8267 | 0.4415 |
| 100 | 3.1371 | 1.0889 | 0.3003 |
| 300 | 3.0482 | 1.6743 | 0.1113 |
| 500 | 3.0153 | 1.8907 | 0.0855 |
第 1 轮 w 就到 2.1673,第 500 轮收敛到 3.0153,b 收敛到 1.8907。
真实值是 3 和 2。机器从来没有见过「3」和「2」这两个数,它是从一百个点里一点点试出来的。
③ 三个数就能描述这个模型
--------------------------------------------------------------------
学到的东西:y = 3.0153 * x + 1.8907
一共几个参数?2 个。
这就是机器学习的全部含义:先假定一个函数形状(这里是直线),再用数据把里面的参数调出来。
「学习」这个词听着玄,其实就是「调参数」。
调法有很多种(梯度下降只是其中一种),但目标只有一个:让预测值和真实值的差尽量小。
④ 模型就是参数,参数不对就全错
--------------------------------------------------------------------
| 参数 | 误差(均方) |
|---|---:|
| w=1.00 b=2.00 | 131.2516 |
| w=3.00 b=2.00 | 0.0815 |
| w=6.00 b=2.00 | 295.8514 |
| w=3.02 b=1.89 | 0.0855 |
w 从 1 改到 3,误差掉了一大截;改到 6 又涨回去。同一个函数形状,参数不同,误差差几十倍。
所谓训练,就是在参数空间里找误差最小的那个点。
⑤ 跟「什么都不学」比一比
--------------------------------------------------------------------
直接拿平均值 16.848 当预测:误差 74.8754
训练出来的直线: 误差 0.0855
好了 876.1 倍
基线很重要。
一个模型误差 0.08 听着不错,但如果「全猜平均值」只要 0.09,那这个模型几乎没学到东西。
所以任何模型报告效果时,都要跟一个笨办法比一比。差得不多就说明白干了。
第二张表是本篇的核心:从 39.25 一路降到 0.0855,每一轮都在往低处走。 注意第 1 轮就跳到 2.17,说明学习率 0.01 对这个尺度来说偏大,但还没大到发散。 第三段那句话值得抄下来:模型不是程序,是一组数。这解释了为什么部署模型这么便宜。 第四段里 w=3、b=2 的误差(0.0815)比训练结果(0.0855)还小,因为梯度下降只保证「往好的方向走」, 不保证走到最好。 最后跟平均值基线比,876 倍。这个倍数不是模型厉害,是数据本身有强规律。 换成噪声更大的数据,倍数会小很多。
30 秒实验
- 把学习率 lr 改成 0.001,跑 500 轮,看 w 停在多少——会不会还没走到 3。
- 把 lr 改成 0.1,跑 50 轮,看误差是不是炸了(发散)。
- 把噪声从 ±0.5 改成 ±2,重跑,看最后的误差变大多少,但 w 是不是还能接近 3。
常见误区
- 「机器学习能自己发现规律。」它只能在你给的函数形状里调参数。 形状选错了,参数调得再好也没用。
- 「误差越小越好。」训练误差能压到 0,但那是记住了噪声。要看没见过的数据。
- 「模型很智能。」一个线性模型就是两个数。它的「智能」全在数据里。
自测三问(点开对答案)
1. 梯度下降每一轮在做什么? —— 算当前参数下误差对每个参数的偏导(梯度),然后沿反方向挪一小步。步子大小就是学习率。 2. 为什么说「模型不是程序,是一组数」? —— 因为训练完之后,模型只剩参数。做预测时只是一次乘加运算,没有任何分支或循环。 3. 训练出来的直线误差 0.0855,而 w=3、b=2 时误差 0.0815,是不是说明训练失败了? —— 不是。梯度下降只保证逐步变好,不保证全局最优。在真实的高维问题里,找到「够好的解」就是目标。下一篇讲训练完之后怎么判断好坏:切数据、看测试误差、识别过拟合。
- ☐ (本篇完,下一篇 4.2 学习的三步:准备、建模、上线)