基于GridSearchCV与Pipeline绘制RepeatedStratifiedKFold各折及平均ROC曲线
交叉验证折ROC、平均ROC与测试集ROC的叠加绘制
核心思路
GridSearchCV默认仅保留最优参数训练的最终模型,不会存储交叉验证过程中每个折的模型与验证集预测结果。因此需要手动遍历交叉验证的每个折,用最优参数训练模型并获取验证集概率,进而计算并绘制各折ROC、平均ROC,最后叠加测试集ROC。
具体实现步骤
1. 导入依赖库与准备数据
import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split, RepeatedStratifiedKFold, GridSearchCV from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler from sklearn.svm import SVC from sklearn.metrics import roc_curve, auc
# 生成示例数据(替换为你的真实数据) X, y = make_classification(n_samples=1000, n_classes=2, random_state=42) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
2. 定义Pipeline与参数网格
# 构建包含标准化与分类器的Pipeline pipe = Pipeline([ ('scaler', StandardScaler()), ('classifier', SVC(probability=True, random_state=42)) ]) # 设置参数搜索网格(替换为你的参数范围) param_grid = { 'classifier__C': [0.1, 1, 10], 'classifier__kernel': ['linear', 'rbf'] }
3. 网格搜索获取最优参数
# 定义重复分层交叉验证策略 cv = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=42) # 执行网格搜索,以ROC-AUC为评分标准 grid_search = GridSearchCV(pipe, param_grid, cv=cv, scoring='roc_auc', n_jobs=-1) grid_search.fit(X_train, y_train) best_params = grid_search.best_params_
4. 遍历交叉验证折,收集ROC数据
fprs = [] # 存储每个折的假阳性率 tprs = [] # 存储每个折的真阳性率 aucs = [] # 存储每个折的AUC值 # 遍历每个交叉验证折 for train_idx, val_idx in cv.split(X_train, y_train): X_tr, X_val = X_train[train_idx], X_train[val_idx] y_tr, y_val = y_train[train_idx], y_train[val_idx] # 用最优参数训练模型 best_pipe = pipe.set_params(**best_params) best_pipe.fit(X_tr, y_tr) # 预测验证集的正类概率 y_val_proba = best_pipe.predict_proba(X_val)[:, 1] # 计算当前折的ROC曲线与AUC fpr, tpr, _ = roc_curve(y_val, y_val_proba) roc_auc = auc(fpr, tpr) fprs.append(fpr) tprs.append(tpr) aucs.append(roc_auc)
5. 计算平均ROC曲线
由于每个折的FPR点数量不一致,需插值到统一的横坐标点上:
# 生成0到1之间的100个均匀FPR点 mean_fpr = np.linspace(0, 1, 100) # 对每个折的TPR进行插值,匹配mean_fpr interp_tprs = [] for fpr, tpr in zip(fprs, tprs): interp_tpr = np.interp(mean_fpr, fpr, tpr) interp_tpr[0] = 0.0 # 强制起点为(0,0) interp_tprs.append(interp_tpr) # 计算平均TPR、平均AUC及标准差 mean_tpr = np.mean(interp_tprs, axis=0) mean_tpr[-1] = 1.0 # 强制终点为(1,1) mean_auc = auc(mean_fpr, mean_tpr) std_auc = np.std(aucs)
6. 绘制所有ROC曲线
plt.figure(figsize=(8, 6)) # 绘制每个交叉验证折的灰色ROC曲线(低透明度避免重叠) for fpr, tpr in zip(fprs, tprs): plt.plot(fpr, tpr, color='gray', alpha=0.3) # 绘制交叉验证平均ROC曲线 plt.plot(mean_fpr, mean_tpr, color='blue', label=f'交叉验证平均ROC (AUC = {mean_auc:.2f} ± {std_auc:.2f})', lw=2) # 绘制测试集ROC曲线 y_test_proba = grid_search.best_estimator_.predict_proba(X_test)[:, 1] test_fpr, test_tpr, _ = roc_curve(y_test, y_test_proba) test_auc = auc(test_fpr, test_tpr) plt.plot(test_fpr, test_tpr, color='red', label=f'测试集ROC (AUC = {test_auc:.2f})', lw=2) # 绘制随机猜测基准线 plt.plot([0, 1], [0, 1], color='black', linestyle='--') # 设置图表属性 plt.xlim([-0.05, 1.05]) plt.ylim([-0.05, 1.05]) plt.xlabel('假阳性率(FPR)') plt.ylabel('真阳性率(TPR)') plt.title('ROC曲线:交叉验证折、平均与测试集') plt.legend(loc="lower right") plt.show()
关键说明
- 若需要使用交叉验证过程中每个折自行搜索到的最优参数(而非全局最优参数),只需在遍历折时,针对当前折的训练数据执行GridSearchCV,再用该折的最优模型预测验证集即可。
- 灰色曲线的透明度
alpha可根据折的数量调整,折数越多则设置越小,避免画面杂乱。
内容的提问来源于stack exchange,提问作者moe
相关产品推荐
相关产品推荐

