在sklearn中使用RandomForestClassifier进行不平衡分类

35
4个回答

51

您可以将样本权重参数传递给随机森林的拟合方法

sample_weight : array-like, shape = [n_samples] or None

样本权重。如果为None,则样本权重相等。在搜索每个节点的分裂时,忽略会创建带有净零或负权重的子节点的分裂。对于分类问题,如果任何一个单一类在任一子节点中具有负权重,则也会忽略分裂。

在旧版本中,有一个preprocessing.balance_weights方法,用于生成给定样本的平衡权重,使得类变得均匀分布。它仍然存在于内部但仍然可用的preprocessing._weights模块中,但已被弃用,并将在未来版本中删除。不知道具体原因。

更新

作为澄清,当你感到困惑时,sample_weight的使用是直截了当的,只要你记住它的目的是平衡训练数据集中的目标类。也就是说,如果你有X作为观察值和y作为类(标签),那么len(X)==len(y)==len(sample_wight),每个1-D数组sample witght的元素表示对应的(observation, label)对的权重。对于你的情况,如果1类被表示为5次,而0类只有一次,如果你平衡类分布,你可以使用简单的

sample_weight = np.array([5 if i == 0 else 1 for i in y])

将所有的0实例分配权值为5,将所有的1实例分配权值为1。请参见上面的链接以了解更加巧妙的balance_weights权重评估函数。


2
但是如何将训练集中属于少数类的每个样本输入到数组-[n_samples]中呢? - mlo
@mlo,我不理解你的评论的意思,请你能否重新表述一下? - alko
抱歉,我的意思是你在“[n_samples]”中究竟会输入什么?那只是数据集中所有标签的数组吗?例如,如果您有X(特征)和y(标签),您是否只需像这样使用函数:fit(X,y,sample_weight = y)?如果您不介意,能否提供一个示例,例如使用我的情况,其中y = [1,1,0,0,0,0,0,0,0,0](比率为5:1)。如何使用sample_weight = [n_samples]调整权重? - mlo
1
由于在评论中不利于阅读,我更新了我的答案并提供了有关sample_weights使用的信息。对于 y = [1,1,0,0,0,0,0,0,0,0],可以使用 sw = [1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] - alko
1
再次感谢。由于sklearn中的参数需要类似数组的输入,因此当使用类似列表的sample_weight = [5 if i == 0 else 1 for i in y]时会出现错误,所以只需将其更改为sample_weight = np.array([5 if i == 0 else 1 for i in y]),一切都可以正常工作。 - mlo

11
很遗憾的是,sklearn的“fit”方法不允许指定要优化的性能度量。当我们在解决分类任务时调用fit方法时,似乎没有人真正理解、质疑或感兴趣于实际发生了什么。
scikit-learn用户只能间接使用交叉验证网格搜索,并使用适合于非平衡数据集的特定评分方法,希望能够找到一组产生适当AUC或F1分数的参数/元参数集。
但是请考虑一下:看起来每次在底层调用“fit”方法时,始终都会优化准确性。因此,最终效果是,如果我们的目标是最大化F1分数,则GridSearchCV会给我们“从所有具有最佳准确度的模型中选择最佳F1模型”。这不是很傻吗?直接优化模型参数以获得最大的F1分数不是更好吗?
还记得那些旧版好的Matlab人工神经网络包吗?你可以将期望性能指标设置为RMSE、MAE或任何你想要的东西,只要定义了梯度计算算法。为什么在scikit-learn中默默地省略了选择性能指标?
至少,为什么没有简单的选项自动分配类实例权重以解决非平衡数据集的问题?为什么我们必须手动计算权重?此外,在许多机器学习书籍/文章中,我看到作者称赞scikit-learn的手册是关于这个主题最棒甚至是最好的信息来源。真的吗?那么为什么非平衡数据集问题(显然对数据科学家非常重要)甚至没有在文档中涉及?
自scikit-learn 0.17以来,您可以传递class_weight ='balanced'选项到一些分类器中:
“平衡”模式使用y的值自动调整权重,与输入数据中类频率成反比,即 n_samples / (n_classes * np.bincount(y))。

6

使用参数 class_weight='balanced'

来自sklearn文档:使用平衡模式,根据输入数据中类别频率的倒数自动调整权重,公式为n_samples / (n_classes * np.bincount(y))


1

如果多数类为1,少数类为0,并且它们的比例为5:1,则sample_weight数组应为:

sample_weight = np.array([5 if i == 1 else 1 for i in y])

请注意不要颠倒比例。这也适用于 class_weights。较大的数字与多数类相关联。

2
我认为最少出现的标签应该被赋予最大的权重。 - robertspierre
sample_weight = np.array([5 if i == 0 else 1 for i in y]) - agent18

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接