【问题标题】:XGboost python - classifier class weight option?XGboost python - 分类器类权重选项?
【发布时间】:2021-05-17 16:40:55
【问题描述】:

有没有办法为 xgboost 分类器设置不同的类权重?例如,在 sklearn RandomForestClassifier 中,这是由“class_weight”参数完成的。

【问题讨论】:

  • 注意:以下所有解决方案都不再有效,因为不再支持 sample_weight。
  • scale_pos_weight 是正确的参数。看看我下面的答案。
  • @SriK 是的,但它只适用于二元分类问题
  • @SriK 我不是机器学习的员工/资深人士,但根据我在 XGBoost 的 scikit-learn 版本中看到的情况,我们确实有可用的样本权重,而且效果非常好很适合我几分钟前对罕见疾病的研究。 xgboost.readthedocs.io/en/latest/python/…

标签: scikit-learn xgboost


【解决方案1】:

使用 sklearn 包装器时,有一个权重参数。

示例:

import xgboost as xgb
exgb_classifier = xgboost.XGBClassifier()
exgb_classifier.fit(X, y, sample_weight=sample_weights_data)

其中参数应该是数组,长度N,等于目标长度

【讨论】:

  • 如何将它与 Pipeline 一起使用?因为你不能直接在管道内使用fit
  • @Deshwal 由于这是一种不同类型的查询,我不想深入研究与原始内容无关的回复,这里有一篇不错的文章讨论这样的事情:towardsdatascience.com/…
【解决方案2】:

适用于 sklearn 版本

只需为您的火车数据的每个条目分配其类别权重。首先使用 sklearn 的class_weight.compute_class_weight 获取类权重,然后为每一行训练数据分配适当的权重。

我在这里假设火车数据的列class 包含班级编号。我还假设有从 1 到 nb_classesnb_classes

from sklearn.utils import class_weight
classes_weights = list(class_weight.compute_class_weight('balanced',
                                             np.unique(train_df['class']),
                                             train_df['class']))

weights = np.ones(y_train.shape[0], dtype = 'float')
for i, val in enumerate(y_train):
    weights[i] = classes_weights[val-1]

xgb_classifier.fit(X, y, sample_weight=weights)

更新 sklearn 版本 >= 0.19

有更简单的解决方案

from sklearn.utils import class_weight
classes_weights = class_weight.compute_sample_weight(
    class_weight='balanced',
    y=train_df['class']
)

xgb_classifier.fit(X, y, sample_weight=classes_weights)

【讨论】:

  • 我得到了你的答案,它工作正常,但是当你必须使用 Pipeline 时你怎么能做到这一点?不能直接使用fit方法。
  • @Deshwal 由于这是一种不同类型的查询,我不想深入研究与原始内容无关的回复,这里有一篇不错的文章讨论这样的事情:towardsdatascience.com/…
【解决方案3】:

我最近遇到了这个问题,所以想到会留下我尝试过的解决方案

from xgboost import XGBClassifier

# manually handling imbalance. Below is same as computing float(18501)/392318 
on the trainig dataset.
# We are going to inversely assign the weights
weight_ratio = float(len(y_train[y_train == 0]))/float(len(y_train[y_train == 
1]))
w_array = np.array([1]*y_train.shape[0])
w_array[y_train==1] = weight_ratio
w_array[y_train==0] = 1- weight_ratio

xgc = XGBClassifier()
xgc.fit(x_df_i_p_filtered, y_train, sample_weight=w_array)

不确定,为什么,但结果非常令人失望。希望这对某人有所帮助。

[参考链接]https://www.programcreek.com/python/example/99824/xgboost.XGBClassifier

【讨论】:

  • 应该是 w1 = np.array([1.0] * y_train.shape[0]) ,将 numpy 数组的 dtype 初始化为浮点数。否则,以下语句将生成一个包含全零的 numpy 数组。
【解决方案4】:

这里的答案已经过时了。不再支持 sample_weight 参数。它被 scale_pos_weight 取代

而只是做 scale_pos_weight = sum(negative instances) / sum(positive instances)

【讨论】:

  • 是的,但这仅适用于二元分类问题
【解决方案5】:
from sklearn.utils.class_weight import compute_sample_weight
xgb_classifier.fit(X, y, sample_weight=compute_sample_weight("balanced", y))

【讨论】:

  • 请在开始代码实现之前为您的答案添加一些解释。
【解决方案6】:

您也可以使用scale_pos_weight 超参数,如XGBoost docs 中所述。这种方法的优点是不必构造样本权重向量,也不必在fit时间传入样本权重向量。

【讨论】:

  • 有趣。我尝试了我的问题,我的问题是这种方法与 fit 方法中的 sample_weight 有什么不同?如果您对此有所了解,那就太棒了。
【解决方案7】:

类似于@Firas Omrane 和@Pramit 的回答,但我认为它更像是pythonic


    from sklearn.utils import class_weight
    class_weights = dict(
            zip(
                [0,1],
                class_weight.compute_class_weight(
                    'balanced', classes=np.unique(train['class']), y=train['class']
                ),
            )
        ) 
    
    xgb_classifier.fit(X, train['class'], sample_weight=class_weights)

【讨论】:

  • class_weights 的格式不是xgb 所期望的。您能否详细说明是否需要做任何额外的工作才能使其正常工作?谢谢
  • @juanbretti 使用 Skibee 的响应将不适用于 Scikit-xgboost learn 的实现,因为它们需要一个类似于您的类目标的列表(即相同的大小)但具有此第 i 个的权重值而不是1、0 或列中的任何唯一值。因此,此答案非常适合记录,例如,应将哪些类权重应用于您的唯一值。但是,我建议在将其与 XGBoost Scikit Learn 实现一起使用时使用 class weight.compute 样本权重。你明白吗?还是一头雾水?
猜你喜欢
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
  • 2020-01-19
  • 2021-07-24
  • 2018-01-30
  • 2019-04-13
  • 2021-05-24
相关资源
最近更新 更多