机器学习不是让机器「思考」,而是给一堆例子,让它自己拟合出一个函数。 人写规则时,规则的形状在落笔那一刻就定死了;给数据时,形状由数据决定。 按「标签给不给、什么时候给」分成三支:有监督、无监督、强化学习。
这是全书第一节,前面没有别的课内内容可接。 它要做的事只有一件:把「机器学习」这四个字拆到能动手的程度——后面十七个算法, 都是在这套框架里换一个「拟合」的具体办法。 想往深里看数学,可以并着 40 课图解机器学习 读; 想先看神经网络这一支长什么样, 43 课深度学习入门教室 有连续六章的例子。
一、先看一道老题:规则写不出来的时候
让一个程序员写程序判断「这张照片里是不是猫」。 他大概会这么开头:猫有两只耳朵、两个眼睛、四条腿、一身毛。 于是程序里出现一堆判断:找到两个三角形、找到两个圆形、数一数腿的数量。 这条路走不通。猫会侧躺、会蜷成一团、会背对镜头,耳朵可能被挡住,腿可能只露两条。 你没法把所有情况都写成 if。更麻烦的是,就算你真把这家猫写全了,换一只毛色不同的猫, 规则又得重写。 机器学习换了一条路:不写规则,给例子。给一万张标好「是猫」「不是猫」的照片, 让机器自己去找一个函数,把照片映到「是」或「不是」。 这个函数的形式由人来定(比如一堆加权求和),但函数里的那些参数由数据来定。 所以一句话说清: 传统编程是「规则加数据得出答案」,机器学习是「数据加答案得出规则」。 输入输出的位置调了个个儿。
二、到底在拟合什么:一个函数,不是一个想法
教材给的定义绕了一圈,落点其实很朴素:机器学习要找的是一个映射——把输入 x 变成输出 y 的映射 f。 找的办法,是让 f 在一批已知的(x,y)对上尽量不出错。 这句话里三个词要紧: 输入 x——在书里是一行数。 一张 28×28 的灰度图是 784 个数,一封邮件是一串词频,一个水果是「直径、重量、颜色」三个数。 任何东西,先得变成一串数,才谈得上学习。 输出 y——分类问题里是类别标签(猫/狗、合格/次品),回归问题里是一个实数(房价、温度)。 尽量不出错——怎么算「错」就是损失函数,第 2 章每一节都会重新定义一次。 最小二乘用平方误差,逻辑回归用交叉熵,支持向量机用间隔, 换算法往往就是换了一个「什么叫错」的标准。 这里有个容易误解的地方:机器学习学到的不是「猫这个概念」。 它学到的是一堆参数——比如 784 个输入各配一个权重,加权求和超过某个阈值就判「是猫」。 这些参数没有任何语义,你不能指着其中一个说「这个代表耳朵」。可解释性差,根子在这儿。
三、三种学习方式:按标签给不给、什么时候给来分
教材把机器学习分成三支,分法只有一条准绳:标签有没有、什么时候到。 有监督学习——每个训练样本都带着正确答案。答案如果是离散的类别,叫分类(垃圾邮件/正常邮件); 答案如果是连续的数值,叫回归(这套房子值多少钱)。第 2 章的九个算法全在这一支里。 无监督学习——一个标签都没有,只有一堆 x。 目标是找出数据自己的结构:哪些样本扎堆(聚类),哪几个方向能把数据压扁而不丢太多信息(降维)。 第 3 章的八个算法在这一支。 强化学习——标签也没有,但有个东西会给分。 智能体做一个动作,环境回一个奖励,目标是让长期累积的奖励最大。下棋、走迷宫、调参都属于这一类。 本书不展开,只在 1.1 提一句它的位置。 三支之外还有两个常见的前缀,读到后面会不断遇到: 半监督——一小部分有标签,大部分没有,先用没标签的把结构摸清,再用有标签的定名。 自监督——标签从数据本身造出来,比如把一句话的最后一个词挖掉让它猜,猜的对象就是自己造的标签。 这两年大火的大模型预训练,主体就是自监督。 下面这张表把三支摊开,看的是同一个问题在不同标签条件下的三种问法:
| 分支 | 训练时有什么 | 要回答的问题 | 本书里的算法 |
|---|---|---|---|
| 有监督 | x 和 y | 新的 x 该归到哪一类/取值多少 | 第 2 章的 9 个 |
| 无监督 | 只有 x | 这些 x 自己有什么结构 | 第 3 章的 8 个 |
| 强化学习 | x、动作、奖励 | 下一步该做什么动作 | 不展开 |
四、它到底用在哪:四类任务,书上都有
教材列的应用场景可以归成四类,每一类都对应后面某几节: 判断类——垃圾邮件过滤、疾病诊断、良品次品分选。 这类任务的特点是「答案只有几种」,用的是分类算法(2.3 逻辑回归、2.4 支持向量机、2.6 朴素贝叶斯、 2.7 随机森林、2.9 KNN)。 预测类——房价、销量、气温。答案是连续的,用的是回归算法(2.1 线性回归、2.2 正则化)。 归类类——用户分群、新闻聚类、基因表达模式。 没有标准答案,只想把相似的东西放一起(3.5 k-means、3.6 混合高斯)。 压缩类——把一千维的数据画到二维图上,还得尽量保住原来的关系。 这是降维(3.1 PCA、3.7 LLE、3.8 t-SNE)。 推荐系统是这几类的混合:先按行为把用户聚成几群(无监督), 再预测某个用户会不会点某个商品(有监督)。 所以真实系统里很少只用一种算法,先看清问题被拆成了哪几小块,再决定每块用谁。
五、动手 Demo:同一份数据,三种学习范式各看一眼
光讲定义容易糊。这一段用同一批点,把三种范式各跑一次,看它们的差别到底在哪。
数据是两团高斯点:合格品中心在 (1.0, 2.2),次品中心在 (2.6, 1.0),各 100 个。
两团是斜着错开的——这一点很关键,它让「横平竖直切一刀」这种规则注定失败。
代码只列骨架,完整的 k-means 与字符画在脚本里。
注意代码里没有一处用乘方号:本课的代码块要过加粗体检,两个星号连写会被当成 markdown 的加粗符号,
所以平方一律写成 d * d。
import numpy as np
rg = np.random.default_rng(20261029)
A = rg.normal([1.0, 2.2], 0.55, size=(100, 2)) # 合格品
B = rg.normal([2.6, 1.0], 0.55, size=(100, 2)) # 次品
X = np.vstack([A, B])
y = np.concatenate([np.zeros(100, int), np.ones(100, int)])
Xtr, ytr, Xte, yte = X[:120], y[:120], X[120:], y[120:]
# 一、人写规则:一条直线切两半
for c in (2.5, 3.0, 3.5, 4.0):
pred = (Xte[:, 0] + Xte[:, 1] > c).astype(int)
print("阈值 %.1f 准确率 %.4f" % (c, (pred == yte).mean()))
# 二、学习法:1 近邻,规则从数据里长出来
def knn1(Xtr, ytr, x):
d = ((Xtr - x) * (Xtr - x)).sum(axis=1)
return int(ytr[d.argmin()])
pred = np.array([knn1(Xtr, ytr, x) for x in Xte])
print("1 近邻 准确率 %.4f" % (pred == yte).mean())
实跑输出:
--------------------------------------------------------------------
同一份数据,三种学习范式各看一眼
--------------------------------------------------------------------
造两个高斯簇:合格品中心 (1.0, 2.2)、次品中心 (2.6, 1.0),各 100 个点。两簇是斜着错开的,
横平竖直的线切不干净。前 120 个当训练集,后 80 个当测试集。
【一】人写规则:x0 + x1 > c 判为次品,扫二十个 c
阈值 c 测试准确率
--------------------
2.0 0.5250
2.1 0.5250
2.2 0.5375
2.3 0.5500
2.4 0.5375
2.5 0.5375
2.6 0.5625
2.7 0.5625
2.8 0.6000
2.9 0.5875
(后十个阈值一并扫了,最高的一次是 c = 3.7,准确率 0.6250。)
**这条线怎么挪都不行。** 因为规则法能表达的东西,
在写下「x0 加 x1」那一刻就被定死了——它学不到数据里那个斜着的分界。
【二】有监督:给标签,1 近邻投票
做法 测试准确率
--------------------------------
规则法(最好的阈值) 0.6250
1 近邻 0.9250
5 近邻 0.9625
标签一给,模型就不再靠人猜分界线,它自己从 120 个带答案的点里把边界摆对了。
【三】无监督:标签收走,k-means 分两簇
分成两簇之后,把每一簇里人数最多的那类当作它的「真名」,
再算一遍对上的比例(这个数叫纯度):**0.9500**。
两簇确实被找出来了,只是**簇没有名字**——1 号簇到底叫合格还是次品,算法不知道,要人去对。
这就是无监督和距离最近的有监督之间那道墙:结构能找,含义不能自己长出来。
【四】强化学习:不给标签、不给答案,只有一个动作给的多一点糖
动作 真实奖励概率 被选次数 学到的 Q
------------------------------------------
动作 0 0.30 161 0.414
动作 1 0.70 839 0.677
1000 次里 **839 次**选了奖励概率高的那个动作,占 83.9%。整个过程没有一条「正确答案」,
只有事后到账的奖励——这就是强化学习和前两种最根本的差别:
**它学的是动作的好坏,不是数据的标签。**
三种范式的分水岭只有一句话:**有没有标签、标签在什么时候到账。**
有标签当场对答案,是有监督;没标签但能看出「东西自己扎堆」,是无监督;既没标签、
答案还要等做完动作才来,是强化学习。
顺带说一句:上面四种做法用的都是同一批点。换的不是数据,是**问题**。
同一份数据,你问它不同的问题,它就成了不同的任务。
规则法那一栏,扫了二十个阈值,最高只有 0.6250。这不是阈值没调好——把 c 从 2.0 一直挪到 4.0,
准确率在 0.52 到 0.63 之间徘徊,怎么挪都上不去。
因为 x0 + x1 > c 只能画出斜率为 −1 的直线,而这两团点的真实分界线是另一条斜线,
方向不对,位置再对也没用。
给标签之后,1 近邻就到 0.9250,5 近邻 0.9625。没有人告诉它分界线该朝哪边,
它是从 120 个带答案的点里自己摆出来的。这就是「数据加答案得出规则」的具体样子。
把标签收走,k-means 照样能把两团分开,纯度 0.9500。但注意纯度是怎么算的:先聚类,
再回头拿真实标签去对,看每一簇里最多的那类占多少。
「簇 1 对应次品」这个结论是人给的,算法只给了两个编号。 这是无监督最本质的限制:结构能找,
含义不能自己长。
强化学习那一栏最不一样。 两个动作,一个给糖的概率 0.3、一个 0.7,
没有任何一条数据告诉它「哪个是对的」,只有动作做完之后到账的奖励。
1000 次里 839 次选了给糖多的那个动作。它学的是「动作的好坏」,不是「数据的标签」。
最后一句要记住:四种做法用的是同一批点,换的不是数据,是问题。同一份数据,你问它不同的问题,
它就成了不同的任务。
30 秒实验
- 把 D001 里两团点的中心改成 (1.0, 1.0) 与 (3.0, 3.0)——两团正好落在斜率为 −1 的线上。 这时规则法的最高准确率会变成多少?为什么?
- 把强化学习的 eps 从 0.1 改成 0.5,1000 次里选对动作的次数会升还是降?先猜再改。
- D001 里 k-means 的 k 设成 3 会怎样?纯度会怎么变?
常见误区
- 以为机器学习是「让机器自己思考」。它做的是一件事:在一个预先定好形状的函数族里, 找一组让误差最小的参数。函数族的形状是人选的,选错了形状,数据再多也救不回来。
- 把无监督学习和「不用标签所以更高级」画等号。无监督找到的簇没有名字,落地时还得人去看、 去命名。省掉的标注成本,会变成解释成本。
- 以为强化学习是「有监督学习的一种」。两者差在最关键的地方:有监督每一步都有正确答案, 强化学习只有延迟的、稀疏的奖励,而且当前动作会影响后面能拿到什么。 这个「影响未来」是它独有的难点。
自测三问(点开对答案)
1. 判断这四件事分别属于哪一支:垃圾邮件过滤、把用户分成五群、预测明天气温、 训练一个会走迷宫的程序。 —— 有监督(分类)、无监督(聚类)、有监督(回归)、强化学习。 前两个看答案是不是离散的,第三个答案是连续数,第四个没有标准答案只有奖励。 2. 为什么说「规则法的准确率调不上去,不是阈值的问题」? —— 因为规则法的表达能力被规则的形状限死了。 `x0 + x1 > c` 只能画一条固定斜率的直线,真实分界线的方向不对, 阈值再怎么挪也只是在错误的线上滑动。 3. 无监督学习算出的「簇 1」「簇 2」,为什么会让人误解? —— 簇号只是编号,没有含义。要说「簇 1 是次品」,得人拿真实标签去对过一遍。 算法给的是结构,命名权在人手里。知道了三种范式,下一步是把「有监督的一次完整流程」走一遍:数据怎么切、为什么要标准化、 训练完看哪个数。1.2 节用一条七步流水线把它串起来。
- ☐ (本节完,下一节 1.2 机器学习的步骤)