如何绘制交叉验证的 AUROC 并找到最佳阈值?

问题描述 投票:0回答:1

在通过交叉验证评估我的机器学习模型时,我遇到了一个问题。我知道如何在交叉验证中绘制 AUROC 和每个折叠的相应阈值,但我不确定是否绘制所有折叠的平均 AUROC 及其相应阈值。

为此,我在Stack Overflow上探索了相关问题,找到了相应的解决方案。您可以通过以下链接找到原始问题:[https://stackoverflow.com/questions/57708023/plotting-the-roc-curve-of-k-fold-cross-validation%5C]。尽管我成功生成了平均 ROC,但在准确绘制相应阈值方面遇到了挑战。为了解决这个问题,我根据自己的理解合并了额外的代码,但我不确定这种方法的正确性。

此外,我观察到使用

np.mean()
计算的平均 AUC 与通过
sklearn.metrics
计算的 AUC 值之间存在差异。因此,我正在寻求关于哪个值更准确以获得精确的 AUC 结果的指导。下面是我调整后的修改代码。

X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=42)

cv = StratifiedKFold(n_splits=10)
classifier = SVC(kernel='sigmoid',probability=True,random_state=0)

tprs = []
aucs = []
optimal_thresholds = []
mean_fpr = np.linspace(0, 1, 100)
plt.figure(figsize=(10,10))
i = 0
for train, test in cv.split(X, y):
    probas_ = classifier.fit(X[train], y[train]).predict_proba(X[test])
    # Compute ROC curve and area the curve
    fpr, tpr, thresholds = roc_curve(y[test], probas_[:, 1])

    # The code I added:
    optimal_threshold_index = np.argmax(tpr-fpr)
    optimal_threshold = thresholds[optimal_threshold_index]
    optimal_thresholds.append(optimal_threshold)
    #

    tprs.append(np.interp(mean_fpr, fpr, tpr))
    tprs[-1][0] = 0.0
    roc_auc = auc(fpr, tpr)
    aucs.append(roc_auc)
    plt.plot(fpr, tpr, lw=1, alpha=0.3,
             label='ROC fold %d (AUC = %0.4f)' % (i, roc_auc))

    i += 1



plt.plot([0, 1], [0, 1], linestyle='--', lw=2, color='r',
         label='Chance', alpha=.8)

mean_tpr = np.mean(tprs, axis=0)
mean_tpr[-1] = 1.0


mean_auc = auc(mean_fpr, mean_tpr)

# The code I added:
np_mean_AUC = np.mean(aucs)
# print(f"np_mean_AUC={np_mean_AUC},mean_auc={mean_auc}")
#

std_auc = np.std(aucs)

plt.plot(mean_fpr, mean_tpr, color='b',
         label=r'Mean ROC (AUC = %0.4f $\pm$ %0.4f)' % (np_mean_AUC, std_auc),
         lw=2, alpha=.8)

# The code I added:
mean_optimal_threshold_index = np.argmax(mean_tpr-mean_fpr)
plt.annotate(f'Mean Optimal Threshold ({np.mean(optimal_thresholds):.2f})',
                xy=(mean_fpr[mean_optimal_threshold_index], mean_tpr[mean_optimal_threshold_index]),
                xytext=(5, -5),
                textcoords='offset points',
                arrowprops=dict(facecolor='red', arrowstyle='wedge,tail_width=0.7', shrinkA=0, shrinkB=10),
                color='red')
#

std_tpr = np.std(tprs, axis=0)
tprs_upper = np.minimum(mean_tpr + std_tpr, 1)
tprs_lower = np.maximum(mean_tpr - std_tpr, 0)
plt.fill_between(mean_fpr, tprs_lower, tprs_upper, color='grey', alpha=.2,
                 label=r'$\pm$ 1 std. dev.')

plt.xlim([-0.01, 1.01])
plt.ylim([-0.01, 1.01])
plt.xlabel('False Positive Rate',fontsize=18)
plt.ylabel('True Positive Rate',fontsize=18)
plt.title('Cross-Validation ROC of SVM',fontsize=18)
plt.legend(loc="lower right", prop={'size': 15})
plt.show()

以下是输出:

enter image description here

请告诉我我在代码中所做的更改是否可以准确绘制用于交叉验证的 ROC 曲线以及相应的阈值,以及标记的 AUC 值是否有意义。

python-3.x machine-learning data-science auc
1个回答
0
投票
  • 对于每一次折叠,您都会获得:ROC 曲线、AUC 和最佳阈值
  • 将每个折叠的 ROC 曲线插值到公共轴上
  • 所有分割完成后,对插值曲线进行平均并计算结果曲线的 AUC 和最佳阈值坐标。

我没有发现您代码中的任何错误。我认为您的报告方式略有差异

optimal_threshold
,我将在最后进行扩展。

我观察到使用以下方法计算的平均 AUC 之间存在差异

np.mean()
和由
sklearn.metrics
计算的 AUC 值。 因此,我正在寻求关于哪个值更准确的指导 获得精确的 AUC 结果。

我的观点是,为了报告单个性能分数,对 10 个 AUC 分数进行平均比插值方法更容易解释。这是因为您对 10 个“实际”训练模型的分数进行了平均,从而提供了跨折叠的性能摘要。如果您以另一种方式进行操作,即首先导出平均 ROC 曲线,则该曲线下方的面积不属于任何特定模型,并且不太容易解释为总分。尽管如此,将曲线插值到公共轴上是一种在不同阈值下放大 TPR-FPR 特征的有用技术。 在实践中,我认为这两个指标是相似的,在这种情况下它们非常接近。我认为没有明确的正确与错误的方法。

虽然我成功生成了平均 ROC,但我遇到了挑战 准确绘制相应的阈值。

在您的代码中绘制了平均 ROC 曲线,并用
np.mean(optimal_thresholds)

进行注释,而不是该平均曲线本身的阈值。这有点像您有一条曲线,但使用从其他曲线派生的一些聚合度量对其进行注释。假设我们将每个折叠的阈值插值到一个公共轴上,并获得每个点的平均阈值......这对我来说仍然没有意义,因为 skearn 对于每个折叠使用的阈值可能存在很大差异:

该图显示了

roc

为每次折叠返回的阈值,其中黑线标记了平均ROC上的最佳位置。对我来说,平均阈值似乎不是有用的可操作信息。

    

© www.soinside.com 2019 - 2024. All rights reserved.