使用概率估计重复 10 倍交叉验证的平均 ROC

机器算法验证
2022-01-31 20:11:22

我计划使用机器学习算法对大约 10,000 个案例使用重复(10 次)分层 10 倍交叉验证。每次重复将使用不同的随机种子完成。

在这个过程中,我为每个案例创建了 10 个概率估计实例。在 10 次交叉验证的 10 次重复中的每一个中的 1 个概率估计实例

我可以为每个案例平均 10 个概率,然后创建一个新的平均 ROC 曲线(代表重复 10 倍 CV 的结果),可以通过配对比较将其与其他 ROC 曲线进行比较?

2个回答

根据您的描述,这似乎很有意义:您不仅可以计算平均 ROC 曲线,还可以计算其周围的方差以建立置信区间。它应该让您了解模型的稳定性。

例如,像这样:

在此处输入图像描述

在这里,我放置了单独的 ROC 曲线以及平均曲线和置信区间。有些区域曲线一致,因此我们的方差较小,有些区域曲线不一致。

对于重复的 CV,您可以重复多次并获得所有单个折叠的总平均值:

在此处输入图像描述

它与上一张图非常相似,但给出了更稳定(即可靠)的均值和方差估计。

这是获取情节的代码:

import matplotlib.pyplot as plt
import numpy as np

from sklearn.datasets import make_classification
from sklearn.cross_validation import KFold
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve

X, y = make_classification(n_samples=500, random_state=100, flip_y=0.3)

kf = KFold(n=len(y), n_folds=10)

tprs = []
base_fpr = np.linspace(0, 1, 101)

plt.figure(figsize=(5, 5))
plt.axes().set_aspect('equal', 'datalim')

for i, (train, test) in enumerate(kf):
    model = LogisticRegression().fit(X[train], y[train])
    y_score = model.predict_proba(X[test])
    fpr, tpr, _ = roc_curve(y[test], y_score[:, 1])
    
    plt.plot(fpr, tpr, 'b', alpha=0.15)
    tpr = np.interp(base_fpr, fpr, tpr)
    tpr[0] = 0.0
    tprs.append(tpr)

tprs = np.array(tprs)
mean_tprs = tprs.mean(axis=0)
std = tprs.std(axis=0)

tprs_upper = np.minimum(mean_tprs + std, 1)
tprs_lower = mean_tprs - std


plt.plot(base_fpr, mean_tprs, 'b')
plt.fill_between(base_fpr, tprs_lower, tprs_upper, color='grey', alpha=0.3)

plt.plot([0, 1], [0, 1],'r--')
plt.xlim([-0.01, 1.01])
plt.ylim([-0.01, 1.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()

对于重复的简历:

idx = np.arange(0, len(y))

for j in np.random.randint(0, high=10000, size=10):
    np.random.shuffle(idx)
    kf = KFold(n=len(y), n_folds=10, random_state=j)

    for i, (train, test) in enumerate(kf):
        model = LogisticRegression().fit(X[idx][train], y[idx][train])
        y_score = model.predict_proba(X[idx][test])
        fpr, tpr, _ = roc_curve(y[idx][test], y_score[:, 1])

        plt.plot(fpr, tpr, 'b', alpha=0.05)
        tpr = interp(base_fpr, fpr, tpr)
        tpr[0] = 0.0
        tprs.append(tpr)

灵感来源:http ://scikit-learn.org/stable/auto_examples/model_selection/plot_roc_crossval.html

平均概率是不正确的,因为这不代表您尝试验证的预测并且涉及验证样本之间的污染。

请注意,可能需要 100 次重复 10 倍交叉验证才能达到足够的精度。或者使用 Efron-Gong 乐观引导程序,它需要更少的迭代来获得相同的精度(参见例如 Rrmsvalidate函数)。

ROC 曲线对这个问题毫无洞察力。使用适当的准确度分数并附带 $c$-index(一致性概率;AUROC),它比曲线更容易处理,因为它可以使用 Wilcoxon-Mann-Whitney 统计量轻松快速地计算。c-index (concordance probability; AUROC) which is much easier to deal with than the curve, since it is calculated easily and quickly using the Wilcoxon-Mann-Whitney statistic.