Traditional_machine_learning_tutorial

第4章第3节.模型的评估与选择

为什么要模型评估?

1. 交叉验证(cross_val_score)

使用train_test 分割一次,可能会因为分割数据集的偶然性影响结果,特别是小的数据集。

所以需要使用K折交叉验证(K-Fold CV)

将训练集分成K份,轮流使用K-1份训练,1份验证,重复K次,取平均性能

from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification

#生成示例数据
X,y= make_classification(n_samples=1000,n_features=15,n_classes=2,random_state=100)

#创建模型
rf = RandomForestClassifier(n_estimators=100)

#5折交叉验证(一般是5折或10折交叉验证)
cv_scores = cross_val_score(rf,X,y,cv=5,scoring='accuracy')

print('CV score:',cv_scores)
print(f"mean accuracy:{cv_scores.mean():.4f} ± {cv_scores.std():.4f}")

常用的CV策略

方法 适用场景
KFold(n_splits=5) 默认,适用于独立同分布数据
StratifiedKFold 分类任务推荐!保持每折中类别比例一致
LeaveOneOut 极小数据集(n < 50),计算昂贵
ShuffleSplit 随机划分多次,控制训练/测试比例

使用分层K折(推荐用于分类)

from sklearn.model_selection import StratifiedKFold

skf = StratifiedKFold(n_splits=5,shuffle=True,random_state=100)
scores = cross_val_score(rf,X,y,cv=skf)
print('CV score:',scores)
print(f"mean accuracy:{scores.mean():.4f} ± {scores.std():.4f}")

分类指标:准确率、召回率、F1-score

混淆矩阵

#完整的使用K折交叉验证和混淆矩阵的例子
from sklearn.model_selection import cross_val_score,train_test_split,StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
#引入模型评价模块混淆矩阵和可视化模块
from sklearn.metrics import confusion_matrix,accuracy_score
import seaborn as sns
import matplotlib.pyplot as plt

#生成示例数据
X,y= make_classification(n_samples=1000,n_features=15,n_classes=2,random_state=100)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.15)

#创建模型
rf = RandomForestClassifier(n_estimators=100)
#实例化分层K折验证
skf = StratifiedKFold(n_splits=5,shuffle=True,random_state=100)
#开始K折训练
scores = cross_val_score(rf,X_train,y_train,cv=skf)

print(f"5折交叉验证训练集的准确率:,{scores.mean():.4f} ± {scores.std():.4f}")
#生成训练模型
rf.fit(X_train,y_train)
#使用模型对测试集进行验证
y_pred=rf.predict(X_test)

#计算预测的准确率
test_accuracy=accuracy_score(y_test,y_pred)
print(f"测试集的准确率:{test_accuracy:.4f}")
#计算混淆矩阵
cm= confusion_matrix(y_test,y_pred)
sns.heatmap(cm,annot=True,fmt='d',cmap='Blues')
plt.xlabel('Predicted');plt.ylabel('Actual')
plt.show()

混淆矩阵和TP,TN,FN,FP的关系

  预测为正类(P) 预测为负类(N)
真实为正类(P) TP FN
真实为负类(N) FP TN

分类模型的评价指标

|指标|公式|使用场景| |—|—|—| |准确率Accuracy|(TP+TN)/(TP+TN+FP+FN)|类别平衡时可用| |精确率Precision|TP/(TP+FP)|关注”预测为正的有多少是真的”(如垃圾邮件)| |召回率Recall/Sensiyivity|TP/(TP+FN)|关注真实的正例有多少被找出来,如疾病检测| |F1-score|(Precision * Recall)/(Precision+Recall)|精确率与召回率的调和平均|

注意区分这几个关键评价指标的区别,不同的场景下优先考虑的侧重评价指标是不一样的。

一次性计算多个指标

from sklearn.metrics import classification_report
print(classification_report(y_test,y_pred))

只要输入真实值和预测值,一次输出上面的准确率、精确率、召回率、F1-score

多个指标同时评估

在K折交叉验证中评估多个指标的变化情况

#在K折交叉验证中评估多个指标
from sklearn.model_selection import cross_validate
scoring=['accuracy','precision','recall','f1']
scores = cross_validate(rf,X_train,y_train,cv=5,scoring=scoring)
for metric in scoring:
    key = f'test_{metric}'
    print(f"{metric.capitalize()}:{scores[key].mean():.4f}± {scores[key].std():.4f}")

回归指标

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import (mean_squared_error,mean_absolute_error,r2_score,mean_absolute_percentage_error)

#1.生成模拟回归数据
X,y = make_regression(n_samples=1000,#样本数
                     n_features=1,#特征数
                     n_informative=1,#有效特征数
                     noise=20,#噪音强度
                     random_state=100)
#拆分训练集和测试集
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=100)

#2.训练回归模型

#初始化并实例化线性回归模型
lr=LinearRegression()
lr.fit(X_train,y_train)

#开始预测
y_pred = lr.predict(X_test)

#3.计算回归评价指标
#3.1 均方差(MSE)
mse = mean_squared_error(y_test,y_pred)

#3.2均方根误差(RMSE)
rmse = np.sqrt(mse)

#3.3平均绝对误差
mae = mean_absolute_error(y_test,y_pred)

#3.4决定系数R2,取值范围是负无穷到1.越接近1越好。和相关系数R,不是同一个东西。
r2=r2_score(y_test,y_pred)

#3.5 平均绝对百分比误差MAPE
mape=mean_absolute_percentage_error(y_test,y_pred)*100

#4.打印评价指标
print("——回归任务评价指标——")
print("MSE:",mse)
print("RMSE",rmse)
print("MAE",mae)
print("R2",r2)
print("MAPE",mape)

#5.可视化预测结果
plt.figure(figsize=(10,6))
plt.scatter(X_test,y_test,color="blue",alpha=0.6,label='真实值')
plt.plot(X_test,y_pred,color='red',linewidth=2,label='预测值')
plt.xlabel('特征X');plt.ylabel('目标y')
plt.title('线性回归预测结果与真实值')
plt.legend()
plt.grid(True,alpha=0.3)
plt.show()

总结

步骤 建议
1. 划分数据 先 train_test_split,再在训练集上做 CV
2. 选择 CV 策略 分类用 StratifiedKFold,回归用 KFold
3. 选对指标 不平衡分类不用 Accuracy;回归看 MSE/R²
4. 多指标评估 用 cross_validate 同时看多个指标
5. 报告不确定性 给出 均值 ± 标准差(如 0.93 ± 0.01)
6. 最终评估 在独立测试集上报告最终性能