【问题标题】:Which metric to use for imbalanced classification problem?哪个指标用于不平衡分类问题?
【发布时间】:2023-12-17 17:55:02
【问题描述】:

我正在研究一个类别非常不平衡的分类问题。我的数据集中有 3 个类:0,1 类和 2 类。0 类是训练集的 11%,1 类是 13%,2 类是 75%。

我使用了随机森林分类器并获得了 76% 的准确率。但我发现 93% 的准确率来自 2 类(多数类)。这是我得到的Crosstable

我想要的结果:

  • 0 类和 1 类的假阴性更少或/和 0 类和 1 类的假阳性更少

我在互联网上找到解决问题的方法以及我尝试过的方法:

  • 使用 class_weight='balanced' 或自定义 class_weight(0 类为 1/11%,1 类为 1/13%,2 类为 1/75% ),但它不会改变任何东西(准确性和交叉表仍然相同)。你对此有解释/解释吗?

  • 我知道在这种情况下准确度并不是最好的指标,我使用了其他指标:precision_macroprecision_weightedf1_macrof1_weighted,我为每个类实现了精确率与召回率曲线下的面积,并使用平均值作为指标。

这是我的代码(欢迎反馈):

from sklearn.preprocessing import label_binarize

def pr_auc_score(y_true, y_pred):
    y=label_binarize(y_true, classes=[0, 1, 2])
    return average_precision_score(y[:,:],y_pred[:,:])

pr_auc = make_scorer(pr_auc_score, greater_is_better=True,needs_proba=True)

这是precision vs recall curves 的情节。

唉,对于所有这些指标,交叉表保持不变......它们似乎没有任何效果

  • 我还调整了 Boosting 算法(XGBoost 和 AdaBoost)的参数(以准确度为指标),但结果并没有得到改善。我不明白,因为 boosting 算法应该处理不平衡的数据

  • 最后,我使用了另一个模型 (BalancedRandomForestClassifier),我使用的指标是准确度。正如我们在crosstab 中看到的那样,结果很好。我很高兴得到这样的结果,但我注意到,当我更改此模型的指标时,结果再次没有变化......

所以我真的很想知道为什么使用 class_weight、更改指标或使用提升算法不会带来更好的结果...

【问题讨论】:

  • 您是否尝试过使用权重数组的 Xgboost?我使用 xgboost 进行不平衡的二元类分类,并设置 scale_pos_weight 提高了模型的性能。由于你有一个多类分类你不能使用 scale_pos_weight 除非你使用 one vs rest 方法,但是你可以使用权重数组,这应该可以解决问题。

标签: random-forest metrics multilabel-classification imbalanced-data boosting


【解决方案1】:

如你所见,你遇到了“准确性悖论”;

假设您有一个准确率达到 98% 的分类器,那将是惊人的,对吧? 可能,但如果您的数据包含 98% 的 0 类和 2% 的 1 类,则通过将 所有 值分配给 0 类,您可以获得 98% 的准确度,这确实是一个糟糕的分类器。

那么,我们应该怎么做?我们需要一个对数据分布不变的度量 - 输入 ROC 曲线。

  • ROC 曲线对数据的分布是不变的,因此无论分类器是否不平衡,它都是可视化分类器性能的好工具。但是,它们仅适用于二分类问题(您可以通过创建一对休息或一对一 ROC 曲线将其扩展到多分类)。

  • F-score 使用起来可能比 ROC-AUC 更“棘手”,因为它是 precision and recall 之间的权衡,您需要设置 beta 变量(通常是“1”,因此 F1 分数)。

您写道:“0 类和 1 类的误报更少或/和 0 类和 1 类的误报更少”。请记住,所有算法都通过最小化或最大化某些东西来工作——通常我们最小化某种损失函数。对于随机森林,假设我们要最小化以下函数 L:

L = (w0+w1+w2)/n

其中wi 是类别i 被分类为非类别i 的数量,即如果w0=13 我们错误分类了类别0 中的13 个样本,n 是样本总数。

很明显,当类 0 包含大部分数据时,获得小L 的简单方法是将大部分样本分类为0。现在,我们可以通过为每个类添加权重来克服这个问题,例如

L = (b0*w0+b1*w1+b2*x2)/n

例如说b0=1, b1=5, b2=10。现在您可以看到,我们不能只将大部分数据分配给c0 而不会受到权重的惩罚,即我们通过将样本分配给 0 类来更加保守,因为将 1 类分配给 0 类给我们的数据是 5 倍现在损失和以前一样!这正是(大多数)分类器中weight 的工作方式——它们为每个类分配一个惩罚/权重(通常与其比率成正比,即如果类 0 由 80% 组成,而类 1 由 20% 的数据组成然后是b0=1b1=4) 但您通常可以指定自己的重量;如果你发现分类器仍然会产生一个类的许多假阴性,那么增加该类的惩罚。

不幸的是,“没有免费的午餐”,即使用什么指标是一个问题、数据和使用特定的选择。

附带说明 - 由于拆分的计算方式,当您没有太多数据时,“随机森林”实际上可能在设计上很糟糕(如果您想知道原因,请告诉我 - 很容易看到当使用例如 Gini 作为拆分时)。由于您只向我们提供了每个班级的比例而不是数字,我无法确定。

【讨论】: