我见过太多人学机器学习,路径惊人地一致:先看视频教程,再照着敲几个 demo,跑通了就觉得自己入门了。可一旦被问到底层问题——这个模型为什么有效?损失函数为什么这样设计?测试集分数高就一定代表模型可靠吗?就开始含糊。如果你也有这种“概念都见过、串不起来”的迷茫,问题大概率不在你不够努力,而在学习的时候没有先抓住主干。
机器学习的主干非常清晰,就是经典的三要素框架:模型、策略、算法,外加一个贯穿始终的环节——模型评估。模型决定你假设答案长什么样,策略决定你如何定义“好坏”,算法决定你用怎样的方式找到那个“好”的答案,模型评估则负责最后告诉你,这个答案放到真实场景里到底能不能打。这篇文章不打算做面面俱到的科普,重点就是把三要素和模型评估这条主线吃透,适合刚起步的人建立骨架,也适合学过一段时间但知识还散落一地的朋友把线串起来。
1. 学机器学习的正确打开方式:先抓住三要素这条主线
1.1 三要素的分工:模型、策略、算法各管哪一段
机器学习本质上是“从数据里自动找规律”:给定一组样本,让程序学习出一个从输入到输出的映射函数,并且这个函数对新数据也能给出合理预测。很多人觉得机器学习算法多、公式杂,是因为他们把每个算法当成独立知识点去死记。实际上,几乎所有监督学习算法都跑不出同一个流程:先规定一个可选的函数范围,再定一个衡量好坏的准则,最后用优化方法把最优函数找出来。这三个环节,就是三要素各自的分工。
模型对应的是“候选函数范围”,也叫假设空间。线性回归的假设空间是所有形如 (f(x)=wx+b) 的一次函数,逻辑回归的假设空间则是经过 sigmoid 变换的函数集合。策略是判断哪个函数更好的准则,表现在目标函数上就是损失函数加正则项。损失函数告诉模型每个候选函数在训练样本上“错多少”,正则项告诉模型“别把参数搞得太大、太复杂”。算法是具体怎么找最优解的方法,比如梯度下降、牛顿法,以及深度学习里的各种优化器。三者合起来,才构成一个完整的机器学习系统。
很多人以为深度学习是三要素之外的另一种东西,其实不然。一个卷积神经网络是模型,交叉熵是策略,Adam 优化器是算法。深度学习只是把模型做得更深、更复杂,把算法的工程实现做得更重,但骨架还是这一套。所以,如果你能把这套骨架内化,往后看任何一篇模型论文时,都可以先问三个问题:它改的是假设空间?改了评判标准?还是改了求解方式?带着这三个问题去读,效率会高很多。
1.2 把三要素装进一个例子里:房价预测如何串联全部概念
理论和概念不落到例子上,很难真正长在脑子里。后面讲的所有内容,我都会反复回到一个模拟场景:某城市二手房价格预测。
假设手上有一批历史成交记录,每条样本包含面积、房龄、楼层、到地铁站距离等特征,目标是预测成交价。按三要素的思路来拆:模型上,先假设价格近似是特征的加权和,即 (f(x)=\theta_0+\theta_1\cdot面积+\theta_2\cdot房龄+\dots),这就是线性回归模型。策略上,使用均方误差作为损失函数,衡量预测价与真实成交价的差距,同时加一个小的 L2 正则项防止权重过大。算法上,用梯度下降迭代更新参数 (\theta),直到目标函数收敛。最后做模型评估:把数据切成训练集、验证集和测试集,在训练集上优化参数,在验证集上监控是否过拟合,最后用测试集算 RMSE 和 (R^2),判断这套模型如果上线到底靠不靠谱。
这个例子看起来简单,但它把整篇文章要讲的点全部串起来了。模型没有选对,后面损失函数和优化算法再努力也白搭;损失函数选择不当,模型会陷入“只顾压极端误差”或者“对异常值缺乏反应”的偏科状态;评估环节如果做得不严谨,比如数据泄漏或者指标选错,分数再高也只是自欺欺人。后面每个章节,我都会不断回到这个例子上展开。
2. 要素一:模型——你学的其实是“假设空间”里的一族函数
2.1 假设空间:模型学习时到底在搜索什么
模型的本质是限定“搜索范围”。形式化地说,假设空间是从输入 (X) 到输出 (Y) 的所有候选映射函数集合。线性模型的假设空间是所有一次函数,多项式模型的假设空间包含一次、二次乃至更高次函数,决策树的假设空间是所有可能的树结构,神经网络的假设空间则是所有满足特定网络拓扑结构的参数化函数。
这里有一个特别容易被忽略、但特别关键的认知:如果真实规律压根不在假设空间里,那优化到死也找不到好解。这就好比你想在一栋楼里找人,但这个人在楼外的小区花园里,你拿着再精确的楼内导航也没有用。很多人在建模时反复调参、拼命迭代,效果却一直上不去,根子往往不在参数,而是在一开始就把搜索范围定错了。想象一下用线性模型去拟合周期性很强的日出日落光照数据,无论怎么调学习率、怎么加正则化,都不可能拟合出有周期性的预测结果。
这也是特征工程重要的理论原因。特征工程看似是在“加工数据”,实际上是在改变输入空间,让真实函数在新的假设空间里更靠近内部。把面积和房价的关系从线性假设改成面积平方项,就相当于把原本“只找直线”的搜索范围扩大成“允许找抛物线和更高次曲线”,模型才有机会表达非线性关系。理解了这一层,你再看特征工程就不会觉得它只是玄学操作了。
2.2 从线性到非线性:表达能力是把双刃剑
线性模型最大的优点是简单、可解释、不容易失控,缺点是表达能力有限。真实世界里很多关系都不是线性的,比如房价不会随着面积增大而无限线性上涨,户型、地段、楼龄之间还有各种交互效应。应对方式有两个方向:一个是手工加特征,把多项式项、交互项造出来塞进线性模型;另一个是直接换非线性模型,比如决策树、随机森林、梯度提升树,或深度神经网络。
但要注意,非线性的表达能力强,不代表一定更好。假设空间越大,越有可能找到一条“完美贴合训练集”的函数——问题是这个函数可能只是在死记样本,而不是在学规律。我经常用多项式拟合来举例子:给 (y=\sin(x)) 的函数采 10 个点,用 9 阶多项式可以做到几乎零误差穿过每一个点,可你一离开采样区间,曲线就开始疯狂震荡,预测结果离谱到不可信。神经网络同理,参数量一旦超过样本量所能约束的规模,它就更容易“背题”,而不是“学会解题”。
用个通俗的比方:线性模型像一张白纸的简笔画,画不了太精细但不容易画错;强非线性模型像一支可以调色的画笔,能画油画,但也可能把画面涂成一团乱麻。机器学习的日常,就是要在这两种风险之间找平衡。不存在一个放之四海皆准的最优模型,不同任务背后真实规律的复杂度不同,数据量不同,只能用实验来试探,这也是后面讲模型评估的意义所在。
2.3 模型选型的现实约束:数据规模、任务类型与可解释性
选模型没有银弹,但有几条我实际项目中反复用到的判断准则。
第一条是数据规模。几千条数据时,复杂神经网络的收益通常还不如树模型和线性模型,因为复杂模型的方差太大,喂不饱就会过拟合;数据到了几十万、几百万的量级,深度模型才开始有发挥空间。第二条是任务类型。回归问题先考虑线性回归、树模型;分类问题先考虑逻辑回归、树模型;序列建模、图像语音这类高维非结构化任务,则基本只能靠深度学习。第三条是可解释性。银行信贷、医疗诊断、法律风控这些领域往往需要说清楚“为什么给出这个判断”,线性模型和浅层决策树容易解释,黑盒模型很难过审计这一关。互联网推荐、图像识别这类以最终效果为先的场景,解释性的优先级就可以往后放。
我个人的工作习惯是:任何一个新项目,先跑一个简单 baseline,绝不直接上最复杂的模型。线性回归或逻辑回归在三五天内能跑到什么水平,心里先有个数,然后再逐步加复杂度。这个习惯帮我挡住过很多“为了复杂而复杂”的方案。很多时候,简单模型加合理的特征工程,已经足够达到业务目标,复杂模型只是在增加部署、监控和维护成本。
3. 要素二与要素三:策略定方向,算法定路径
3.1 损失函数:模型“认错”的方式决定它学成什么样
策略中最核心的部分是损失函数。一句话概括:损失函数决定了模型把哪种错误看成“更不可接受”。同样是回归任务,选不同的损失函数,训练出来的模型性格完全不同。
拿房价预测来说,如果用均方误差 MSE,也就是 (L=(y-\hat y)^2),模型会对大误差施加二次方级别的惩罚。样本里如果有一套房子的实际成交价比预测高了 200 万,这个样本的梯度会把模型狠狠往那个方向拽。好处是模型会努力控制大偏差,坏处是它对异常值极其敏感,一个录入错误的数据就足以带偏全局。如果用平均绝对误差 MAE,惩罚是线性的,模型对异常值就淡定了很多,但它的梯度在误差为零处不可导,训练时可能在小幅震荡中收敛。实际工程里还常用 Huber 损失:误差小时按二次惩罚,误差大了切回一次惩罚,相当于在 MSE 的敏感度和 MAE 的稳健性之间取了个中间值。这个选择不是数学技巧,而是业务场景决定的——你的数据里异常点多不多,你对大误差有多不能容忍,直接决定选哪个。
分类任务的损失函数选择更有点讲究。理想情况是最小化 0-1 损失,也就是直接数预测对错的比例,但它全程不可导,梯度下降根本没法用。逻辑回归和神经网络里常用的交叉熵损失,来源是极大似然估计,它把模型输出解释成概率,然后计算真实标签的负对数似然。为什么分类任务不用 MSE?除了概率解释缺失之外,还有一个非常实际的原因:sigmoid 函数在两端饱和区的梯度接近零,如果配合 MSE,误差虽然大但梯度消失,参数更新极其缓慢;交叉熵配合 sigmoid,在预测严重错误时梯度反而更明显,模型学起来效率高得多。所以对分类问题,绝大多数场景下请直接默认交叉熵。
3.2 正则化:给结构风险加一个刹车
经验风险最小化,意思是只盯着训练集上的平均损失去优化,这样做很容易过拟合。所以机器学习里引入了结构风险最小化:在训练损失后面追加一项正则项,目标变成“训练损失小 + 模型复杂度也小”。正则化的本质,就是给模型加税收、踩刹车,不允许它为了拟合训练数据而把参数做得过于极端。
最常见的两个选择是 L2 和 L1 正则。L2 正则惩罚权重的平方和,优化结果倾向于把权重压到接近零但不等于零,也叫岭回归。它的效果是所有特征都被保留,但影响力被均匀压缩。L1 正则惩罚权重的绝对值之和,优化结果会出现很多真正等于零的权重,也叫套索回归,常用于特征选择。很多人不理解为什么 L1 和 L2 有这种差异,几何上看很直观:L1 的约束区域是菱形,顶点落在坐标轴上,最优解更容易出现在坐标轴交点附近,对应的参数就是零;L2 的约束区域是光滑的圆,没有这种“角点”,参数只会变小,但不会直接变成零。
正则化强度 (\lambda) 不是拍脑袋定的,通常用交叉验证在验证集上选。(\lambda) 太小,刹车踩得不过瘾,模型还是过拟合;(\lambda) 太大,所有参数被压得接近于零,预测结果趋近于只取一个常数截距,相当于模型退化成了“不管输入是什么,都预测均值”。就好比一辆车刹车踩太死,直接熄火。神经网络里常用的权重衰减就是 L2 的一种工程实现,Dropout、早停也都能从正则化的角度去理解——它们本质上都是在限制模型对训练数据的记忆能力,提升泛化稳定性。
3.3 优化算法:梯度下降与它绕不开的坑
策略定好了,接下来的问题是算法怎么把最优解找出来。有些模型存在解析解,比如线性回归的正规方程 ( \theta = (X^TX)^{-1}X^Ty ),数据量不大时可以一步算完。但 (X^TX) 的求逆在大规模场景下非常昂贵,大多数模型也没有闭式解,所以工程上几乎全靠迭代优化。
核心方法就是梯度下降:每次计算目标函数对参数的梯度,朝梯度的反方向迈一步,( \theta := \theta - \eta \nabla J(\theta) )。学习率 (\eta) 是最敏感的超参数之一:设大了,参数在最低点附近来回震荡甚至发散;设小了,训练半天纹丝不动。实际训练里一般先用 (10^{-2}) 或 (10^{-3}) 起步,观察损失在最初几个 epoch 有没有明显下降,再决定往哪个方向调。
梯度下降按每次用多少数据来分,有批量、随机、小批量三种。批量梯度下降每次用全量数据算梯度,方向最准但计算量大;随机梯度下降每次只用一个样本更新,快但噪声大,路径在最低点附近晃来晃去;小批量梯度下降一次取几十到几百个样本,是当下训练神经网络的事实标准。处理深度学习任务时,Adam、RMSProp 这类带自适应学习率的优化器通常表现不错,尤其是对调参经验还不丰富的人,默认参数往往就能跑出尚可的结果。但优化器的数学细节不用死磕,关键是要知道:算法只是找路的手段,策略定的目标函数才是评判“好”的裁判。目标的坑,优化器救不回来。
4. 模型评估的起点:切数据、防泄漏、读学习曲线
4.1 数据切分:为什么留出法不够,要上交叉验证
模型评估的第一步不是算指标,而是把数据切对。标准做法是把数据分成三份:训练集用于求解模型参数,验证集用于对比不同模型和调超参数,测试集只允许在最后用一次,模拟真实场景、评估最终泛化能力。比例上常见的是 70% 训练、15% 验证、15% 测试,数据量足够大时可以稍微调低验证比例。
只做一次切分,也就是留出法,问题在于结果受随机性影响太大。运气好时验证集恰好贴近真实分布,分数偏高;运气不好时验证集太难或者太偏,分数偏低,完全没办法判断是模型的问题还是切分的问题。因此小数据和中等数据场景下,我更推荐 K 折交叉验证:把训练集切成 K 份,轮流拿其中 K-1 份训练、1 份验证,最终取 K 次结果的平均值和标准差,常用 5 折或 10 折。分类任务记得用分层抽样,按类别比例保留正负样本的比例;时间序列数据则绝对不能随机 shuffle,必须按时间顺序切分,用前段训练、后段验证,否则会导致“用未来预测历史”的虚假高分。
工程上做交叉验证,用 Python 机器学习库自带的cross_val_score就很方便,它会在内部完成切分和评分:
from sklearn.model_selection import train_test_split, cross_val_score from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.linear_model import Ridge X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42, stratify=y ) pipe = Pipeline([ ("scaler", StandardScaler()), ("ridge", Ridge(alpha=1.0)) ]) scores = cross_val_score(pipe, X_train, y_train, cv=5, scoring="r2") print(scores.mean(), scores.std())这里的 Pipeline 设计有个隐藏的价值:标准化只在每一折的训练部分拟合,再应用到验证部分,天然规避了数据泄漏。
4.2 数据泄漏:评分虚高最常见、也最隐蔽的原因
做评估时遇到“分数高到不可思议”,我的第一反应永远是查数据泄漏,而不是开心庆祝。数据泄漏指的是模型在训练时接触到了真实预测场景里不可能拿到、或者不该提前知道的信息,导致验证和测试分数严重虚高,上线后立刻打回原形。
泄漏最常见的来源有三个。第一个是预处理泄漏。很多人习惯先对全量数据做标准化,再切训练集测试集,于是全局均值、方差这些统计量是通过整份数据算出来的,其中已经包含了测试集的信息。正确做法是只在训练集上 fit 预处理,再用训练集的统计量去 transform 验证集和测试集。上面代码里把 StandardScaler 放进 Pipeline,就是为了让它在交叉验证的每个折内部重新拟合,从机制上避免这种泄漏。
第二个是目标泄漏。特征里混进了与结局直接相关、但在真实预测时拿不到的信息。房价预测里如果用“成交后买家的评价”做特征,那你未来换一套新房源时根本没有这个评价可用,这就是目标泄漏。做特征时要反复问自己:预测那一刻,这个信息真的已经存在并且能拿到吗?
第三个是重复数据。同一个用户、同一条记录在训练集和测试集里各出现一次,模型等于已经见过“答案”了。去重操作在切分之前就要完成。排查泄漏有个简单实用的小技巧:故意喂一个明显无关、但和标签强相关的伪造特征,如果验证分数立刻暴涨,说明你的评估链路上确实存在不该有的信息通道。
4.3 学习曲线:一眼看出模型是欠拟合还是过拟合
学习曲线是诊断模型状态最直观的工具,横轴是训练样本数量,纵轴是误差,通常画两条线:训练集误差和验证集误差。
看曲线时先看两条线的绝对位置和相对差距。如果训练误差很高,验证误差也很高,而且两条线几乎贴在一起,说明模型处于欠拟合状态,容量不够,记不住训练数据里的规律。这时要做的不是收集更多数据,而是增加模型复杂度、增加特征、减少正则化。反过来说,如果训练误差降到了很低,验证误差却明显高出一截,两条线中间有一个宽宽的“鸿沟”,就是过拟合,模型把训练数据的噪声也背了下来。此时加正则化、降低模型复杂度、增加数据量、早停,都是正确方向。还有一种情况是两条线都很高但差距很大,那不一定是模型问题,很可能又回到数据泄漏或者训练集和验证集分布不一致上面了。
学习曲线还能帮你回答一个特别现实的问题:加数据到底有没有用?如果随着训练样本量增加,验证误差曲线还在明显下降,说明数据规模没喂够,继续加数据会有增益;如果验证误差已经走平,加数据的边际收益就很低了,不如把精力花在换模型、调正则化上。这个判断在节省算力和时间上价值很大,因为 GPU 训练一次的成本越来越高,盲目加数据就是烧钱。
5. 分类与回归的评估指标:尺子用错,结论全偏
5.1 混淆矩阵:分类评估的地基
分类评估的所有指标,几乎都可以从混淆矩阵这一张表推导出来。二分类结果有四类:真正例 TP、假正例 FP、假负例 FN、真负例 TN。基于这四个数,可以得到准确率、精确率、召回率、F1 等指标。准确率是预测对的样本占总数的比例,精确率是预测为“正”的样本中有多少是真的正,召回率是真正的正样本中有多少被成功找了出来。
精确率和召回率天然存在一种取舍关系:同一个模型,把判断阈值调高,也就是说足够确信才输出正类,精确率会上升,但大量可疑的正样本会被漏掉,召回率下降;把阈值调低,召回率上升,但误报增多,精确率下降。F1 是两者的调和平均,当你不希望偏向任何一方、希望综合衡量时可以用它。实际应用中,这个取舍一定要跟着业务走。内容推荐场景,推荐系统把不相关的内容推给用户,用户会流失,所以宁可漏掉一些也不愿意误报,精确率优先;反欺诈场景,漏掉一笔欺诈交易的损失远大于误报一笔正常交易,所以更看重召回率。评估一个模型的最终指标,应该由业务成本函数决定,而不是谁的代码写起来最顺手。为了规范化FilePath,我要保持输出为纯文本接口响应。
5.2 类别不平衡时,别让准确率误导你
类别不平衡问题在现实数据里极其常见:欺诈交易占比通常不到 1%,罕见病阳性率可能只有 0.1%,一个“永远预测正常”的模型可以在这种数据上拿到 99% 的准确率,但它实际什么都没学到。这个例子不是极端假设,而是大量业务线上真实上演过的“假繁荣”。
所以遇到不平衡分类时,我只看精确率、召回率、F1 和 PR 曲线。PR 曲线的横轴是召回率,纵轴是精确率,它完全聚焦在正类上,曲线下面积称为 AP,越高表示模型在正类上的综合排序能力越好。ROC 曲线则是横轴为假正例率、纵轴为正例率,AUC 表达的含义更直白:随机抽一个正样本和一个负样本,模型把正样本排在前面的概率。AUC 的优点是阈值无关、整体排序评估稳定,很多论文里都用它。但它在正样本极度稀少时容易显得过于乐观,因为负样本基数大,假正例率被稀释了。举个直观的例子,一万封邮件里只有十封垃圾邮件,哪怕模型把所有正常邮件全预测错一点点,FPR 仍然很低,AUC 看着还不错,但你实际关注的是那十封垃圾邮件有没有被抓出来。所以,极度不平衡且更关心正类识别的场景,建议以 PR 曲线和 F1 为主,AUC 作为辅助参考。
5.3 回归评估:MSE、MAE 与 R² 怎么选
回归任务的评估指标同样需要挑。MSE 的数学性质极好,处处可导,适合做优化目标,但它的量纲是平方级别,解释起来不直观,而且对异常值的惩罚极重,一个极端误差就能把整体分数拉爆。RMSE 是 MSE 开根号,量纲回到原变量,日常汇报更常用。MAE 是误差的绝对值平均,解释起来非常直观,对异常值稳健,但作为优化目标时梯度在零点附近不光滑。
实际使用我的建议是至少同时看两个角度:一个对异常值敏感的,一个对异常值稳健的。比如房价预测模型,RMSE 告诉你平均而言预测会偏差几万元,MAE 告诉你中位数水平上偏差多少;两个指标差得很远,基本可以断定数据里有较大的离群点或预测存在系统性偏向。(R^2) 是另一个常见指标,它表示模型相对“直接用均值预测”到底提升了多少,值的区间正常在 0 到 1 之间,但测试集上完全可能为负,说明模型的预测比无脑用均值还差。(R^2) 不等于越接近 1 模型就一定好,它受极端值影响很大,而且对数据分布变化敏感。回归评估中没有万能指标,多指标交叉验证才是常态。
6. 从评估结果到模型改进:偏差-方差权衡与调参路线
6.1 误差的三分法:偏差、方差与不可约噪声
为什么调参看起来像一门玄学?因为很多人没有理解预测误差到底由哪些部分构成。统计学习里有一个经典分解:模型在新样本上的期望误差,可以拆成偏差的平方、方差,以及数据本身的不可约噪声三项。
偏差衡量的是模型预测的平均值与真实值的差距。模型太简单,比如用线性模型去拟合一个强非线性关系,无论换多少训练数据,平均预测都偏离真实,这就是高偏差,对应欠拟合。方差衡量的是模型预测在不同训练集之间的波动程度。模型太复杂,换个训练集结果就差很远,这就是高方差,对应过拟合。用打靶来理解最直观:偏差决定你瞄准的位置是不是靶心,方差决定你击中的点有多分散。一个模型可能打得又散又偏,也可能都打在靶心附近,但最优目标是又准又集中。
理解了这一分解,很多策略就有了理论依据。Bagging 类方法,比如随机森林,通过多棵树的平均来降低方差,所以它对“高方差”问题最有效。Boosting 类方法,比如梯度提升树,每一步都在拟合前一步的残差,本质是在持续降低偏差,所以它对“欠拟合”问题最有效。这也是为什么实际比赛里 XGBoost 和随机森林经常搭配使用,它们俩解决的误差成分不一样。
6.2 调参主线:从欠拟合走向过拟合再走回来
调参不是漫无目的地拿验证集分数去试网格,而是有章法的两步走。第一步,确保训练误差能降到可接受的水平,这一步只负责解决欠拟合;第二步,在不明显牺牲训练误差的前提下,设法缩小训练误差和验证误差之间的差距,这一步才用来解决过拟合。
拿决策树举例。如果max_depth=3时训练误差和验证误差都很高,说明模型容量不够,先把深度调到 15,训练误差会明显下降,但验证误差很可能反而上升,因为树过于复杂、开始过拟合。然后再把深度慢慢往回退,比如试试 5、6、7、8,看到验证误差先降后升的拐点,就找到了当前数据下的合理复杂度。神经网络也是同样的逻辑:先保证训练损失能下降,如果不能,就调学习率、优化器,或者增加网络容量;训练损失能降了,再看验证损失,如果验证损失不再下降甚至回升,就加正则化、Dropout、早停,或者收集更多数据。需要注意的是,深度学习里面早停不是可选项,而是必备操作。训练过程中持续监控验证损失,在验证损失连续若干个 epoch 不再改善时停止训练,能够在不过分复杂的前提下保住最佳模型。
这里有一张我长期放在手边的诊断表,遇到问题先对号入座,再动手调:
| 现象 | 状态 | 优先动作 |
|---|---|---|
| 训练误差高,验证误差高,差距小 | 欠拟合 | 增加模型复杂度、加特征、减少正则化、训练更久 |
| 训练误差低,验证误差高,差距大 | 过拟合 | 加正则化、增加数据、降低模型复杂度、早停 |
| 训练误差低,验证误差也低但线上崩 | 数据泄漏或分布漂移 | 排查预处理/目标/重复泄漏,检查数据分布一致性 |
6.3 三个实战习惯:先小样实验、先简单模型、盯验证集
最后分享几个我自己踩过多次坑后养成的实战习惯,每一个都帮我省过大量无效时间。
第一,先小样实验。拿到一份新数据集,不要直接全量跑,先在几千条数据上把特征、模型、评估链路全部跑通,确认没有报错、没有泄漏、指标定义正确,再放开到全量数据。全量数据一次训练可能几小时,链路没跑通就直接上等于烧钱。第二,先设一个 naive baseline。分类任务让模型预测多数类,回归任务直接让模型预测均值,先算出这个底线分数。任何模型都必须明显超过这个底线才值得继续投入。很多时候你会发现,一个认真调过的逻辑回归已经接近复杂模型的分数,那个复杂模型就不必上了。第三,每次实验只改一个变量,并且留实验记录。同时改了学习率、网络深度、数据增强方式和损失函数,分数涨了,你根本不知道是哪个操作起的作用。固定随机种子、保持单一变量,一周后的你绝对会感谢现在的克制。
评估指标和实验流程这些细节,看起来没有模型结构那么高大上,但它们才是决定一个机器学习项目能不能落地、落地后会不会翻车的真正关键。我在实际项目中,花在搭建可信评估链路上的时间经常比调模型还多,因为只要评估环节是漏的,后面一切“效果提升”都建立在流沙上。先把尺子校准了,再谈怎么把模型调得更好,这大概是最朴素也最重要的一条经验。