本节你会学到
- 说清楚「模型评估与交叉验证:不要只相信一次划分」解决的核心问题
- 知道它在「传统机器学习基础(21~34)」中的位置
- 把 GridSearchCV、分类与回归、过拟合 这些关键词联系起来
理解训练集、验证集、测试集、交叉验证、平均分和波动,避免用一次随机划分误判模型能力。
学习路线:传统机器学习基础(21~34) · 第 34 课
补齐文本分类项目背后的数据处理、算法、评估和模型选择知识。
学完本阶段你能做到:拿到一份结构化表格数据,独立完成清洗、特征工程、建模、评估、模型选择和保存,并用规范流程比较多个算法。
推荐读法:建议系统读。做项目时遇到数据和模型选择问题,也可以按需回查。
查看完整阶段 · 14 篇先看目标,再带着问题读正文。读完后用练习确认自己真的理解了。
单一指标会掩盖类别不平衡、业务代价和错误分布。评估要结合任务目标、混淆矩阵和具体错误样本。
当类别不平衡或不同错误代价差异很大时,准确率可能很高但模型仍然没解决关键问题。
前面我们已经学了线性回归、逻辑回归、KNN、决策树和随机森林。到这里,很多人会自然地问:模型训练出来以后,分数到底能不能信?
答案是:不能只相信一次划分、一次训练、一个分数。
假设你把数据按 8:2 切成训练集和测试集,模型在测试集上准确率是 0.86。这个数字看起来不错,但它可能受很多因素影响:
所以模型评估的目标不是只拿到一个漂亮数字,而是判断:这个模型在没见过的数据上是否稳定可靠。
三类数据要分工清楚。
| 数据 | 作用 | 能不能反复看 |
|---|---|---|
| 训练集 | 让模型学习参数 | 可以 |
| 验证集 | 选模型、调参数、比较方案 | 可以,但要有节制 |
| 测试集 | 最后一次客观考试 | 尽量只用一次 |
训练集像课堂练习,验证集像模拟考试,测试集像正式考试。你可以用模拟考试决定怎么复习,但不能一边正式考试一边改答案。
交叉验证的核心是:把数据分成多份,每一份轮流当验证集。
以 5 折交叉验证为例:
第 1 次:第 1 折做验证,其余 4 折训练
第 2 次:第 2 折做验证,其余 4 折训练
第 3 次:第 3 折做验证,其余 4 折训练
第 4 次:第 4 折做验证,其余 4 折训练
第 5 次:第 5 折做验证,其余 4 折训练
最后你会得到 5 个分数。相比一次划分,一个平均分加一个波动范围更有参考价值。
交叉验证通常会输出多个分数。例如:
[0.82, 0.86, 0.84, 0.83, 0.85]
平均分是模型整体表现,标准差代表不同折之间的波动。
实际汇报时,不要只写“准确率 0.85”,更好的写法是:
5 折交叉验证 accuracy = 0.84 ± 0.02
下面用随机森林和鸢尾花数据集做 5 折交叉验证。
import numpy as np
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
X, y = load_iris(return_X_y=True)
model = RandomForestClassifier(
n_estimators=100,
random_state=42,
n_jobs=-1,
)
scores = cross_val_score(
model,
X,
y,
cv=5,
scoring="accuracy",
n_jobs=-1,
)
print("每折分数:", scores)
print(f"平均分: {scores.mean():.4f}")
print(f"标准差: {scores.std():.4f}")
cv=5 表示 5 折交叉验证。scoring="accuracy" 表示使用准确率作为评估指标。
准确率很直观,但类别不平衡时可能骗人。
假设 1000 条样本里 990 条是正常邮件,10 条是垃圾邮件。一个模型永远预测“正常”,准确率也能达到 99%,但它完全没有抓住垃圾邮件。
这时更应该看:
评估指标要服务于任务代价。垃圾邮件、风控、医疗筛查、推荐系统,关心的指标不一定相同。
如果想同时看多个指标,可以用 cross_validate:
from sklearn.model_selection import cross_validate
result = cross_validate(
model,
X,
y,
cv=5,
scoring=["accuracy", "f1_macro"],
return_train_score=True,
)
print("验证 accuracy:", result["test_accuracy"])
print("验证 f1_macro:", result["test_f1_macro"])
print("训练 accuracy:", result["train_accuracy"])
return_train_score=True 可以帮助你比较训练分数和验证分数。如果训练分数很高,验证分数明显低,通常要警惕过拟合。
交叉验证不是测试集的替代品。更稳妥的流程是:
这样做可以减少“调参过程中污染测试集”的风险。
测试集一旦被反复使用,就不再客观。你以为是在提高模型,其实是在适应测试集。
两个模型平均分都为 0.86,但一个标准差 0.01,另一个标准差 0.08,稳定性完全不同。
如果你在全量数据上先 fit 标准化器或 TF-IDF,再做交叉验证,就可能发生数据泄漏。正确做法是使用 Pipeline,让每一折只在训练折里 fit 预处理器。
把示例模型换成 DecisionTreeClassifier(max_depth=None),再和 RandomForestClassifier 比较 5 折交叉验证的平均分和标准差。观察单棵树和随机森林谁更稳定。
下一课我们学习 GridSearchCV。它会把交叉验证和参数搜索结合起来,帮我们系统地寻找更合适的模型参数。
留言讨论