☰
机器学习模型评估指南:用Scikit-learn避开过拟合陷阱
2026/10/9 11:11:40 网站建设 项目流程

模型训练完了,loss 降得很低,测试集准确率 98%,是不是就可以开开心心上线了?我在刚开始用 Scikit-learn 做机器学习项目的时候就这么想,结果被一次 A/B 测试狠狠打脸:线上效果远不如离线指标那么漂亮。后来才明白,评估模型这件事,不是跑几个函数、打印几个分数那么简单,它是一整套围绕“泛化能力”展开的工程流程。这篇文章,我就用 Scikit-learn 这个我日常使用最多的机器学习库,把机器学习模型评估从头到尾捋一遍:从数据划分、分类指标、回归指标,到交叉验证、学习曲线,再到我真实踩过的坑。如果你正在做机器学习期末复习,或者刚跑通一个建模流程但总觉得评估环节有点虚,这篇内容应该能帮你把知识点串起来。

1. 为什么说模型评估是机器学习项目的“照妖镜”

1.1 没有评估,模型就是个黑盒

很多初学者的第一个模型都是这样出来的:把数据丢进fit(),再用同一份数据算一下准确率,发现 0.95,觉得自己已经掌握了机器学习。实际上,这一步几乎不能说明任何问题。模型完全可能把训练样本的答案背下来,换一批新数据就原形毕露。这种现象就是过拟合,也是机器学习里最需要警惕的问题。

我后来复盘自己被“打脸”的那个项目,原因很简单:模型在训练集上表现很好,但到了线上,数据的分布、噪声水平都和训练时有差异,模型就撑不住了。所以评估的本质不是给你一个好看的分数,而是尽可能诚实地回答一个问题:模型在没见过的数据上,到底行不行。机器学习应用流程里,评估也不是最后一步,它更像是迭代反馈的起点,每一步特征工程、调参、算法选择,都要靠评估结果来驱动。

1.2 不看业务场景谈指标,等于耍流氓

评估指标的选取,必须跟业务目标绑定。同样是分类问题,推荐系统里更关心“推给用户的十件商品里有没有用户真正点的那件”,这时候精确率很重要;医疗筛查场景里,漏掉一个患者比多叫一个人复查更严重,这时候召回率才是核心指标。准确率只是最简单的基础指标,它默认所有错误的代价相同,这在大多数真实场景下是不成立的。

Scikit-learn 的好处在于,它把各种评估指标都封装成了函数,accuracy_score、precision_score、recall_score、f1_score、roc_auc_score,一行就能算出来。但麻烦也在这里:工具越顺手,越容易让人忘记先想清楚“我到底该看哪个指标”。我的习惯是,在写建模代码之前,先把业务指标写在一张便签上贴到屏幕旁边,避免训练到一半被漂亮的分数字遮住眼睛。

1.3 Scikit-learn 在评估生态里的位置

你可能觉得评估嘛,用 NumPy 自己写也不难:把预测值和真实值一减,再求个平均。但真正做项目时你会发现,自己实现容易遗漏细节,比如多分类的average策略、类别不平衡时的样本权重、zero_division异常处理。Scikit-learn 的另一个优势是 API 设计一致:数据划分、交叉验证、评分函数、Pipeline 可以无缝组合,还省去了大量重复代码。

而且它和 Pandas、NumPy、Matplotlib 的配合非常自然,评估结果可以直接放到 DataFrame 里做对比,画残差图、学习曲线也方便。对教学和企业原型来说,这是目前最顺手的一套工具链。当然,评估的底层逻辑比工具本身更重要,这也是本文后面几节要重点展开的。

2. 数据划分:评估的第一道工序

2.1 别一上来就 train_test_split,先想清楚三件事

很多机器学习的课程,比如吴恩达的《机器学习》,开篇做实验设计时就会反复强调:数据不能只用一份,要分成训练、验证、测试。我当时不以为然,觉得不就是切个数据集吗?后来才发现,切分方式直接决定评估结果是否可信。

用 Scikit-learn 切数据很简单,但有三件事必须提前想清楚。第一,是否要保证类别比例一致,这时候要用stratify参数;第二,是否需要固定随机种子,否则每次跑出来的结果都不一样,没法复盘;第三,数据是否有时间顺序,如果乱切,等于让模型偷看未来。基本用法是:

