random-forest - 哪个指标用于不平衡分类问题?
问题描述
我正在研究一个类别非常不平衡的分类问题。我的数据集中有 3 个类:0,1 类和 2 类。0 类是训练集的 11%,1 类是 13%,2 类是 75%。
我使用了随机森林分类器,得到了 76% 的准确率。但我发现 93% 的准确率来自 2 类(多数类)。这是我得到的交叉表。
我想要的结果:
- 0 类和 1 类的假阴性更少 OR/AND 0 类和 1 类的假阳性更少
我在互联网上找到解决问题的方法以及我尝试过的方法:
使用class_weight='balanced'或自定义的class_weight(类 0 为 1/11%,类 1 为 1/13%,类 2 为 1/75%),但它不会改变任何东西(准确性和交叉表仍然是相同的)。你对此有解释/解释吗?
我知道在这种情况下准确率不是最好的指标,我使用了其他指标:precision_macro、precision_weighted、f1_macro和f1_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)
这是精确度与召回率曲线的图。
唉,对于所有这些指标,交叉表保持不变......它们似乎没有效果
我还调整了 Boosting 算法的参数(XGBoost 和 AdaBoost)(以准确度为指标),结果也没有得到改善。我不明白,因为 boosting 算法应该处理不平衡的数据
最后,我使用了另一个模型(BalancedRandomForestClassifier),我使用的指标是准确度。正如我们在这个交叉表中看到的那样,结果很好。我很高兴得到这样的结果,但我注意到,当我更改此模型的指标时,结果再次没有变化......
所以我真的很想知道为什么使用class_weight、改变度量或使用提升算法,不会带来更好的结果......
解决方案
如您所见,您遇到了“准确性悖论”;
假设你有一个准确率为 98% 的分类器,那将是惊人的,对吧?可能是这样,但如果您的数据由 98% 的 0 类和 2% 的 1 类组成,则通过将所有值分配给 0类,您可以获得 98% 的准确度,这确实是一个糟糕的分类器。
那么,我们应该怎么做呢?我们需要一种对数据分布不变的度量——输入 ROC 曲线。
ROC 曲线对于数据的分布是不变的,因此是可视化分类器的分类性能的好工具,无论它是否不平衡。但是,它们只适用于二分类问题(您可以通过创建一对休息或一对一 ROC 曲线将其扩展到多分类)。
F-score 使用起来可能比 ROC-AUC 更“棘手”,因为它是精度和召回率之间的权衡,您需要设置 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=1
和b1=4
)但是您通常可以指定自己的重量;如果您发现分类器仍然会产生一个类的许多假阴性,则增加该类的惩罚。
不幸的是,“没有免费的午餐”,即使用什么指标是一个问题、数据和使用特定的选择。
附带说明-由于拆分的计算方式,当您没有太多数据时,“随机森林”实际上可能在设计上很糟糕(如果您想知道原因,请告诉我-使用时很容易看到例如基尼作为分裂)。由于您只向我们提供了每个班级的比例而不是数字,我无法确定。
推荐阅读
- multidimensional-array - xarray 数据集:对数据变量进行分面绘图 (data_vars)
- javascript - Javascript多输入计算器,输入由用户生成,然后这些输入应该进行计算
- vb.net - 如何在ms access数据库中按单个日期搜索?
- mysql-python - 在访问 MySQL 数据库时,使用 Python 在 where 子句中将变量传递给 SQL 选择查询
- django - 在 django 项目中将西里尔字体从 html 页面渲染为 pdf
- java - 如何在时间间隔内管理 Firestore 数据库中文档的离线更新状态
- flutter - 如何创建从侧面打开的模态底页
- javascript - NextJS - 错误:对象作为 React 子项无效(找到:带有键 {items} 的对象)
- nunjucks - 页