TRACK A · COMPOSITE SOURCE · 复合内容来源 · 对应课程 1.2.4、1.2.6、1.4.3 和 1.5.1–1.5.7

如何评估机器学习模型?

学习如何公平评估模型:划分训练、验证和测试数据,选择回归与分类指标,理解类别不平衡、阈值、过拟合和数据泄漏。

学习目标

1. 为什么要评估模型?

模型可能在训练样本上几乎完美,却无法处理新数据。因此,质量评估必须使用未参与参数拟合的数据。评估是一项实验,目的是尽可能模拟模型未来的实际使用条件。

2. 训练集、验证集与测试集

训练集用于拟合模型参数;验证集用于比较配置、选择超参数和决策阈值;测试集保留到最后,对选定方案进行独立评估。如果反复根据测试分数调整模型,测试集就参与了开发过程,结果会产生偏差。

按用途划分数据TRAININGfit parametersVALIDATIONselect optionsTESTfinal evaluation
70% / 15% / 15%仅为示例,并非通用规则。

3. 基线模型

Baseline(基线)是用于比较的简单参考方案。回归任务可以预测训练集均值或中位数;分类任务可以始终预测出现频率最高的类别。复杂模型必须证明有可测量的收益,才能说明其成本合理。

4. 回归指标

MAE是原始单位下的平均绝对误差;MSE对误差平方求平均,对较大的错误惩罚更强;RMSE是MSE的平方根,单位回到目标变量原单位;R²将模型与均值预测基线比较。R²可以为负数,也不代表预测正确率百分比。

Confusion matrixTrue positive · TPFalse negative · FNFalse positive · FPTrue negative · TN
混淆矩阵分别统计正确识别、漏报和误报。

MAE:平均绝对误差;MSE:均方误差;RMSE:均方根误差;R²:相对均值基线的决定系数。

5. 分类指标

混淆矩阵包含TP(真正例)、TN(真负例)、FP(假正例)和FN(假负例)。Accuracy是预测正确的比例。Precision = TP/(TP+FP),衡量正向预测的可靠性;Recall = TP/(TP+FN),衡量实际正例被发现的比例;F1是两者的调和平均数。

Accuracy = (TP+TN)/N · Precision = TP/(TP+FP) · Recall = TP/(TP+FN) · F1 = 2PR/(P+R)

6. 类别不平衡

如果1000次设备检查中只有10次故障,始终预测“无故障”的模型也能获得99%的准确率,但故障召回率为0%。面对稀有事件,必须检查混淆矩阵、precision、recall、PR曲线以及错误的实际代价。

MAEabsolute errorMSEsquared errorRMSEroot mean squared errorR²coefficient of determination
不同指标强调误差的不同方面,任何决策都不能只依赖一个数字。

7. 决策阈值与错误代价

分类器通常输出分数或概率,阈值将其转换为类别。降低阈值通常会提高recall,同时增加误报;提高阈值可能提高precision,却会漏掉更多事件。阈值应根据FP和FN的后果选择,而不是默认0.5永远正确。

8. 过拟合与数据泄漏

欠拟合意味着模型过于简单;过拟合意味着模型过度适应训练数据;泛化指模型在新数据上的表现。数据泄漏是未来信息或测试集信息进入特征或预处理。缺失值填补、标准化和特征选择都只能在训练集上拟合。

1,000 cases: 10 failures, 990 normalAccuracy 99% · Recall 0%Always predict “normal”
类别不平衡可能使准确率很高,即使所有故障都被漏报。

9. 正确划分数据

随机划分并非总是合适。预测未来时,应按时间划分:用过去训练,用未来评估。如果多行数据属于同一用户、设备或建筑,可能需要按组划分,避免相关记录同时出现在训练集和测试集。小数据集可以采用合适策略的交叉验证。

RecallPrecisionDecision threshold: low → high
示意图展示阈值变化对Precision和Recall的影响。实际曲线取决于模型和数据。

10.1. ROC-AUC 与 Precision–Recall AUC

ROC曲线展示阈值变化时真正例率(Recall)与假正例率(False Positive Rate)的关系。ROC-AUC是曲线下面积,用于衡量模型将正例排在负例之前的能力。接近0.5通常表示随机排序,1.0表示在当前评估样本上完全区分。ROC-AUC并不能告诉我们实际应用中应选择哪个阈值。

Precision–Recall曲线展示不同阈值下Precision与Recall的变化。Average Precision(AP)概括排序质量。当正类非常稀少时,PR曲线往往比ROC更有解释力:大量真负例可能使假正例率看起来很低,但实际误报数量仍然很多。AP的基线取决于正类比例。

ROC-AUC和AP都不能代替混淆矩阵、概率校准、错误成本分析以及独立测试集评估。比较模型时必须使用相同的数据划分策略。

ROC-AUCRanking · TPR / FPRPR-AUC / APPrecision / RecallK-FOLD CVRepeated validation
图6:三个互补工具——排序质量、少数正类分析,以及不同数据划分下的稳定性。

10.2. 交叉验证与数据划分策略