from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, stratify=y, random_state=42, shuffle=True )

stratify=y的作用是让切分后的训练集和测试集里,各类别所占比例和原始数据尽量一致。如果你的数据里 A 类占 80%、B 类占 20%,不设置这个参数,运气差的时候测试集里可能 B 类只剩一点点,评估结果方差就很大。random_state则是让整个过程可复现,我一般固定 42,虽然没什么深意,但团队协作时方便大家跑出一模一样的结果。

2.2 样本少、类别不平衡时,划分要更讲究

stratify也不是万能的。如果某个类别总共只有十几个样本,就算用分层抽样,测试集里也可能只分到两三个,随便猜错一个,指标波动就非常大。这时候我一般会考虑两种办法:一种是做多轮随机划分,把多次评估的均值作为最终参考;另一种是使用交叉验证,而不是单次切分,这个问题在后面第五部分会详细说。

还有一种情况是类别分布极不平衡,比如风控场景里坏样本可能只有 1%。直接按比例切分,测试集里的正样本会非常少,算出来的精确率和召回率都不稳定。我的做法是先检查每个类别的最小样本数,如果某个类的数量都少于交叉验证的折数,就要考虑用StratifiedKFold并配合重复多次的方式,或者干脆在建模前就针对小类做专门的处理。

2.3 时间序列数据不能随机切

时间序列是数据划分里最容易翻车的一类。金融交易、销量预测、服务器监控数据,它们天然有先后顺序,如果像普通数据那样随机打乱再切分,模型就会在训练阶段看到未来的数据,等于开卷考试,评估分数自然虚高。Scikit-learn 提供了TimeSeriesSplit,它保证训练集始终在测试集之前。

from sklearn.model_selection import TimeSeriesSplit tscv = TimeSeriesSplit(n_splits=5) for train_idx, val_idx in tscv.split(X): X_train, X_val = X[train_idx], X[val_idx] y_train, y_val = y[train_idx], y[val_idx] # 每一折里,训练集都是过去,验证集都是未来

我第一次用的时候还踩过一个坑:TimeSeriesSplit是按顺序切,但真正常见的业务里存在“同一天的数据内部也有相关性”,这时候简单按行顺序切也不完全合理。更稳妥的做法是按时间戳分组聚合后切分,但至少你得先意识到,随机切分对时间序列不适用。

2.4 划分时的信息泄漏,是老手也容易犯的低级错误

数据划分并不只是把数据切两半,关键问题是“预处理操作”要在哪一步做。很多人习惯先用全量数据做标准化,再切分,这其实是典型的信息泄漏。因为你已经让模型看到了测试集的均值和方差,测试集就不再是“没见过的新数据”了。正确做法是先切分,再只用训练集的统计量去 transform 测试集。

手动写起来有点啰嗦,所以我在项目里几乎都是用Pipeline把预处理和模型放在一起,再对整个 Pipeline 交叉验证。这样能保证每一个 CV 折里面,预处理只看到对应训练折的信息,不容易出纰漏。

3. 分类模型评估指标与 Scikit-learn 实现

3.1 准确率为什么最容易让人误判

准确率的公式是:预测正确的样本数除以总样本数。它直观、好算,但也是分类指标里最容易被误用的。假设一个风控系统要识别 1% 的欺诈交易,你直接把所有交易都判成正常,准确率也有 99%。看起来很强,实际上这个模型毫无价值。

所以做分类评估,第一件事就是不要只算准确率。Scikit-learn 里的classification_report可以一次输出多个基础指标,看起来非常方便,但你得知道每个指标的含义再去看结果:

from sklearn.metrics import classification_report, accuracy_score print(accuracy_score(y_true, y_pred)) print(classification_report(y_true, y_pred))

classification_report会按类别输出精确率、召回率、F1,并且给出一行加权平均。初学者最容易犯的错,是盯着一行“macro avg”就下结论,忘了看每个类别的样本量。如果某个类别样本特别少,单个类别的指标波动会很大,宏观平均也会被带偏。

3.2 混淆矩阵:不是花架子,是定位问题的地图

分类指标一大堆,但很多问题最终都要回到混淆矩阵里去看。混淆矩阵把预测结果分成了四类:真正例 TP、假正例 FP、假负例 FN、真负例 TN。只看准确率,你会觉得模型不错,但看混淆矩阵可能发现,问题都出在某一个类别上。

