跳到主要内容
Python 数据分析:模型评估与选择实战 | 极客日志
Python AI 算法
Python 数据分析:模型评估与选择实战 机器学习模型评估与选择的完整流程。涵盖数据集划分、交叉验证方法、回归模型指标(MAE、MSE、RMSE、R²)、分类模型指标(混淆矩阵、准确率、召回率、F1-score)及 ROC-AUC 分析。通过 sklearn 实战代码演示了基准模型对比、学习曲线绘制及分类报告生成,帮助读者掌握模型性能优化与选择的关键技术。
星星泡饭 发布于 2025/2/6 更新于 2026/8/23 52 浏览Python 数据分析:模型评估与选择实战
引言
在机器学习任务中,数据预处理完成后,需要根据研究目标建立模型。选择合适的模型首先需要对其效果进行评估。本文介绍如何使用 sklearn 进行模型评估。
模型评估的基本步骤如下:
将数据集分为训练集和测试集
对训练集进行模型拟合
确定合适的评估指标
计算在测试集上的评估指标
1. 数据集划分
在机器学习问题中,理论上需要将数据集划分为训练集、验证集、测试集。
训练集 :用于拟合模型(平常的作业和测试)
验证集 :用于计算验证集误差,选择模型(模拟考)
测试集 :用于评估模型(最终考试)
但在实际应用中,一般分为训练集和测试集两个部分。通常训练集占 70%,测试集占 30%。这个比例在深度学习中可以进行相应的调整。我们可以使用 sklearn 中的 train_test_split 划分数据集。
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn import metrics
from sklearn.model_selection import KFold, cross_val_score
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
import pandas as pd
df = pd.read_csv(r'C:\Users\DELL\data-science-learning\seaborn-data\iris.csv' )
print (df.shape)
输出:(150, 5)
train_set, test_set = train_test_split(df, test_size=0.3 ,
random_state=12345 )
print (train_set.shape, test_set.shape)
输出:((105, 5), (45, 5))
可以看出此时训练集有 105 个数据,测试集有 45 个数据。
2. 交叉验证模型 评估模型时,最常用的方法之一就是交叉验证。下面以一个具体案例来看如何实现。
digits = datasets.load_digits()
features = digits.data
target = digits.target
stand = StandardScaler()
logistic = LogisticRegression()
pipeline = make_pipeline(stand, logistic)
kf = KFold(n_splits=10 , shuffle=True , random_state=1 )
使用 shuffle 打乱数据,保证我们验证集和训练集是独立同分布的 (IID) 的。
cv_results = cross_val_score(pipeline,
features,
target,
cv=kf,
scoring='accuracy' ,
n_jobs=-1 )
print (cv_results.mean())
使用 pipeline 方法可以使得这个过程很方便。上述我们是直接对数据集进行了交叉验证,在实际应用中,建议先对数据集进行划分,再对训练集使用交叉验证。
from sklearn.model_selection import train_test_split
features_train, features_test, target_train, target_test = train_test_split(features,
target,
test_size=0.1 ,
random_state=1 )
stand.fit(features_train)
features_train_std = stand.transform(features_train)
features_test_std = stand.transform(features_test)
这里之所以这样处理是因为我们的测试集是未知数据,如果使用测试集和训练集一起训练预处理器的话,测试集的信息有一部分就会泄露,因此是不科学的。更通用的做法是先将训练集训练模型,用验证集评估选择模型,最后再用训练集和验证集一起来训练选择好的模型,再来在测试集上进行测试。
pipeline = make_pipeline(stand, logistic)
cv_results = cross_val_score(pipeline,
features_train_std,
target_train,
cv=kf,
scoring='accuracy' ,
n_jobs=-1 )
print (cv_results.mean())
3. 回归模型评估指标
MAE (平均绝对误差) : $MAE = \frac{1}{m}\sum_{i=1}^{N}|y_i - \hat{y}_i|$
MSE (均方误差) : $MSE = \frac{1}{m}\sum_{i=1}^{N}(y_i - \hat{y}_i)^2$
RMSE : $RMSE = \sqrt{\frac{1}{m}\sum_{i=1}^{N}(y_i - \hat{y}_i)^2}$
R² : $R^2 = \frac{ESS}{TSS}$
from sklearn.datasets import make_regression
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LinearRegression
from sklearn import metrics
features, target = make_regression(n_samples=100 ,
n_features=3 ,
n_informative=3 ,
n_targets=1 ,
noise=50 ,
coef=False ,
random_state=1 )
ols = LinearRegression()
print (metrics.SCORERS.keys())
输出包含多种评分器,如 'explained_variance', 'r2', 'max_error', 'neg_mean_absolute_error' 等。
print (cross_val_score(ols, features, target, scoring='neg_mean_squared_error' , cv=5 ))
print (cross_val_score(ols, features, target, scoring='r2' ))
4. 创建一个基准回归模型 from sklearn.datasets import fetch_california_housing
from sklearn.dummy import DummyRegressor
from sklearn.model_selection import train_test_split
housing = fetch_california_housing()
features, target = housing.data, housing.target
features_train, features_test, target_train, target_test = train_test_split(features, target,
random_state=0 )
dummy = DummyRegressor(strategy='mean' )
dummy.fit(features_train, target_train)
dummy_score = dummy.score(features_test, target_test)
print (f"Dummy Score: {dummy_score} " )
from sklearn.linear_model import LinearRegression
ols = LinearRegression()
ols.fit(features_train, target_train)
ols_score = ols.score(features_test, target_test)
print (f"Linear Regression Score: {ols_score} " )
通过与基准模型的对比,我们可以发现线性回归模型的优势。
5. 混淆矩阵 评估分类器性能的一个重要方法是查看混淆矩阵。一般的想法是计算 A 类实例被分类为 B 类的次数,以及 B 类被预测为 A 类的个数。要计算混淆矩阵,首先需要有一组预测,以便与实际目标进行比较。
TP (True Positive) :正确预测正类的个数
FP (False Positive) :错误预测正类的个数
TN (True Negative) :正确预测负类的个数
FN (False Negative) :错误预测负类的个数
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import pandas as pd
iris = datasets.load_iris()
features = iris.data
target = iris.target
class_names = iris.target_names
features_train, features_test, target_train, target_test = train_test_split(
features, target, random_state=1 )
classifier = LogisticRegression()
target_predicted = classifier.fit(features_train, target_train).predict(features_test)
matrix = confusion_matrix(target_test, target_predicted)
df = pd.DataFrame(matrix, index=class_names, columns=class_names)
sns.heatmap(df, annot=True , cbar=None , cmap='Blues' )
plt.ylabel('True Class' )
plt.xlabel('Predict Class' )
plt.title('Confusion Matrix' )
plt.show()
6. 分类评估指标
F1-score : $F1 = \frac{2}{\frac{1}{precision} + \frac{1}{recall}}$
准确率 : $Accuracy = \frac{TP + TN}{FP + TP + FN + TN}$
召回率 : $Recall = \frac{TP}{TP + FN}$
精确率 : $Precision = \frac{TP}{TP + FP}$
其中,对于非均衡数据,使用 F1-score 比较合理。下面我们来看具体如何得到这些评估指标。
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification
X, y = make_classification(random_state=1 ,
n_samples=1000 ,
n_features=3 ,
n_informative=3 ,
n_redundant=0 ,
n_classes=2 )
logit = LogisticRegression()
print (cross_val_score(logit, X, y, scoring='accuracy' ))
print (cross_val_score(logit, X, y, scoring='f1' ))
print (cross_val_score(logit, X, y, scoring='precision' ))
可以看出,召回率和精确率两个往往不会同时增加(增加样本量可能可以让两个指标同时增加),这有点像假设检验中的第一类错误和第二类错误。因此,我们要保证这两个指标都不能太小。下面我们介绍 ROC 和 AUC。
7. ROC 和 AUC
7.1 ROC 曲线 ROC 曲线是用于二分类器的另一个常用工具。它与精密度/召回率非常相似,但不是绘制精密度与召回率的关系,而是绘制真阳性率(召回率的另一个名称)与假阳性率(FPR)的关系。FPR 是未正确归类为正的负实例的比率。通过 ROC 曲线来进行评估,计算出每个阈值下的真阳性率和假阳性率。
$TPR = TP / (TP + FN)$
$FPR = FP / (FP + TN)$
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, roc_auc_score
from sklearn.model_selection import train_test_split
features, target = make_classification(n_samples=1000 ,
n_features=10 ,
n_classes=2 ,
n_informative=3 ,
random_state=3 )
features_train, features_test, target_train, target_test = train_test_split(features,
target,
test_size=0.1 ,
random_state=1 )
logit = LogisticRegression()
logit.fit(features_train, target_train)
target_probabilities = logit.predict_proba(features_test)[:, 1 ]
false_positive_rate, true_positive_rate, thresholds = roc_curve(target_test, target_probabilities)
plt.plot(false_positive_rate, true_positive_rate)
plt.plot([0 , 1 ], ls='--' )
plt.plot([0 , 0 ], [1 , 0 ], c='.7' )
plt.plot([1 , 1 ], c='.7' )
plt.title('ROC Curve' )
plt.xlabel('False Positive Rate' )
plt.ylabel('True Positive Rate' )
plt.show()
7.2 AUC 值 比较分类器的一种方法是测量曲线下面积(AUC)。完美分类器的 AUC 等于 1,而适当的随机分类器的 AUC 等于 0.5。Sklearn 提供了一个计算 AUC 的函数 roc_auc_score。
auc_value = roc_auc_score(target_test, target_probabilities)
print (f"AUC Value: {auc_value} " )
可以看出该分类器的 AUC 值为 0.97,说明该模型的效果很好。
由于 ROC 曲线与精度/召回(PR)曲线非常相似,您可能想知道如何决定使用哪一条曲线。根据经验,当阳性类别很少,或者当你更关心假阳性而不是假阴性时,你应该更喜欢 PR 曲线。否则,使用 ROC 曲线。
8. 创建一个基准分类模型 from sklearn.datasets import load_iris
from sklearn.dummy import DummyClassifier
from sklearn.model_selection import train_test_split
iris = load_iris()
features, target = iris.data, iris.target
features_train, features_test, target_train, target_test = train_test_split(features, target,
random_state=0 )
dummy = DummyClassifier(strategy='uniform' , random_state=1 )
dummy.fit(features_train, target_train)
print (f"Dummy Classifier Score: {dummy.score(features_test, target_test)} " )
from sklearn.ensemble import RandomForestClassifier
classifier = RandomForestClassifier()
classifier.fit(features_train, target_train)
print (f"Random Forest Score: {classifier.score(features_test, target_test)} " )
9. 可视化训练集规模的影响 我们都知道,只要给我们足够多的数据集,那我们基本能训练一个效果很好的模型。接下来我们来看看如何绘制训练集大小对模型效果的影响(learning curve)。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_digits
from sklearn.model_selection import learning_curve
digits = load_digits()
features, target = digits.data, digits.target
train_sizes, train_scores, test_scores = learning_curve(RandomForestClassifier(),
features,
target,
cv=10 ,
scoring='accuracy' ,
n_jobs=-1 ,
train_sizes=np.linspace(0.01 , 1 , 50 ))
train_mean = np.mean(train_scores, axis=1 )
train_std = np.std(train_scores, axis=1 )
test_mean = np.mean(test_scores, axis=1 )
test_std = np.std(test_scores, axis=1 )
plt.plot(train_sizes, train_mean, '--' , color='black' , label='Training score' )
plt.plot(train_sizes, test_mean, color='black' , label='Cross-validation score' )
plt.fill_between(train_sizes, train_mean-train_std,
train_mean + train_std, color='#DDDDDD' )
plt.fill_between(train_sizes, test_mean-test_std,
test_mean + test_std, color='#DDDDDD' )
plt.title('Learning Curve' )
plt.xlabel('Training Set Size' )
plt.ylabel('Accuracy Score' )
plt.legend(loc='best' )
plt.tight_layout()
plt.show()
10. 生成评估指标报告 from sklearn.metrics import classification_report
iris = datasets.load_iris()
features = iris.data
target = iris.target
class_names = iris.target_names
features_train, features_test, target_train, target_test = train_test_split(
features, target, random_state=1 )
classifier = LogisticRegression()
model = classifier.fit(features_train, target_train)
target_predicted = model.predict(features_test)
print (classification_report(target_test,
target_predicted,
target_names=class_names))
总结 本文系统介绍了机器学习模型评估的核心流程与关键指标。通过 sklearn 库的实战演示,涵盖了从数据集划分、交叉验证到各类评估指标(回归与分类)的计算方法。重点讲解了混淆矩阵、ROC-AUC 曲线及学习曲线的分析与绘制。掌握这些技能有助于科学地选择模型、诊断模型性能瓶颈并进行有效优化。在实际项目中,建议结合业务场景选择合适的评估指标,避免单一指标的局限性。
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
Mermaid 预览与可视化编辑 基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
随机西班牙地址生成器 随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online