K折交叉验证将训练数据分成K份,重复训练K次:每次使用K−1份训练,并在剩余一份上验证。指标的平均值和波动反映结果对单次划分的敏感程度。类别不平衡时可使用StratifiedKFold,使各折中的类别比例大致一致。若同一对象有多条相关记录,应考虑GroupKFold;时间序列则应使用TimeSeriesSplit等按时间前进的策略。

交叉验证只在训练部分内部进行。测试集应保持独立,直到最终评估。若用交叉验证选择超参数,不应再反复根据测试集分数调参。预处理步骤应放入Pipeline,以便每个训练折独立拟合,避免数据泄漏。

10. 实践评估

在同一数据划分下比较基线模型和两个候选模型。回归计算MAE与RMSE;分类计算混淆矩阵、precision和recall。记录实验局限。指标不是绝对真理,它只回答特定数据上的特定问题。

Python实践

from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
from sklearn.linear_model import LinearRegression

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
model = LinearRegression().fit(X_train, y_train)
pred = model.predict(X_test)
print("MAE:", mean_absolute_error(y_test, pred))
print("RMSE:", mean_squared_error(y_test, pred) ** 0.5)
print("R2:", r2_score(y_test, pred))

注意:所有数据转换步骤都必须只在训练集上拟合。

分类实践:基线模型与逻辑回归

本实验使用合成数据,演示分层抽样、基线分类器、预处理Pipeline和多种指标。实际项目中应替换为真实特征,并提前明确误报与漏报的代价。

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split, StratifiedKFold, cross_val_score
from sklearn.dummy import DummyClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (confusion_matrix, precision_score, recall_score,
                             f1_score, roc_auc_score, average_precision_score)

X, y = make_classification(
    n_samples=1200, n_features=12, weights=[0.9, 0.1],
    class_sep=0.8, random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, stratify=y, random_state=42
)
models = {
    "baseline": DummyClassifier(strategy="prior"),
    "logistic": make_pipeline(StandardScaler(),
                              LogisticRegression(max_iter=1000))
}
for name, model in models.items():
    model.fit(X_train, y_train)
    pred = model.predict(X_test)
    score = model.predict_proba(X_test)[:, 1]
    print("\\n", name)
    print("confusion matrix:\\n", confusion_matrix(y_test, pred))
    print("precision:", precision_score(y_test, pred, zero_division=0))
    print("recall:", recall_score(y_test, pred, zero_division=0))
    print("f1:", f1_score(y_test, pred, zero_division=0))
    print("roc_auc:", roc_auc_score(y_test, score))
    print("average_precision:", average_precision_score(y_test, score))

cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
cv_scores = cross_val_score(models["logistic"], X_train, y_train,
                            cv=cv, scoring="average_precision")
print("CV AP mean/std:", cv_scores.mean(), cv_scores.std())

请在相同测试样本上比较基线模型与逻辑回归。检查混淆矩阵,并判断0.5阈值是否符合误报与漏报的实际代价。交叉验证AP衡量训练数据内部的稳定性;测试集分数仍是最终独立评估。

术语表

Baseline(基线)
用于比较候选模型的简单参考方案。
Precision(精确率)
所有正向预测中真正为正例的比例。
Recall(召回率)
所有真实正例中被模型发现的比例。
Threshold(阈值)
将分类器输出分数转换为类别的边界值。
Data leakage(数据泄漏)
使用了实际预测时不可获得的信息。
Cross-validation(交叉验证)
在多个数据划分上重复评估,以获得更稳定的估计。
ROC-AUC
ROC曲线下面积,用于衡量正例与负例的排序能力。
Average Precision(AP)
Precision–Recall曲线的汇总指标,适合正类稀少的场景。
分层抽样(Stratified split)
在不同数据子集中大致保持类别比例的划分方式。
K折交叉验证(K-fold CV)
在训练数据的K个折上重复进行验证。
混淆矩阵(Confusion Matrix)
比较真实类别与预测类别的表格。
真正例(True Positive,TP)
实际为正类且被预测为正类的样本。
假正例(False Positive,FP)
实际为负类却被预测为正类的样本。
真负例(True Negative,TN)
实际为负类且被预测为负类的样本。
假负例(False Negative,FN)
实际为正类却被预测为负类的样本。
准确率(Accuracy)
所有样本中被正确分类的比例。
F1 分数(F1-score)
Precision 与 Recall 的调和平均数。
平均绝对误差(MAE)
预测值与实际值之间绝对差的平均值。
均方误差(MSE)
预测误差平方的平均值。
均方根误差(RMSE)
MSE 的平方根,单位与目标变量相同。
决定系数(R²)
将回归模型误差与均值基线进行比较的指标。

本课知识检查

问题 1

为什么不能反复根据测试集分数选择模型?

问题 2

类别不平衡时,为什么 Accuracy 可能产生误导?

问题 3

预测未来事件时,应如何划分数据?

问题 4

如果 Accuracy 为 99%,而少数类的 Recall 为 0%,模型是否可能漏掉该类的全部事件?

← 1.4.1 · 1.4.2 · 1.4.5 · 3.1.6 · 知识地图

RU · EN · 中文