Scikit-learn 的confusion_matrix返回矩阵的行代表真实标签,列代表预测标签。如果你只给两个类别,默认labels是排序后的 [0, 1],那么cm[0,0]是 TN,cm[0,1]是 FP,cm[1,0]是 FN,cm[1,1]是 TP。很多文档不会提醒这一句,我自己就曾经把行和列看反,差点得出完全相反的结论。

from sklearn.metrics import confusion_matrix cm = confusion_matrix(y_true, y_pred) print(cm)

光看数字不够直观,还可以配合可视化,把混淆矩阵输出成热力图。哪个类别被错判成哪个类别,一眼就能看出来,这在多分类问题里特别有用。

3.3 精确率和召回率的“矛盾”怎么平衡

精确率(Precision)回答的是“你预测为正类的样本里,有多少是真的正类”;召回率(Recall)回答的是“真正的正类里,你找到了多少”。这两个指标天然存在矛盾:想把召回率拉高,通常会预测更多的正类,于是误报变多,精确率下降;想提高精确率,就需要更保守,又会漏掉一些正类。

F1-score 是精确率和召回率的调和平均,它能综合反映两者。调和平均对“某一项特别低”的情况非常敏感,所以模型如果只偏重一边,F1 不会好看。但这个指标也不是万能的,业务到底是更怕“假正例”还是“假负例”,你得自己判断。举个生活化的例子:邮箱垃圾邮件过滤,把正常邮件误判成垃圾邮件,用户可能直接卸载 App,这时更看重精确率;贷款违约预测,漏掉一个老赖,银行损失的是真金白银,这时更看重召回率。

3.4 AUC-ROC:排序能力的体检报告

ROC 曲线和 AUC 是分类模型评估里出现频率极高的概念。很多分类模型输出的并不是标签,而是一个概率值,默认阈值是 0.5,大于 0.5 判成正类。但 0.5 不一定是业务上的最优阈值,AUC 的意义在于,它可以脱离阈值来评估模型的排序能力:模型给正类打高分、给负类打低分的能力有多强。

用 Scikit-learn 计算时有个细节要特别注意,roc_curve和roc_auc_score接受的不是概率还是决策分数?有的模型有predict_proba,取正类的概率;有的只有decision_function,比如 LinearSVC。顺序也很关键,多分类时二分类的 ROC,默认取的是第二个类别(也就是 label 为 1 的列)的概率,用错标签顺序,AUC 结果就很诡异。

from sklearn.metrics import roc_curve, auc y_proba = model.predict_proba(X_test)[:, 1] fpr, tpr, thresholds = roc_curve(y_test, y_proba) roc_auc = auc(fpr, tpr)

得到 ROC 曲线后,还可以顺手做个阈值选择。画出每个阈值对应的精确率和召回率,或者直接算一下业务成本,找到最适合当前场景的阈值。这一步经常被忽略,但它往往比换模型更能提升线上效果。

3.5 多分类和类别不平衡的指标设置

多分类问题里,指标会自动多出很多种计算方式。average='macro'表示每个类别各自算分数后取简单平均,average='weighted'会按每个类别样本量做加权平均,average='micro'是把所有类别的 TP、FP、FN 汇总后再算。几种方式没有绝对好坏,但反映的问题不同。

比如f1_score用macro时,每个类别的权重相同,小类的表现会被放大;用weighted时,大类贡献更多,业务上更贴近“总体表现”。我通常在报告里同时打印macro和weighted,如果两者差距很大,说明类别间表现不均衡,那光看总分意义不大,必须回到混淆矩阵里定位。类别不平衡时,还可以关注 PR 曲线下的面积average_precision_score,它在正类很少时比 ROC-AUC 更敏感。

4. 回归模型的评估指标与 Scikit-learn 实现

4.1 四个核心指标:MAE、MSE、RMSE、R²

回归问题预测的是连续值,评估逻辑和分类完全不一样。最常用的四个指标是 MAE、MSE、RMSE 和 R²。MAE 是绝对误差的平均值,MSE 是误差平方的平均值,RMSE 是 MSE 开根号,R² 是决定系数。它们的计算方式都很简单,Scikit-learn 里也是一行代码的事。

