解释不平衡数据集上的 AUC、准确性和 f1 分数
Interpreting AUC, accuracy and f1-score on the unbalanced dataset
我想了解在数据集不平衡的情况下,AUC 是一个比 class化准确度更好的指标。
假设一个数据集包含 3 classes 的 1000 个示例,如下所示:
a = [[1.0, 0, 0]]*950 + [[0, 1.0, 0]]*30 + [[0, 0, 1.0]]*20
很明显,这个数据是不平衡的。
一个天真的策略是预测属于第一个 class.
的每个点
假设我们有一个具有以下预测的 classifier:
b = [[0.7, 0.1, 0.2]]*1000
使用列表 a
中的真实标签和列表 b
中的预测,class化准确度为 0.95。
因此,人们会相信该模型在 class 化任务上确实做得很好,但这并不是因为该模型正在预测一个 class.
中的每个点。
因此,建议使用 AUC 指标来评估不平衡的数据集。
如果我们使用 TF Keras AUC 指标预测 AUC,我们将获得 ~0.96.
如果我们通过设置 b=[[1,0,0]]*1000
使用 sklearn f1-score 指标预测 f1-score,我们将获得 0.95。
现在我有点困惑,因为所有指标(准确性、AUC 和 f1 分数)都显示出高值,这意味着该模型非常擅长预测任务(这里不是这种情况)。
我在这里遗漏了哪一点以及我们应该如何解释这些值?
谢谢。
您很可能使用 average='micro'
参数来计算 F1 分数。根据 docs,指定 'micro'
作为平均策略将:
Calculate metrics globally by counting the total true positives, false negatives and false positives.
在 class确保每个测试用例都分配给一个 class 的化任务中,计算微观 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
您基本上计算了同一个指标两次。通过指定 average='macro'
,F1-score 将首先独立计算每个标签,然后取平均值:
print(f1_score(y_true, y_pred, average='macro')) # 0.3247863247863248
如您所见,整体 F1 分数取决于平均策略,宏观 F1 分数小于 0.33 是模型在预测任务中存在缺陷的明确指标。
编辑:
由于 OP 询问何时选择哪种策略,我认为它可能对其他人也有用,所以我将尝试详细说明这个问题。
scikit-learn
实际上为支持 multiclass 和多标签 classification 任务的指标实现了四种不同的策略。方便地,classification_report
将 return 所有申请给定 class 化任务的人 Precision,Recall 和 F1-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
根据人们对 class 分布的重视程度,它们都提供了不同的视角。
micro
average是一个全局策略,基本上忽略了classes之间的区别。如果某人真的只对真阳性、假阴性和假阳性方面的总体分歧感兴趣,而不关心 classes 内的差异,这可能是有用的或合理的。如前所述,如果潜在问题不是多标签 classification 任务,这实际上等于准确率得分。 (这也是 classification_report
函数 return 编辑 accuracy
而不是 micro avg
的原因)。
macro
平均作为一种策略将分别计算每个标签的每个指标和 return 它们的未加权平均值。如果每个 class 都具有同等重要性,并且结果不应偏向数据集中的任何 class,则这是合适的。
weighted
average也会先分别计算每个label的每个metric。但平均值是根据 classes 的支持度加权的。如果 classes 的重要性与其重要性成正比,这是可取的,即代表不足的 class 被认为不太重要。
samples
平均值仅对多标签 class 化有意义,因此在此示例中 return 不会被 classification_report
编辑,此处也不讨论;)
因此,平均策略的选择和结果可信度实际上取决于 classes 的重要性。我什至关心 class 差异(如果没有 --> 微观平均),如果是,所有 class 都同样重要(如果是 --> 宏观平均)还是 class 支持度越高越重要(--> 加权平均)。
我想了解在数据集不平衡的情况下,AUC 是一个比 class化准确度更好的指标。
假设一个数据集包含 3 classes 的 1000 个示例,如下所示:
a = [[1.0, 0, 0]]*950 + [[0, 1.0, 0]]*30 + [[0, 0, 1.0]]*20
很明显,这个数据是不平衡的。
一个天真的策略是预测属于第一个 class.
的每个点
假设我们有一个具有以下预测的 classifier:
b = [[0.7, 0.1, 0.2]]*1000
使用列表 a
中的真实标签和列表 b
中的预测,class化准确度为 0.95。
因此,人们会相信该模型在 class 化任务上确实做得很好,但这并不是因为该模型正在预测一个 class.
中的每个点。
因此,建议使用 AUC 指标来评估不平衡的数据集。
如果我们使用 TF Keras AUC 指标预测 AUC,我们将获得 ~0.96.
如果我们通过设置 b=[[1,0,0]]*1000
使用 sklearn f1-score 指标预测 f1-score,我们将获得 0.95。
现在我有点困惑,因为所有指标(准确性、AUC 和 f1 分数)都显示出高值,这意味着该模型非常擅长预测任务(这里不是这种情况)。
我在这里遗漏了哪一点以及我们应该如何解释这些值?
谢谢。
您很可能使用 average='micro'
参数来计算 F1 分数。根据 docs,指定 'micro'
作为平均策略将:
Calculate metrics globally by counting the total true positives, false negatives and false positives.
在 class确保每个测试用例都分配给一个 class 的化任务中,计算微观 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
您基本上计算了同一个指标两次。通过指定 average='macro'
,F1-score 将首先独立计算每个标签,然后取平均值:
print(f1_score(y_true, y_pred, average='macro')) # 0.3247863247863248
如您所见,整体 F1 分数取决于平均策略,宏观 F1 分数小于 0.33 是模型在预测任务中存在缺陷的明确指标。
编辑:
由于 OP 询问何时选择哪种策略,我认为它可能对其他人也有用,所以我将尝试详细说明这个问题。
scikit-learn
实际上为支持 multiclass 和多标签 classification 任务的指标实现了四种不同的策略。方便地,classification_report
将 return 所有申请给定 class 化任务的人 Precision,Recall 和 F1-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
根据人们对 class 分布的重视程度,它们都提供了不同的视角。
micro
average是一个全局策略,基本上忽略了classes之间的区别。如果某人真的只对真阳性、假阴性和假阳性方面的总体分歧感兴趣,而不关心 classes 内的差异,这可能是有用的或合理的。如前所述,如果潜在问题不是多标签 classification 任务,这实际上等于准确率得分。 (这也是classification_report
函数 return 编辑accuracy
而不是micro avg
的原因)。macro
平均作为一种策略将分别计算每个标签的每个指标和 return 它们的未加权平均值。如果每个 class 都具有同等重要性,并且结果不应偏向数据集中的任何 class,则这是合适的。weighted
average也会先分别计算每个label的每个metric。但平均值是根据 classes 的支持度加权的。如果 classes 的重要性与其重要性成正比,这是可取的,即代表不足的 class 被认为不太重要。samples
平均值仅对多标签 class 化有意义,因此在此示例中 return 不会被classification_report
编辑,此处也不讨论;)
因此,平均策略的选择和结果可信度实际上取决于 classes 的重要性。我什至关心 class 差异(如果没有 --> 微观平均),如果是,所有 class 都同样重要(如果是 --> 宏观平均)还是 class 支持度越高越重要(--> 加权平均)。