大模型通识 / AI 理论基础
2. 机器学习:程序怎样从数据中学到规律
原文备份 · 第 3 / 14 篇 · 查看极客时间原知识库 ↗
本篇目录 · 7 节
来源:AI 理论基础
假设你想给自己的邮箱加一个垃圾邮件过滤器。最初的规则很简单:正文里出现“免费”或“中奖”,就放进垃圾箱。
很快,你发现一封正常邮件也被拦住了:“你已购课程的免费补课安排。”于是补上一条:熟悉的发件人不拦截。随后又遇到陌生地址发来的正常验证码,以及看起来很像正常通知的广告。规则越来越多,例外也越来越多。
机器学习提供了另一种处理方式:整理一批已经判断过的邮件,让程序依据这些例子选择判断方式。但“依据例子选择”究竟发生了什么?模型会把邮件背下来吗?它如何处理下一封邮件?
这一篇用一个小到可以手算的分类器,把样本、特征、标签、参数和预测连起来。读完后,你应该能指出哪些信息来自输入,哪些数值通过学习确定,以及为什么模型在旧数据上表现好,还需要接受新数据的检验。
下面的邮件、参数与结果都是为解释机制而构造的教学例子,不是真实邮箱的实验,也不能用于判断实际产品效果。 不需要安装软件,只需会加减乘法。
从一封邮件开始:样本、特征与标签
我们先准备六封邮件,并约定两种分类结果:垃圾邮件记为 1,正常邮件记为 0。表中的判断由整理数据的人根据背景给出。
| 编号 | 邮件内容或背景 | 发件人在通讯录中 | 已知分类 |
|---|---|---|---|
| A | 未请求的推销:“恭喜中奖,点击领取” | 否 | 垃圾,1 |
| B | 未请求的推销:“免费领取礼品,立即登记” | 否 | 垃圾,1 |
| C | 已购课程通知:“你已购课程的免费补课安排” | 是 | 正常,0 |
| D | 同事通知:“明天的会议改到下午” | 是 | 正常,0 |
| E | 正规服务:“你刚申请的登录验证码” | 否 | 正常,0 |
| F | 已报名活动:“你报名的免费公开课即将开始” | 是 | 正常,0 |
这里的一封邮件及其相关记录,就是一个样本,sample 或 example。把许多样本放在一起,形成一个数据集,dataset。
为了看清计算过程,我们暂时不让模型直接处理整段文字,而是只给它两个数字:
u:内容里是否出现“免费”或“中奖”这两个指定字符串中的任意一个。出现记为 1,否则记为 0。v:发件人是否在通讯录中。在记为 1,否则记为 0。
这两个供模型判断的输入叫作特征,feature。已经给出的分类结果叫作标签,label,用 y 表示。样本、输入特征和目标标签,是理解监督学习的基本概念。Google:监督学习基础
经过转换,模型面对的是下面这张表:
| 样本 | 特征 u:出现指定词 | 特征 v:在通讯录中 | 标签 y:是否垃圾 |
|---|---|---|---|
| A | 1 | 0 | 1 |
| B | 1 | 0 | 1 |
| C | 1 | 1 | 0 |
| D | 0 | 1 | 0 |
| E | 0 | 0 | 0 |
| F | 1 | 1 | 0 |
请留意:模型的判断公式只接收 u 和 v,不会把这一行的 y 当作判断依据。标签用于检查它猜得对不对。如果先把正确答案交给它,再问分类准不准,就失去了检验意义。
这张表也暴露了我们的主动取舍。模型不知道 C 中的课程是否真的购买过,不知道 E 的验证码是否真的申请过;这些背景帮助人确定标签,却没有进入这两个特征。人看过原文,不等于模型获得了原文里的全部信息。
模型先要有一种可以调整的判断方式
我们给模型安排一个简单结构:先算分,再按分数分类。
分数 = a × u + b × v + c
分数 ≥ 1:预测为垃圾邮件
分数 < 1:预测为正常邮件
先别被字母吓住。u 和 v 是这一封邮件带来的输入;a、b 和 c 是控制计算方式的三个数。
a 决定指定词对分数的影响,b 决定通讯录信息对分数的影响,它们叫作权重,weight。c 是无论输入如何都会加上的偏移量,通常叫作偏置,bias。这里的“偏置”是数学名称,并不是在说社会偏见。
这些可由训练确定的数值,统称为参数,parameter。加权相加再加偏置,是许多模型里会遇到的基本计算形式;Google 的线性回归教材也用这种形式解释权重和偏置。我们这里又加了分类阈值,因此整个例子是一个简化分类器,不是用来预测连续数值的线性回归任务。权重、偏置与加权计算
本例把分类阈值固定为 1,只学习 a、b、c。真实系统也可能另外选择阈值,但那是另一个设计决定。
例如,暂时取 a=1、b=-1、c=0。邮件 C 的两个输入都是 1,算出来是:
分数 = 1 × 1 + (-1) × 1 + 0 = 0
0 小于 1,因此预测为正常邮件。
这里的分数不是概率。分数为 0 不代表“垃圾邮件概率为 0%”,分数为 -1 也没有数学矛盾;它只是这套判断规则的中间数值。
更关键的问题还没回答:为什么选这三个参数值,而不是别的值? 只有说明它们怎样由数据确定,才真正进入了“学习”。
用数据选择参数,就是一次极简的学习
为了让整个过程可以看完,我们只允许程序考虑三组候选参数。候选范围由人预先设定,程序的任务是:对每一组参数,把六封邮件都算一遍,数出预测错误的数量,选错误最少的一组。
| 候选 | a | b | c | 对应分数 | 六封邮件中判断错误的样本 |
|---|---|---|---|---|---|
| 甲 | 1 | 0 | 0 | u | C、F,共 2 封 |
| 乙 | 1 | -1 | 0 | u − v | 无,共 0 封 |
| 丙 | 0 | -1 | 1 | 1 − v | E,共 1 封 |
可以检查一下甲为什么出错。它只看指定词,C 和 F 都有“免费”,分数都是 1,于是被判成垃圾邮件。但标签显示它们是正常邮件,所以计为两次错误。
再看丙。它完全不看内容,只要不在通讯录中,分数就是 1。A、B 确实是垃圾邮件,但 E 是用户刚申请的正规验证码,因此丙错了一次。
乙在这六个样本上没有错误,于是程序选择 a=1、b=-1、c=0。学习的结果可以保存为这三个参数,之后继续用于新邮件。
整个过程可以画成两条路径:
学习阶段:
六封已分类邮件 → 提取特征 → 逐组尝试参数
↓
将预测与标签比较,数错误
↓
保存错误最少的参数
使用阶段:
一封新邮件 → 提取相同特征 → 使用已保存参数 → 给出预测
这里,数据、模型结构、评价好坏的目标,以及搜索参数的方法,已经齐了。《动手学深度学习》也用数据、模型、目标函数和优化算法来组织机器学习的基本组成。教材:机器学习的组成
我们的目标是减少训练样本上的错误数量,方法是穷举三组参数。它非常简陋,却足以展示一个完整的学习过程。如果换一批邮件或换一套标签,程序可能选中另一组参数。
反过来,如果开发者不让程序比较样本,只凭经验直接写死 a=1、b=-1、c=0,那么即使最后得到同样的公式,也不能说这三个数是本次程序从数据中学到的。判断是否发生学习,要看参数或判断方式怎样获得,而不只看最后的公式长什么样。
真实训练通常不会只在三组数中挑选。许多模型会依据目标逐步更新大量参数,也常使用比“数错了几次”更适合优化的损失函数。第 06 篇会讲如何衡量误差,第 08 篇再解释参数如何一步步更新。现在不需要提前掌握那些公式。
使用模型时,变的是输入,不一定是参数
参数选定后,一封新邮件到来,我们只需按相同方式提取 u、v,放进 分数=u−v,再看是否达到阈值。
这个计算过程叫作预测,prediction,也是运行已训练模型进行推理的一种情形。“预测”不一定在猜未来:判断当前这封邮件属于哪类,也叫预测。
此时,邮件可以一直变化,参数却保持不变。新邮件不会仅仅因为被分类过,就自动成为新的训练材料。即使用户点了“判断错误”,也还需要有保存反馈、整理标签和重新训练等机制,反馈才可能进一步改变参数。
这能帮助你分清五个常见词在同一个任务里的位置:
| 概念 | 本例中指什么 | 什么时候会变化 |
|---|---|---|
| 样本 | 一封邮件及其相关记录 | 换邮件就换样本 |
| 特征 | 这封邮件的 u、v | 随邮件内容和发件人信息变化 |
| 标签 | 已知的垃圾或正常分类 | 来自标注;不由当前模型预测自动保证正确 |
| 参数 | 控制打分的 a、b、c | 在本例的学习阶段选定 |
| 预测 | 模型本次给出的分类 | 用当前输入和参数计算得到 |
标签也可能标错。例如,整理者没有注意到用户主动报名了活动,把 F 标成垃圾邮件,训练过程就会接收到另一种信号。学习程序并不会天然知道标签背后的现实事实。这个问题会在数据篇继续展开。
六封全部答对,为什么还不能放心使用
现在取三封没有参与参数选择的新邮件,检验乙的表现:
| 新邮件 | u | v | 分数 u−v | 预测 | 根据背景确定的分类 |
|---|---|---|---|---|---|
| G:通讯录里的同事说“下午三点开会” | 0 | 1 | -1 | 正常 | 正常 |
| H:陌生人发送未请求的“中奖补贴请领取” | 1 | 0 | 1 | 垃圾 | 垃圾 |
| I:课程方的新地址发来“你已报名课程的免费回放” | 1 | 0 | 1 | 垃圾 | 正常 |
模型错在 I 上。课程方换了地址,暂时不在通讯录里,而正文又包含“免费”,两个特征恰好与 A、B 一样。
从人的角度,A 和 I 有明显区别:一封是未请求的推销,一封是已报名课程的通知。但对只接收 (1,0) 的模型来说,它们是同一个输入。只要判断方式固定,同一个输入就会得到同一个输出,无法同时满足两个相反的标签。
这是一个比“参数还不够好”更具体的问题:用来区分它们的信息,没有进入模型。 可以考虑增加报名记录、域名信息,或让模型读取更完整的内容,再检验是否有效。仅仅把处理这两个数字的模型做大,并不能凭空恢复缺失的信息。
这三封新邮件是说明问题的反例,不是有统计代表性的测试集。“三封答对两封”不能据此宣传真实邮箱准确率约为三分之二。
但它说明了评估的基本原则:用来学习的数据表现好,并不能单独证明模型对未见输入也表现好。scikit-learn 的评估文档特别区分了训练数据与留出数据;反复依据同一份测试结果改模型,也会破坏最终检验的独立性。训练与独立评估
在实际项目里,若已经用 I 这个错误指导修改,它就成了开发过程中见过的案例。修改后仍应准备另外的、没有参与这些决定的数据,检查改进能否成立。第 09 篇会进一步区分训练集、验证集和测试集。
从邮件分类,回到大模型应用开发
看完这个例子,容易产生另一种误会:既然模型能学规则,以后是不是所有规则都应交给它学习?
仍要看任务。“分数超过阈值后显示一个提示”是清楚的程序逻辑,“哪些邮件看起来像垃圾邮件”则存在许多难以穷举的变化。二者可以配合。模型预测为垃圾邮件后,应用可以标记、移入可恢复目录,或者请用户确认;预测结果本身并不等于必须采取某个动作。
换成前一篇的个人复习助手,道理一样。你可以训练一个小模型给笔记分类,也可以调用已经训练好的大语言模型,让它根据当前笔记判断类别。后一种情况下,你在使用已有模型的能力,不必先完成一套模型训练。
给语言模型几个分类示例,让它照着处理当前笔记,也不等于你已经执行了参数训练。它可能根据输入中的示例调整本次回答,但这与前面“依据数据选定并保存新参数”的操作不同。第二部分会解释这种在上下文中利用示例的机制。
对应用开发者来说,本篇最有用的习惯是:当模型答错,先明确它实际看到了什么、你希望它输出什么、依据哪些例子认为它应该能做到。这样的排查,比只说“它还不够聪明”更容易找到可改进的地方。
理解检查:亲手走完一次判断
先用选出的参数 a=1、b=-1、c=0、阈值 1 回答,再看后面的解释。
- 一封来自通讯录好友的邮件包含“免费”,分数是多少?模型预测什么?这个结果能否证明邮件一定正常?
- 两封邮件的两个特征完全相同,标签却相反。保持这个固定模型及输入不变,它能同时正确分类吗?
- 训练数据六封全部答对,是否可以宣布模型已适合真实邮箱?
- 用户纠正了一次分类结果,但应用只把这条纠正写进日志,没有再次训练。三个参数会自动改变吗?
第 1 题: u=1、v=1,所以分数是 0,预测正常。它只是模型依据两个特征作出的判断,不能证明现实中的邮件一定正常;分数也不是概率。
第 2 题: 不能。固定模型对同一输入给出相同预测,因此至少会错一个。需要检查特征是否遗漏信息,也要检查标签是否一致,而不是只继续微调这三个数。
第 3 题: 不能。六个样本可能过少、过于单一;模型也可能利用了在新邮件中不成立的线索。需要独立且符合使用场景的评估。
第 4 题: 不会。保存反馈和用反馈更新模型,是两个步骤。反馈可以成为后续改进的材料,但日志文件的变化不等于模型参数已经变化。
如果这四题能解释清楚,你已经能把“模型从数据中学习”拆成可检查的环节。下一篇还要追问一个问题:这里每封邮件都有人给答案,其他机器学习也必须如此吗?我们将从训练信号的来源出发,理解监督学习、无监督学习与自监督学习。
上一篇:01|先建立一张地图:AI、机器学习、深度学习与大模型是什么关系
下一篇:03|监督学习、无监督学习与自监督学习:训练信号从哪里来
返回:第一部分大纲