from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score import numpy as np mae = mean_absolute_error(y_true, y_pred) mse = mean_squared_error(y_true, y_pred) rmse = np.sqrt(mse) r2 = r2_score(y_true, y_pred)

MSE 之所以被广泛使用,是因为它把每个误差平方之后,大误差对总损失的贡献会被放大。这既是优点也是缺点:如果你希望模型更在意那些“离群的大误差”,MSE 是合适的;但如果你不想让个别异常点过分主导评估结果,MAE 会更稳。RMSE 的好处是和原始单位一致,解释起来更直观。

4.2 R² 不要盲目使用

R² 的解释是模型解释了目标变量方差的百分比,但它并不像字面看起来那么绝对。一个很常见的误读是:R² 等于 0.8,就代表模型预测“80% 正确”。实际上,R² 等于 0.8 只是说模型比“预测所有样本都为均值”这个基线好了一些,至于是否“好到能上线”,取决于业务误差容忍度。

更麻烦的是,R² 在某些场景下可能非常低甚至为负。比如预测房价,如果房价受政策、地段等外部因素影响很大,模型只靠已有特征能解释的部分本来就不多,R² 低不代表特征工程白做。我习惯把 R² 和 MAE/RMSE 一起看:R² 看整体解释力,MAE/RMSE 看实际误差大小,二者合在一起,才不至于被单一指标误导。

4.3 残差分析:指标之外的诊断

回归评估里,我最看重的其实不是那几个数字,而是残差图。残差是真实值减预测值的差。如果残差随机散布在 0 附近,说明模型已经把可解释的规律学得比较干净;如果残差图出现明显的漏斗形状,比如预测值越大,误差越大,说明模型在某个范围内系统性失效。

import matplotlib.pyplot as plt residuals = y_true - y_pred plt.scatter(y_pred, residuals, alpha=0.5) plt.axhline(0, color='red', linestyle='--') plt.xlabel('Predicted Value') plt.ylabel('Residuals') plt.show()

我做过一个销量预测项目,指标分数看起来还不错,但残差图一画出来就发现,模型在促销日当天的预测误差特别大。后来单独加上促销日特征,才把残差里的规律去掉。所以说,指标是总结,残差图是细节,两个都不该少。

5. 交叉验证:让评估结果更可信

5.1 为什么单个测试集不够

用train_test_split切出来的测试集只有一个,它的好坏取决于切分时的运气。如果这一份测试集恰巧比较简单,模型评估分数就会偏高;如果恰好包含了很多难样本,分数就偏低。对稳定性要求高的项目来说,这种单次评估太脆弱了。

交叉验证的思路是多切几刀:把数据分成 K 份,每次拿其中一份当验证集,剩下 K-1 份当训练集,轮一遍后取指标的平均值。这样每个样本都有机会当验证数据,评估结果对数据划分的依赖就小了很多。Scikit-learn 里的cross_val_score是最快的入门方式:

from sklearn.model_selection import cross_val_score scores = cross_val_score(model, X, y, cv=5, scoring='accuracy') print(scores.mean(), scores.std())

cv=5就是五折交叉验证,scoring='accuracy'指定评分指标。这里的scores是每一折的分数,不要把均值当作唯一的答案,标准差的含义也很重要。标准差太大,说明模型在不同子集上表现波动明显,背后可能是数据分布不均匀或模型不稳定。

5.2 KFold 与 StratifiedKFold 怎么选

KFold是简单的 K 折,StratifiedKFold是分层 K 折,后者在每一折里尽量保持类别比例和原始数据一致。分类问题里我几乎不用普通KFold,除非类别极其均衡。StratifiedKFold的写法是:

from sklearn.model_selection import StratifiedKFold, cross_validate from sklearn.ensemble import RandomForestClassifier cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) model = RandomForestClassifier(random_state=42) cv_results = cross_validate( model, X, y, cv=cv, scoring={'accuracy': 'accuracy', 'recall': 'recall'}, return_train_score=True )

这里用cross_validate是因为它能同时算多个指标,还能选择是否返回训练集分数。对比训练集和验证集的分数,是判断过拟合的重要手段:如果训练分数很高、验证分数明显更低,说明模型过拟合了;如果两个分数都低,可能是欠拟合。

5.3 分组数据要用 GroupKFold

