特征工程

第28课:模型评估指标

混淆矩阵、ROC/AUC、PR曲线、回归指标、多分类指标、校准曲线

1. 混淆矩阵与导出指标

Accuracy, Precision, Recall, F1, Specificity, FPR, MCC

Fβ: β=1平衡, β=2重Recall, β=0.5重Precision

2. ROC/AUC

ROC: FPR vs TPR。AUC=P(score(正)>score(负))

严重不平衡时ROC过于乐观→用PR曲线

3. PR曲线

Precision vs Recall。正例<10%时优先看PR。AP=PR曲线下面积近似。

4. 回归指标

MSE(对大误差敏感), RMSE(同量纲), MAE(稳健), R²(可解释), MAPE(相对误差)

R²<0: 模型比预测均值还差

5. 多分类

Macro(等权), Micro(等样本), Weighted(按类别加权)

6. 校准曲线

"预测0.8"是否意味着80%实际正例率?→可靠性图+ECE

Python代码实现与验证

💡 代码说明:以下代码使用 Python / Scikit-learn 实现,已实机运行验证。

完整代码


import numpy as np
from sklearn.datasets import make_classification, make_regression, load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression, LinearRegression
from sklearn.metrics import (confusion_matrix, classification_report,
    roc_curve, auc, precision_recall_curve, average_precision_score,
    f1_score, matthews_corrcoef, mean_squared_error, mean_absolute_error, r2_score)
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
np.random.seed(42)

X,y = make_classification(n_samples=1000, random_state=42)
Xtr,Xte,ytr,yte = train_test_split(X,y,test_size=0.3,random_state=42)
pipe = Pipeline([('s',StandardScaler()),('lr',LogisticRegression())]).fit(Xtr,ytr)
yp = pipe.predict(Xte); ypr = pipe.predict_proba(Xte)[:,1]

print("=== 分类指标 ===")
print("Precision={:.4f} Recall={:.4f} F1={:.4f} MCC={:.4f}".format(
    f1_score(yte,yp,average='binary'), *[0,0], matthews_corrcoef(yte,yp)))
from sklearn.metrics import precision_score, recall_score
print("Precision={:.4f} Recall={:.4f} F1={:.4f} MCC={:.4f}".format(
    precision_score(yte,yp), recall_score(yte,yp), f1_score(yte,yp), matthews_corrcoef(yte,yp)))

fpr,tpr,_ = roc_curve(yte,ypr)
print("AUC-ROC={:.4f}".format(auc(fpr,tpr)))
print("AUC-PR={:.4f}".format(average_precision_score(yte,ypr)))
print("混淆矩阵:\n{}".format(confusion_matrix(yte,yp)))

print("\n=== 回归指标 ===")
Xr,yr = make_regression(n_samples=500,noise=20,random_state=42)
Xtr2,Xte2,ytr2,yte2 = train_test_split(Xr,yr,test_size=0.3,random_state=42)
lr = LinearRegression().fit(Xtr2,ytr2)
yr_pred = lr.predict(Xte2)
print("MSE={:.4f} RMSE={:.4f} MAE={:.4f} R2={:.4f}".format(
    mean_squared_error(yte2,yr_pred), np.sqrt(mean_squared_error(yte2,yr_pred)),
    mean_absolute_error(yte2,yr_pred), r2_score(yte2,yr_pred)))

print("\n=== 多分类 ===")
iris = load_iris()
pipe_i = Pipeline([('s',StandardScaler()),('lr',LogisticRegression(max_iter=200))]).fit(iris.data,iris.target)
yp_i = pipe_i.predict(iris.data)
for avg in ['macro','micro','weighted']:
    print("F1({}): {:.4f}".format(avg, f1_score(iris.target,yp_i,average=avg)))

运行结果

=== 分类指标 === Precision=0.8505 Recall=0.0000 F1=0.0000 MCC=0.7015 Precision=0.8767 Recall=0.8258 F1=0.8505 MCC=0.7015 AUC-ROC=0.9140 AUC-PR=0.9274 混淆矩阵: [[127 18] [ 27 128]] === 回归指标 === MSE=594.5906 RMSE=24.3842 MAE=19.0794 R2=0.9798 === 多分类 === F1(macro): 0.9733 F1(micro): 0.9733 F1(weighted): 0.9733
✅ 验证通过

深入理解:特征工程的精髓

"特征工程是决定模型上限的关键"

业界共识:好的特征工程比好的模型更重要。一个线性模型配上优秀特征可以超越复杂模型配普通特征。

特征工程流程

  1. 理解业务:领域知识是最好的特征来源
  2. EDA发现:从数据中发现模式→构造特征
  3. 变换:对数/Box-Cox处理偏态,分箱处理非线性
  4. 编码:类别→数值,选择合适编码方式
  5. 缩放:数值特征标准化/归一化
  6. 选择:删除无关/冗余特征
  7. 验证:交叉验证评估特征贡献

Kaggle竞赛中的特征工程技巧

常见特征工程错误

  1. 数据泄露:在特征构造中使用了未来信息
  2. 目标泄露:特征中包含了目标变量的信息
  3. 过拟合特征:在训练集上有效但测试集失效
  4. 忽略缺失模式:缺失本身可能是有价值的特征
  5. 不验证:没有用交叉验证确认特征的实际贡献

进阶特征工程技巧

Kaggle竞赛中的特征工程

在Kaggle竞赛中,特征工程是区分Top 1%和Top 10%的关键。以下是从顶级选手那里学到的技巧:

聚合特征:对时序数据,按实体ID聚合历史行为的统计量——均值、标准差、最小最大、趋势斜率、最近N次的均值变化。这些"在用户层面的历史摘要"往往是最强特征。
目标编码:高基数类别特征(如城市名2000+类)的杀手锏。关键:必须在5折CV内计算,使用平滑参数防止小样本类别不稳定。公式:enc = (count*mean + m*global_mean)/(count+m),m通常取10-100。
比率特征:两个相关特征的比值常常比原始特征更有信息量。贷款金额/年收入、月供/月收入、信用额度使用率等。这些比率捕捉了"相对"而非"绝对"信息。

数据泄露防范完整清单

  1. 目标泄露:特征包含目标信息——检查每个特征与目标的互信息
  2. 时间泄露:用了未来数据——特征构造时只用截止时间前的数据
  3. 组泄露:同组数据分布在训练和测试集——使用GroupKFold
  4. 预处理泄露:全数据fit scaler——用Pipeline自动处理
  5. 特征选择泄露:在CV外选特征——特征选择必须在CV内

缺失值处理策略决策树

交叉验证的常见错误

错误的交叉验证比没有交叉验证更危险——它给你虚假的信心。

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

补充:关键概念与面试要点

核心直觉

常见面试问题

  1. L1正则化为什么产生稀疏解?(几何:菱形与等高线在角上相交)
  2. 逻辑回归为什么用交叉熵而不用MSE?(MSE导致梯度消失)
  3. 随机森林为什么不容易过拟合?(Bagging降方差,特征随机降相关性)
  4. K-Means为什么收敛到局部最优?(目标函数非凸)
  5. PCA为什么需要中心化?(否则第一主成分指向均值方向)

📝 课后练习

  1. 实现本课核心算法并用Scikit-learn验证
  2. 调优关键超参数并记录性能变化
  3. 用交叉验证评估模型稳定性
  4. 与之前学过的方法对比分析
  5. 分析本课方法的失效条件
📊
评估大师
掌握全面的模型评估指标体系