您可以引导 ROC 计算(使用替换新版本的示例)y_true
/ y_pred
脱离原来的y_true
/ y_pred
并重新计算一个新值roc_curve
每次)并以这种方式估计置信区间。
要考虑训练测试分割引起的变异性,您还可以使用随机分割 http://scikit-learn.org/stable/modules/cross_validation.html#random-permutations-cross-validation-a-k-a-shuffle-splitCV迭代器多次,在训练分割上拟合模型,生成y_pred
对于每个模型,从而收集经验分布roc_curve
s 以及最后计算这些的置信区间。
Edit: python 中的引导
以下是从单个模型的预测中引导 ROC AUC 分数的示例。我选择引导 ROC AUC,以便更容易地遵循 Stack Overflow 答案,但它可以调整为引导整个曲线:
import numpy as np
from scipy.stats import sem
from sklearn.metrics import roc_auc_score
y_pred = np.array([0.21, 0.32, 0.63, 0.35, 0.92, 0.79, 0.82, 0.99, 0.04])
y_true = np.array([0, 1, 0, 0, 1, 1, 0, 1, 0 ])
print("Original ROC area: {:0.3f}".format(roc_auc_score(y_true, y_pred)))
n_bootstraps = 1000
rng_seed = 42 # control reproducibility
bootstrapped_scores = []
rng = np.random.RandomState(rng_seed)
for i in range(n_bootstraps):
# bootstrap by sampling with replacement on the prediction indices
indices = rng.randint(0, len(y_pred), len(y_pred))
if len(np.unique(y_true[indices])) < 2:
# We need at least one positive and one negative sample for ROC AUC
# to be defined: reject the sample
continue
score = roc_auc_score(y_true[indices], y_pred[indices])
bootstrapped_scores.append(score)
print("Bootstrap #{} ROC area: {:0.3f}".format(i + 1, score))
您可以看到我们需要拒绝一些无效的重采样。然而,对于具有许多预测的真实数据,这是一个非常罕见的事件,不应显着影响置信区间(您可以尝试改变rng_seed
去检查)。
这是直方图:
import matplotlib.pyplot as plt
plt.hist(bootstrapped_scores, bins=50)
plt.title('Histogram of the bootstrapped ROC AUC scores')
plt.show()
请注意,重新采样的分数在 [0 - 1] 范围内进行审查,导致最后一个 bin 中的分数数量较多。
要获得置信区间,可以对样本进行排序:
sorted_scores = np.array(bootstrapped_scores)
sorted_scores.sort()
# Computing the lower and upper bound of the 90% confidence interval
# You can change the bounds percentiles to 0.025 and 0.975 to get
# a 95% confidence interval instead.
confidence_lower = sorted_scores[int(0.05 * len(sorted_scores))]
confidence_upper = sorted_scores[int(0.95 * len(sorted_scores))]
print("Confidence interval for the score: [{:0.3f} - {:0.3}]".format(
confidence_lower, confidence_upper))
这使:
Confidence interval for the score: [0.444 - 1.0]
置信区间非常宽,但这可能是我选择预测的结果(9 个预测中有 3 个错误),而且预测总数非常小。
关于该图的另一个注释:分数是量化的(许多空的直方图箱)。这是预测数量较少的结果。人们可以在分数上引入一点高斯噪声(或y_pred
值)来平滑分布并使直方图看起来更好。但平滑带宽的选择很棘手。
最后,如前所述,此置信区间特定于您的训练集。为了更好地估计模型类和参数引起的 ROC 变异性,您应该进行迭代交叉验证。然而,这通常成本更高,因为您需要为每个随机训练/测试分割训练一个新模型。
编辑:自从我第一次写这个回复以来,scipy 中直接有一个引导程序实现:
https://docs.scipy.org/doc/scipy/reference/ generated/scipy.stats.bootstrap.html https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.bootstrap.html