有些数据天然不是独立的,比如同一个用户产生了多条行为记录,同一个患者有多次复诊记录。如果简单随机切分,同一个用户的数据可能一部分在训练集、一部分在验证集,模型等于已经见过这个“人”的答案,评估结果会虚高。GroupKFold能做到按组切分,让同一组的样本只出现在同一折里。

这类场景我一开始没注意,后来做用户流失预测时发现验证集分数虚高,排查了好一阵子才发现是分组泄漏。Scikit-learn 里还有GroupShuffleSplit,适合需要更高自由度的情况。判断标准很简单:如果样本存在明显的“组”概念,交叉验证就必须用分组版。

5.4 嵌套交叉验证:调参后的评估不要自己夸自己

交叉验证还有一个进阶用法,叫嵌套交叉验证,专门解决“我用交叉验证调参,然后又把交叉验证分数当作模型最终评估”这种循环论证问题。GridSearchCV 会在内部用交叉验证去找最好参数,如果你再把选出的模型放到同一个交叉验证上评估,结果天然就是偏乐观的,因为你已经看到了验证集的答案。

嵌套交叉验证的思路是:外层循环分割数据,内层循环做调参选模型,外层再用没见过的数据评估。代码看起来有点绕,但逻辑很清晰:

from sklearn.model_selection import GridSearchCV, KFold, cross_val_score outer_cv = KFold(n_splits=5, shuffle=True, random_state=42) inner_cv = KFold(n_splits=3, shuffle=True, random_state=42) clf = GridSearchCV(RandomForestClassifier(), param_grid, cv=inner_cv) scores = cross_val_score(clf, X, y, cv=outer_cv, scoring='roc_auc')

这个嵌套评估得到的分数,才更接近模型未来上线后的真实表现。代价是计算量成倍增加,但我的经验是,宁可多等一会儿,也不要被虚高的调参结果骗了。

6. 学习曲线与模型诊断:评估之外的价值

6.1 学习曲线:欠拟合还是数据不够

交叉验证只能告诉你“当前这个模型在这个数据上表现如何”,但它不告诉你“下一步该怎么改”。这时候学习曲线能派上用场。学习曲线画的是:随着训练样本数量增加,训练集分数和验证集分数的变化趋势。

from sklearn.model_selection import learning_curve import numpy as np train_sizes, train_scores, test_scores = learning_curve( model, X, y, cv=5, train_sizes=np.linspace(0.1, 1.0, 10), scoring='neg_mean_squared_error' )

如果训练分数和验证分数都很低,而且随着样本增加没有明显变好,通常意味着高偏差,也就是模型太简单,学不动规律。这是增加数据也救不了的,需要换更复杂的模型或做更好的特征。如果训练分数很高、验证分数远低于训练分数,说明模型在高方差状态,更常见的原因是过拟合或者数据量本身就太少。

6.2 验证曲线:调参是在找“甜点区”

验证曲线针对的是单个超参数:固定其他条件,让这个超参数从小到大变化,看训练和验证分数怎么变化。比如随机森林的max_depth,过小欠拟合,过大可能过拟合,验证曲线能帮你找到“甜点区”。

from sklearn.model_selection import validation_curve train_scores, test_scores = validation_curve( model, X, y, param_name='max_depth', param_range=range(1, 15), cv=5, scoring='accuracy' )

画出来的曲线通常是:训练分数随参数变大单调上升,验证分数先升后降。验证分数拐点之前的区域是模型能力不足,拐点之后的区域就是过拟合。我在调参时会顺手把训练分数和验证分数都打出来,只看验证分数很难判断一个参数是“有效”还是“过拟合了”。

6.3 噪声数据对评估结果的干扰

机器学习里有个常被讨论的话题:噪声数据到底会怎么影响评估。特征噪声会扰动输入,让模型更难抓到规律;标签噪声更危险,它直接把答案弄错了,模型就算学得再好,分数也会被稀释。交叉验证里如果某一折恰好包含了较多噪声样本,那一折的分数就会明显掉下来,这也解释了为什么不能看单次交叉验证分数就下结论。

我的处理经验是,先做一遍简单清洗,识别明显的异常值和明显标错的标签,但不要过度清洗,否则评估出的“好结果”在真实数据上还原不出来。另一个办法是多次运行RepeatedStratifiedKFold,对多轮交叉验证结果取平均,这样能够把噪声引起的随机波动磨平一部分。噪声是真实世界的一部分,评估的目的不是假装它不存在,而是知道模型在这种噪声水平下到底还有多稳。

