【问题标题】:Unbalanced classification using RandomForestClassifier in sklearn在 sklearn 中使用 RandomForestClassifier 进行不平衡分类
【发布时间】:2013-12-03 15:54:05
【问题描述】:

我有一个类不平衡的数据集。类是“1”或“0”,其中“1”类:“0”类的比率为 5:1。你如何计算每个类的预测误差和相应的重新平衡权重在带有随机森林的 sklearn 中,有点像下面的链接:http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm#balance

【问题讨论】:

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


    【解决方案1】:

    使用参数class_weight='balanced'

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

    【讨论】:

      【解决方案2】:

      sklearn 的“fit”方法不允许指定要优化的性能度量,这真是太可惜了。在解决分类任务时,当一个人在数据样本上调用 fit 方法时,似乎没有人理解、质疑或感兴趣实际发生的事情。

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

      但是想一想:看起来每次在后台调用的“fit”方法总是可以优化准确性。因此,最终,如果我们的目标是最大化 F1 分数,GridSearchCV 会为我们提供“所有模型中 F1 最好的模型”。这不傻吗?直接优化模型参数以获得最大 F1 分数不是更好吗? 记住旧的良好的 Matlab ANNs 包,您可以在其中将所需的性能指标设置为 RMSE、MAE 以及在定义了梯度计算算法的情况下您想要的任何内容。为什么 sklearn 会默默地忽略性能指标的选择?

      至少,为什么没有简单的选项来自动分配类实例权重来解决不平衡的数据集问题?为什么我们必须手动计算重量?此外,在许多机器学习书籍/文章中,我看到作者称赞 sklearn 的手册非常棒,如果不是关于主题的最佳信息来源的话。不完全是?为什么不平衡数据集问题(这显然对数据科学家来说非常重要)甚至没有在文档中涵盖? 我向 sklearn 的贡献者提出这些问题,如果他们读到这个。或者任何知道这样做的原因的人欢迎发表评论并澄清事情。

      更新

      从 scikit-learn 0.17 开始,有 class_weight='balanced' 选项,您至少可以将其传递给一些分类器:

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

      【讨论】:

        【解决方案3】:

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

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

        请注意,您不要反转比率。这也适用于class_weights。较大的数字与多数类相关。

        【讨论】:

        • 我认为最大的权重应该分配给最不频繁的标签
        • sample_weight = np.array([5 if i == 0 else 1 for i in y])
        【解决方案4】:

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

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

        样本权重。如果没有,则样本的权重相同。分裂 将创建净零或负权重的子节点是 在每个节点中搜索拆分时被忽略。如果是 分类,如果拆分会导致任何 单个类在任一子节点中的权重为负。

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

        更新

        一些澄清,因为你似乎很困惑。 sample_weight 的用法很简单,只要你记得它的目的是平衡训练数据集中的目标类。也就是说,如果您将X 作为观察值并将y 作为类(标签),那么len(X) == len(y) == len(sample_wight)sample witght 一维数组的每个元素都表示相应(observation, label) 对的权重。对于您的情况,如果 1 类被表示为 0 类的 5 倍,并且您平衡类分布,您可以使用简单的

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

        5 的权重分配给所有0 实例,将1 的权重分配给所有1 实例。有关更巧妙的balance_weights 权重评估函数,请参见上面的链接。

        【讨论】:

        • 但是如何将训练集中作为少数类的每个样本输入数组-[n_samples]?
        • @mlo 不明白您的评论的意思,请您改写一下
        • 对不起。我的意思是你会为“[n_samples]”输入什么?那只是数据集中所有标签的数组吗?例如,如果你有 X(features) 和 y(labels),你会不会只使用这样的函数:fit(X, y, sample_weight = y)。如果您不介意可以提供一个示例,也许使用我上面的情况,其中 y = [1,1,0,0,0,0,0,0,0,0](比率为 5:1)。我将如何调整权重:sample_weight = [n_samples]?
        • @mlo 因为它在 cmets 中会很乱,所以用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]
        • 再次感谢。由于 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]) 一切正常
        猜你喜欢
        • 2014-06-11
        • 2020-06-18
        • 2021-08-20
        • 2020-07-16
        • 2020-09-25
        • 2018-01-09
        • 2022-12-24
        • 1970-01-01
        • 2017-03-17
        相关资源
        最近更新 更多