训练和推理,听起来像同一件事。很多人第一次接触模型时,这两个词在脑子里是糊在一起的。想分清它们,最快的办法不是打开某个工具,而是拿一张纸、一支笔,亲手跑一遍。
整个练习不需要安装任何东西,不用注册账号,不用写代码。成本为零,收尾就是把纸塞进抽屉。目标也不是做出一个有用的模型,而是按顺序看清四件事各自发生。
这四个词必须先分开:算法是把样本数据变成模型的学习流程,也就是配方;训练是算法跑在数据上的那个阶段;模型是训练出来的结果,接收新输入并给出预测;推理是用训练好的模型处理新输入。
拿面包房打比方:配方是算法,烘烤是训练,面包是模型,切一片端出去是推理。配方不是面包,面包也不会在被人吃的时候还在烤。
第一步:写下带标签的训练数据
画一张小表,每行是一次配送,记录距离和是否迟到。这些数字是为练习编的,不对应任何真实公司。六行数据里,“迟到”这一列记的是每行的正确答案。
这张表有两个特点值得注意。第一,它是带标签的数据:每个样本的正确结果都被记了下来。正因为答案有记录,才能走监督学习这条路——从样本和对应正确输出中学习。如果没人记下哪些配送迟到了,这条路就走不通,行数再多也没用。
第二,它是结构化数据,遵循固定的行列结构。一堆扫描的配送单承载的是同样的事实,但属于非结构化数据,没有固定的数据模型,学习开始前需要多得多的准备工作。
在表格下面画一条线,再写四行训练时不看的记录:3公里不迟到、6公里不迟到、11公里迟到、14公里迟到。这是测试数据。把它盖住,是整个练习里最重要的动作。只有这样才能看出,模型学到的是规律,还是只记住了那六行。
第二步:跑算法,得到一个模型
算法用大白话写出来是这样:在每对相邻距离之间试一个分界值;对每个分界值,把距离超过它的配送都预测为迟到;数一数这个预测在六行训练数据上错了几行;留下错得最少的那个分界值。
现在跑一遍。分界值取8.5公里,只把E和F预测为迟到。它把C判错了,因为C在5公里处确实迟到了,其余全对:错一个。分界值取4.5公里同样只错一个,错在D。两者打平,按约定选8.5公里,继续往下走。
手里现在拿到的就是模型:一句话,“距离超过8.5公里即迟到”。它不是那四步流程,而是流程产出的东西。下个月收集到更多配送数据、想要更好的分界值,就把算法在新数据上再跑一遍。这叫重新训练,也是这个模型唯一的改变方式。
在模型旁边写下训练得分:六对五。
第三步:揭开测试行,给模型打分
揭开那四行测试数据,把这句话逐行套上去。3公里预测不迟到,对;6公里预测不迟到,也对;11公里和14公里预测迟到,都对。四对四。
现在有两个数字:一个来自模型学过的数据,一个来自它从没见过的数据。把这两个数字放在一起读,是判断模型的核心技能。只看训练数据上的好成绩,说明不了什么——那些答案它已经见过了。
第四步:用模型处理一次新配送
来了一单9公里的新配送。只看那句话,别的都不看:超过8.5公里,预测迟到。这就是推理。没有翻训练表,没有重跑那四步。算法和训练数据在这个阶段不参与,参与的只有模型。
训练是费力的,发生在模型被构建或重建的时候;推理是快的,每次使用模型都会发生。一个常见的错误正好踩在这条线上:真正的问题出在答案怎么送到需要它的人手里,却被提成了“重新训练”。
第五步:故意让它死记硬背,看它坏掉
再建第二个模型,算法更懒:“原样抄下训练表;表里没有的距离,一律答不迟到。”
在训练数据上打分,六对六,满分。它给出的每个答案都是从表里直接抄的。换到测试行,画面就变了。3、6、11、14公里都不在它的表里,于是四次全答“不迟到”,对两次错两次:四对二。
这就是过拟合:在训练数据上得分很高,在新数据上表现很差,因为它学的是样本本身连同各种怪癖,而不是样本背后的规律。就像一个把去年答案背下来的学生,换了张卷子就懵了。注意这个死记硬背的模型连C都原样复现了——那个5公里处迟到的异常样本。而分界值模型明智地把它判错了,那一个训练错误,恰恰是它在新数据上站得住的原因之一。
为了完整,再看相反的失败。用一个永远答“不迟到”的模型,训练六对三,测试四对二。两边都低,这叫欠拟合:模型太简单,根本找不到规律。
训练分和测试分之间的差距,就是区分过拟合和欠拟合的依据。记住一条数字判据:训练高、新数据低,是过拟合;两边都低,是欠拟合;两边都好,是拟合良好。过拟合的解法是让模型泛化得更好,比如降低它的灵活度,正则化就是这类技术的名字之一。那句一行的分界值模型已经灵活到不能再低,这正是它赢过死记硬背模型的原因。
第六步:决定模型怎么回答人
模型能用了,接下来的实际问题是它怎么被用起来。常见的服务方式有四种,决定性的问题是“谁在等”,而不是模型本身。
- 实时:有人此刻正等着答案,比如电话那头的调度员。
- 无服务器:请求成批到来,中间有空闲间隔,安静一段时间后第一次回答慢一点可以接受,因为空闲时容量会缩到零。
- 异步:每个请求都很大或很慢,于是进队列,结果稍后从某个存储位置取回。
- 批量:整个数据集在一个任务里打分,比如明天所有排班的配送,任务之间不需要任何东西保持运行。
可以想成邮局:有人排队就开柜台,一袋邮件夜里分拣,大包裹留着等人来取。先看谁在等,再看数据集形态,然后看请求大小,最后看流量模式。
最容易混淆的一对是异步和批量。一个属于某个数据集、一次性打分的大文件,仍然是批量。一个单独到达、进入队列的大文件,是异步。第二个坑:数据持续到达,不等于有人在等答案。仅凭持续到达,推不出需要实时服务。
为什么纸面版本能迁移
接下来用的任何无代码工具,都会换一套说法问你同样的问题:哪一列是要预测的答案?数据该怎么切分做测试?两个分数长什么样?预测会以什么方式被请求?如果你知道选中的那列叫标签,“构建”就是训练,“预测”就是推理,工具界面就好读多了。
这个练习还留下一个值得保持的习惯:先问结果有没有被记录,再问别的。问“有没有标签”,决定监督学习这条路开不开;问“数据有多少”,本身什么都定不了。然后先比较两个分数,再决定信不信其中任何一个。最后,从“谁在等”出发决定服务方式。
几条要点:算法是流程,模型是它的产出;训练构建模型,推理只是反复使用它。监督学习需要带标签的数据,正确答案有没有被记录,比有多少行更重要。永远留出测试数据,判断模型靠的是训练分和未见样本分的对比。先高后低是过拟合,两边都低是欠拟合,把样本背下来的模型可以看起来很完美,却在新样本上翻车。选服务方式,看谁在等、是否整批打分、单个请求多大、流量有多突发。
热门跟贴