6.4 横评多个模型时如何控制评估变量

做模型选型时,大部分人都会同时跑好几个算法:逻辑回归、随机森林、XGBoost、LightGBM,最后比较哪个分数高。但跨模型对比有个很容易被忽略的前提:它们的评估方式必须完全相同。同一个数据集,同样用五折交叉验证,同一个评分指标,这样比较才有意义。

我会把评估逻辑封装成一个函数,统一传X, y, cv, scoring,所有模型走同一套流程。这样省了不少重复代码,也能避免不小心给某个模型换了数据划分方式。还有一个小技巧:横评结果不要只看平均分,把每一折的分数都存到 DataFrame 里,细看哪个模型在哪个折表现差,这往往能暴露出比总分差异更重要的问题。

7. 常见问题排查与避坑实录

7.1 评估结果异常?先按这张表排查

我自己把评估环节遇到的典型问题整理成了一张速查表,遇到异常先对号入座,比反复调参效率高得多。

现象可能原因处理办法
训练集分数很高,测试/验证分数低过拟合、数据泄漏检查预处理是否泄漏,尝试简化模型或加强正则化
分类准确率很高,但业务不可用类别不平衡,准确率掩盖问题改用精确率、召回率、PR-AUC
每次运行结果差异巨大没有固定随机种子设置random_state,或使用多次重复的交叉验证
测试时没有predict_proba只有决策分数模型本身不输出概率用decision_function或改用概率校准模型
交叉验证分数高于单次切分很多分组泄漏或预处理泄漏检查是否有同一组样本跨折,检查 Pipeline
回归的 MAE 很小,但 R² 接近 0数据本身噪声大或特征解释力弱看残差图,确认是否存在系统性缺失特征

这张表解决不了所有问题,但能帮你把排查范围缩得很小。很多时候模型评估异常不是代码 bug,而是评估方式本身和任务目标不匹配。

7.2 我最常犯的三个评估错误

第一个错误是在数据划分之前做数据清洗时不小心用了全量数据的统计量。比如用全量数据算均值填充缺失值,再切分,这会让测试折的信息悄悄进入训练过程。后来我在项目里强制用Pipeline包住所有预处理,从源头解决问题。

第二个错误是拿GridSearchCV.best_score_当模型上线预估。best_score_是调参过程中最优参数下的交叉验证分,它已经看过验证折的答案,天然偏乐观。正确做法是把选出来的最优模型拿去重新做一次交叉验证或放到留出的独立测试集上评估,也就是嵌套交叉验证的思路。

第三个错误是只看classification_report的总分,没有逐类抽查。后来我把输出改成了“按样本量排序的各类别指标”,优先检查样本量最少的几个类,因为它们最容易在总分中被掩盖。

7.3 一个可以抄的评估模板

最后分享一个我一直在用的简化版评估流程。每次拿到一个新任务,我按这个顺序来做:先切出独立的测试集并冻结它,再在训练集上用StratifiedKFold或TimeSeriesSplit做交叉验证;每次迭代只看验证集平均数,等到最终确认模型后,只在冻结的测试集上测一次;记录所有随机种子、评分函数和预处理管道;最后用学习曲线和残差图做诊断,看还有没有明显的结构性问题。

# 伪代码,包含核心步骤 from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler pipeline = Pipeline([ ('scaler', StandardScaler()), ('model', RandomForestClassifier(random_state=42)) ]) cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) results = cross_validate(pipeline, X_train, y_train, cv=cv, scoring=['accuracy', 'f1'], return_train_score=True)

这个模板并不复杂,但它保证了评估结果的稳定性和可复现性。对我这种记性不太好的人来说,把评估流程固定下来,比临时想一个方案靠谱得多。

我做机器学习评估这一年多,最大的体会是:评估不是建模流程的终点,而是一面镜子,它会不断照出你对业务、对数据、对模型的误解。我现在每次跑完模型,都会强制自己回答四个问题:数据是怎么切的?用的哪几个指标?为什么选这些指标?如果把数据重新切一次,分数会稳定吗?这四个问题写下来,比调一堆参数有用得多。也希望读完这篇文章的你,下次评估模型时能少踩几个我踩过的坑。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询