在训练随机森林分类器后,我尝试了两种计算 AUC 分数的方法。第一个是从 cross_validate 函数获取指标:
numeric_transformer = make_pipeline(
IterativeImputer(estimator=RandomForestRegressor(),random_state=0),
StandardScaler()
)
preprocessor = make_column_transformer(
(numeric_transformer, numeric_cols)
)
pipe = Pipeline(steps=[
('preprocessor', preprocessor),
('clf', RandomForestClassifier())
])
scoring = {
'AUC': 'roc_auc',
'ACCURACY': 'accuracy',
'F1_SCORE': 'f1',
'PRECISION': 'precision',
'RECALL': 'recall'
}
print(scoring)
cv = StratifiedKFold(n_splits=5)
cv_scores_RF = cross_validate(pipe, X, y, cv=cv, scoring=scoring, return_estimator=True)
print("Random forest metrics")
print(f"AUC: {abs(cv_scores_RF['test_AUC']).mean()}")
print(f"ACCURACY: {cv_scores_RF['test_ACCURACY'].mean()}")
print(f"F1 SCORE: {abs(cv_scores_RF['test_F1_SCORE']).mean()}")
print(f"PRECISION: {abs(cv_scores_RF['test_PRECISION']).mean()}")
print(f"RECALL: {abs(cv_scores_RF['test_RECALL']).mean()}")
通过上面的代码,我获得了 0.72 的 AUC。
然后我用函数 RocCurveDisplay 绘制了 ROC 曲线:
import matplotlib.pyplot as plt
from sklearn.metrics import RocCurveDisplay
plt.figure(figsize=(8, 6))
tprs = []
aucs = []
for i, estimator in enumerate(cv_scores_RF['estimator']):
viz = RocCurveDisplay.from_estimator(estimator, X, y, ax=plt.gca(), name=f'ROC fold {i+1}')
roc_auc = auc(viz.fpr, viz.tpr)
aucs.append(roc_auc)
interp_tpr = np.interp(mean_fpr, viz.fpr, viz.tpr)
interp_tpr[0] = 0.0
tprs.append(interp_tpr)
mean_tpr = np.mean(tprs, axis=0)
mean_auc = np.mean(aucs)
plt.plot(mean_fpr, mean_tpr, color='b', linestyle='--', lw=2, label=f'Mean ROC (AUC = {mean_auc:.2f})')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC) - RF')
plt.legend(loc='lower right')
plt.show()
print(f"Mean AUC: {mean_auc:.2f}")
但是绘制曲线,我在图中得到的 AUC 是 0.97。为什么会出现这种情况?
我期望得到类似的值,例如我将分类器更改为 SVM,也得到了不同的值。从 cross_validate 获得的指标中,我得到了 0.53 AUC,但从 RocCurveDisplay 中得到了 0.71。还尝试使用朴素贝叶斯,在这种情况下,我得到了非常相似的值,分别为 0.66 和 0.68。
主要问题是你的第二种方法计算整个数据集上每个折叠模型的 AUC:
viz = RocCurveDisplay.from_estimator(estimator, X, y, ax=plt.gca(), name=f'ROC fold {i+1}')
由于这包括模型训练所用的数据折叠,因此分数存在乐观偏差。