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

时间:2013-11-19 21:41:34

标签: python machine-learning classification scikit-learn random-forest

我有一个数据集,其中类是不平衡的。类为'1'或'0',其中类'1':'0'的比例为5:1。如何计算每个类的预测误差以及使用随机森林的sklearn中的重新平衡权重,类似于以下链接:http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm#balance

4 个答案:

答案 0 :(得分:44)

您可以将样本权重参数传递给随机森林fit method

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)sample witght 1-d数组的每个元素代表相应的权重{{一对。对于您的情况,如果(observation, label)类被表示为1类的5倍,并且您平衡类分布,则可以使用简单的

0

为所有sample_weight = np.array([5 if i == 0 else 1 for i in y]) 实例分配5的权重,为所有0个实例分配1的权重。请参阅上面的链接,了解更加狡猾的1权重评估函数。

答案 1 :(得分:7)

这真是一个耻辱,sklearn&#34; fit&#34;方法不允许指定要优化的性能度量。在解决分类任务时,当人们在数据样本上调用拟合方法时,周围没有人似乎理解或质疑或对实际发生的事情感兴趣。

我们(scikit学习软件包的用户)默默地建议间接使用交叉验证网格搜索和适用于不平衡数据集的特定评分方法,希望偶然发现产生适当AUC或F1的参数/元参数集分数。

但请想一想:看起来像#34; fit&#34;引擎盖下每次调用的方法总能优化准确性。因此,在最终效果中,如果我们的目标是最大化F1得分,GridSearchCV为我们提供了所有模式中具有最佳精度的最佳F1的模型&#34;。那不是傻吗?直接优化模型参数以获得最大F1分数不是更好吗? 记住旧的好的Matlab人工神经网络包,在这里你可以设置所需的性能指标到RMSE,MAE,以及任何你想要的梯度计算算法定义。为什么从sklearn中默认选择性能指标?

至少,为什么没有简单的选项可以自动分配类实例权重来修复不平衡的数据集问题?为什么我们必须手动计算人体?此外,在许多机器学习书籍/文章中,我看到作者赞扬sklearn的手册,如果不是主题信息的最佳来源,那就太棒了。不完全是?为什么不平衡的数据集问题(这显然对数据科学家来说非常重要)在文档中甚至没有涉及到它们? 如果他们读到这个,我会向sklearn的贡献者提出这些问题。或者任何知道这样做的理由的人都欢迎评论和澄清。

<强>更新

由于scikit-learn 0.17,有class_weight =&#39; balance&#39;您可以至少传递给某些分类器的选项:

  

“平衡”模式使用y的值自动调整   权重与输入数据中的类频率成反比   as n_samples /(n_classes * np.bincount(y))。

答案 2 :(得分:2)

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

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

请注意,您不会反转比率。这也适用于class_weights。较大的数字与多数班级有关。

答案 3 :(得分:1)

使用参数class_weight='balanced'

摘自sklearn文档: balanced 模式使用y值自动将权重与输入数据中的类频率成反比地调整为n_samples / (n_classes * np.bincount(y))