使用类权重的网格搜索和XGBClassifier

时间:2019-01-11 11:33:50

标签: scikit-learn xgboost grid-search

我正在尝试将scikit-learn GridSearchCVXGBoost XGBClassifier包装器一起用于解决我的不平衡多类分类问题。到目前为止,我已经使用类权重列表作为scale_pos_weight参数的输入,但这似乎不起作用,因为我的所有预测都是针对多数类。这可能是因为在XGBClassifier的文档中提到scale_pos_weight仅可用于二进制分类问题。

所以我的问题是,如何使用scikit-learn GridSearchCV输入多类分类任务的样本/类权重?

我的代码如下:

import numpy as np
import xgboost as xgb
from sklearn.model_selection import GridSearchCV
from sklearn.utils.class_weight import compute_class_weight

class_weights = compute_class_weight('balanced', np.unique(training_targets), 
                                 training_targets[target_label[0]])

random_state = np.random.randint(0, 1000)

parameters =    {
            'max_depth': [3, 4, 5],
            'learning_rate': [0.1, 0.2, 0.3],
            'n_estimators': [50, 100, 150],
            'gamma': [0, 0.1, 0.2],
            'min_child_weight': [0, 0.5, 1],
            'max_delta_step': [0],
            'subsample': [0.7, 0.8, 0.9, 1],
            'colsample_bytree': [0.6, 0.8, 1],
            'colsample_bylevel': [1],
            'reg_alpha': [0, 1e-2, 1, 1e1],
            'reg_lambda': [0, 1e-2, 1, 1e1],
            'base_score': [0.5]
            }

xgb_model = xgb.XGBClassifier(scale_pos_weight = class_weights, silent = True,
                          random_state = random_state)

clf = GridSearchCV(xgb_model, parameters, scoring = 'f1_micro', n_jobs = -1, cv = 5)

clf.fit(training_features, training_targets.values[:, 0])

model = clf.best_estimator_

2 个答案:

答案 0 :(得分:1)

scale_pos_weight仅用于二进制分类,因此不适用于多标签分类任务。

对于您的情况,更建议使用此处描述的weight参数(https://xgboost.readthedocs.io/en/latest/python/python_api.html)。参数将是一个数组,每个元素代表您为相应数据点分配的权重。

该想法实质上是为不同的类别手动分配不同的权重。分配权重没有标准,这取决于您的决定。分配的体重越重,在训练过程中对目标功能的影响就越大。

但是,如果使用scikit学习API格式,则不能指定weight参数,也不能使用DMAtrix格式。幸运的是,xgboost拥有自己的交叉验证功能,您可以在此处找到详细信息:https://xgboost.readthedocs.io/en/latest/python/python_api.html

答案 1 :(得分:0)

我建议您使用compute_sample_weight()函数并通过查看标签来设置每个样本的权重。这将以最优雅的方式解决您的问题。参见以下3个类别(-1,0,1):

sample_weights=compute_sample_weight({-1:4,0:1,1:4},Train_Labels)
random_search = RandomizedSearchCV(model, param_distributions=params, n_iter=param_comb,return_train_score=True, scoring=score,cv=ps, n_jobs=-1, verbose=3, random_state=1001 ) 
random_search.fit(Train,Train_Labels,sample_weight=sample_weights)