微平均 Roc Auc 分数能否大于 Class Roc Auc 分数

数据挖掘 机器学习 评估
2021-10-05 18:53:16

我正在处理一个不平衡的数据集。训练数据中有 11567 个负样本和 3737 个正样本。验证数据中有 2892 个负样本和 935 个正样本。这是一个二元分类问题,我使用微观和宏观平均 ROC 来评估我的模型。但是,我注意到 Micro 平均 Roc-Auc 分数高于特定类别的 Roc-Auc 分数。这对我来说没有意义。 在此处输入图像描述

正如您在图中看到的那样,所有点的微平均 roc-auc 得分都更高。如果可能的话,你能解释一下背后的原因吗?我使用了sklearn-link并将其转换为二进制分类(y-true -> 一种热表示)。我还在下面添加了我的代码。

xgboost_model = XGBClassifier(n_estimators= 450,max_depth= 5,min_child_weight=2)
xgboost_model.fit(X_train,y_train)

yy_true,yy_pred = yy_val, xgboost_model.predict_proba(Xx_val)# .predict_proba gives probability for each class

# Compute ROC curve and ROC area for each class
y_test = flat(yy_true) # Convert labels to one hot encoded version
y_score = yy_pred

n_classes=2
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):
    fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])

# Compute micro-average ROC curve and ROC area
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])

# First aggregate all false positive rates
all_fpr = np.unique(np.concatenate([fpr[i] for i in range(n_classes)]))

# Then interpolate all ROC curves at this points
mean_tpr = np.zeros_like(all_fpr)
for i in range(n_classes):
    mean_tpr += interp(all_fpr, fpr[i], tpr[i])

# Finally average it and compute AUC
mean_tpr /= n_classes

fpr["macro"] = all_fpr
tpr["macro"] = mean_tpr
roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])

# Plot all ROC curves
plt.figure()
plt.plot(fpr["micro"], tpr["micro"],
         label='micro-average ROC curve (area = {0:0.2f})'
               ''.format(roc_auc["micro"]),
         color='deeppink', linestyle=':', linewidth=2)

plt.plot(fpr["macro"], tpr["macro"],
         label='macro-average ROC curve (area = {0:0.2f})'
               ''.format(roc_auc["macro"]),
         color='navy', linestyle=':', linewidth=2)

colors = cycle(['aqua', 'darkorange', 'cornflowerblue'])
for i, color in zip(range(n_classes), colors):
    plt.plot(fpr[i], tpr[i], color=color, lw=lw,
             label='ROC curve of class {0} (area = {1:0.2f})'
             ''.format(i, roc_auc[i]))

plt.plot([0, 1], [0, 1], 'k--', lw=lw)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve for nonSampling Training Data')
plt.legend(loc="lower right")
plt.savefig('nonsample.png', format='png', dpi=600)

plt.show()
2个回答

在二元问题中,没有理由对 ROC(或任何其他指标)进行平均。在多类分类的情况下,通常使用微观和宏观性能来获得基于单个二元分类度量的单个性能值。

所以这里发生的事情是这样的:

  • 两个类的 ROC 曲线是彼此的镜像(使用左上角右下角对角线作为对称轴),因为它们代表完全相同的点,但正负类交换了。
  • 宏观平均曲线是两条曲线的平均值,这没有多大意义,因为它们已经具有相同的形状。这就是宏、0 类和 1 类的所有 AUC 值相同的原因。
  • 微平均 ROC 是加权平均值,因此它主要由多数类(大约 75%)组成:由于多数类中的大多数点都被正确预测为多数类,因此性能看起来要好得多。这与微平均 F1 分数等于准确度这一事实有关,尽管在 ROC 中我不确定这些点是如何精确加权的。

在我看来,这很好地说明了为什么在多类设置中应该非常小心(或根本不)使用 ROC 曲线。ROC 曲线用于二元(软)分类,它们在这种情况下有用且可解释,但不一定在其他情况下。一般来说,它也说明并不是因为可以计算某些东西,结果值才有意义;)

该示例的“微平均 ROC”有点奇怪。这就像微平均统计数据,因为每个单独的样本和可能的标签都得到同等对待,但在大多数其他方面与它们不同。它本质上将问题视为多标签随着阈值的降低,最初每一行都被分类为没有标签,然后选择越来越多的标签,直到最后每一行都被标记为具有所有可能的标签。 然后对所有可能的标签采用真/假阳性/阴性。

这可能很有用,并且可能类似于 ROC,但我认为这样的曲线是否应该与单个类 ROC 曲线有任何特定关系并不明确(当然不是任何通常意义上的它们的平均值)。