解释不平衡数据集上的 AUC、准确度和 f1 分数

abh*_*bhi 2 python scikit-learn auc multiclass-classification tensorflow2.0

我试图了解在数据集不平衡的情况下,AUC 为何是比分类准确性更好的指标。
假设数据集包含 3 个类别的 1000 个示例,如下所示:

a = [[1.0, 0, 0]]*950 + [[0, 1.0, 0]]*30 + [[0, 0, 1.0]]*20
Run Code Online (Sandbox Code Playgroud)

显然,这个数据是不平衡的。
一个幼稚的策略是预测属于第一类的每个点。
假设我们有一个具有以下预测的分类器:

b = [[0.7, 0.1, 0.2]]*1000
Run Code Online (Sandbox Code Playgroud)

使用列表中的真实标签a和列表中的预测b,分类精度为 0.95。
因此,人们会认为该模型确实在分类任务上表现良好,但这并不是因为该模型正在预测一个类别中的每个点。
因此,建议使用 AUC 指标来评估不平衡的数据集。如果我们使用 TF Keras AUC
指标 预测 AUC ,我们会得到 ~0.96。 如果我们通过设置 来使用 sklearn f1-score指标来预测 f1-score ,我们会得到 0.95。
b=[[1,0,0]]*1000

现在我有点困惑,因为所有指标(准确度、AUC 和 f1-score)都显示出很高的价值,这意味着该模型非常擅长预测任务(但这里的情况并非如此)。

我在这里遗漏了哪一点以及我们应该如何解释这些价值观?
谢谢。

afs*_*rov 5

您很可能使用该average='micro'参数来计算 F1 分数。根据文档,指定'micro'平均策略将:

通过计算总的真阳性、假阴性和假阳性来计算全局指标。

在保证每个测试用例都准确分配到一个类的分类任务中,计算微 F1 分数相当于计算准确性分数。只需检查一下:

from sklearn.metrics import accuracy_score, f1_score

y_true = [[1, 0, 0]]*950 + [[0, 1, 0]]*30 + [[0, 0, 1]]*20
y_pred = [[1, 0, 0]]*1000

print(accuracy_score(y_true, y_pred)) # 0.95

print(f1_score(y_true, y_pred, average='micro')) # 0.9500000000000001
Run Code Online (Sandbox Code Playgroud)

您基本上计算了相同的指标两次。通过指定average='macro',将首先独立计算每个标签的 F1 分数,然后求平均值:

print(f1_score(y_true, y_pred, average='macro')) # 0.3247863247863248
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,总体 F1 分数取决于平均策略,小于 0.33 的宏观 F1 分数清楚地表明模型在预测任务中存在缺陷。


编辑:

由于OP询问何时选择哪种策略,并且我认为这对其他人也可能有用,因此我将尝试详细说明这个问题。

scikit-learn实际上实现了四种不同的指标策略,支持多类和多标签分类任务的平均值。方便地,classification_report将返回所有适用于给定分类任务的PrecisionRecallF1-score

from sklearn.metrics import classification_report

# The same example but without nested lists. This avoids sklearn to interpret this as a multilabel problem.
y_true = [0 for i in range(950)] + [1 for i in range(30)] + [2 for i in range(20)]
y_pred = [0 for i in range(1000)]

print(classification_report(y_true, y_pred, zero_division=0))

######################### output ####################

              precision    recall  f1-score   support

           0       0.95      1.00      0.97       950
           1       0.00      0.00      0.00        30
           2       0.00      0.00      0.00        20

    accuracy                           0.95      1000
   macro avg       0.32      0.33      0.32      1000
weighted avg       0.90      0.95      0.93      1000
Run Code Online (Sandbox Code Playgroud)

所有这些都提供了不同的视角,具体取决于人们对班级分布的重视程度。

  1. micro平均是一种全局策略,基本上忽略了阶级之间的区别。如果有人真的只对真阳性、假阴性和假阳性方面的总体分歧感兴趣,而不关心类别内的差异,那么这可能是有用的或合理的。如前所述,如果潜在问题不是多标签分类任务,则这实际上等于准确性分数。(这也是classification_report函数返回accuracy而不是返回的原因micro avg)。

  2. macro平均值作为策略将分别计算每个标签的每个指标并返回其未加权平均值。如果每个类都同等重要并且结果不应偏向数据集中的任何类,则这是合适的。

  3. weightedAverage 还将首先分别计算每个标签的每个指标。但平均值是根据班级的支持度进行加权的。如果类别的重要性与其重要性成正比,即代表性不足的类别被认为不太重要,则这是理想的。

  4. samples平均值仅对多标签分类有意义,因此在此示例中不会返回classification_report,也不会在此处讨论;)

因此,平均策略的选择和值得信赖的结果数字实际上取决于类别的重要性。我是否关心类别差异(如果否 -> 微观平均),如果是,所有类别是否都同等重要(如果是 -> 宏观平均),还是支持度较高的类别更重要( - > 加权平均) 。