【问题标题】:Tuning XGBoost Hyperparameters with RandomizedSearchCV使用 RandomizedSearchCV 调整 XGBoost 超参数
【发布时间】:2021-12-15 14:21:12
【问题描述】:

我正在尝试将 XGBoost 用于包含大约 500,000 个观察值和 10 个特征的特定数据集。我正在尝试使用RandomizedSeachCV 进行一些超参数调整,并且具有最佳参数的模型的性能比具有默认参数的模型差。

具有默认参数的模型:

model = XGBRegressor()
model.fit(X_train,y_train["speed"])
y_predict_speed = model.predict(X_test)

from sklearn.metrics import r2_score
print("R2 score:", r2_score(y_test["speed"],y_predict_speed, multioutput='variance_weighted'))
R2 score: 0.3540656307310167

随机搜索的最佳模型:

booster=['gbtree','gblinear']
base_score=[0.25,0.5,0.75,1]

## Hyper Parameter Optimization
n_estimators = [100, 500, 900, 1100, 1500]
max_depth = [2, 3, 5, 10, 15]
booster=['gbtree','gblinear']
learning_rate=[0.05,0.1,0.15,0.20]
min_child_weight=[1,2,3,4]

# Define the grid of hyperparameters to search
hyperparameter_grid = {
    'n_estimators': n_estimators,
    'max_depth':max_depth,
    'learning_rate':learning_rate,
    'min_child_weight':min_child_weight,
    'booster':booster,
    'base_score':base_score
    }

# Set up the random search with 4-fold cross validation
random_cv = RandomizedSearchCV(estimator=regressor,
            param_distributions=hyperparameter_grid,
            cv=5, n_iter=50,
            scoring = 'neg_mean_absolute_error',n_jobs = 4,
            verbose = 5, 
            return_train_score = True,
            random_state=42)

random_cv.fit(X_train,y_train["speed"])

random_cv.best_estimator_

XGBRegressor(base_score=0.5, booster='gblinear', colsample_bylevel=None,
             colsample_bynode=None, colsample_bytree=None, gamma=None,
             gpu_id=-1, importance_type='gain', interaction_constraints=None,
             learning_rate=0.15, max_delta_step=None, max_depth=15,
             min_child_weight=3, missing=nan, monotone_constraints=None,
             n_estimators=500, n_jobs=16, num_parallel_tree=None,
             random_state=0, reg_alpha=0, reg_lambda=0, scale_pos_weight=1,
             subsample=None, tree_method=None, validate_parameters=1,
             verbosity=None)

使用最佳模型:

regressor = XGBRegressor(base_score=0.5, booster='gblinear', colsample_bylevel=None,
             colsample_bynode=None, colsample_bytree=None, gamma=None,
             gpu_id=-1, importance_type='gain', interaction_constraints=None,
             learning_rate=0.15, max_delta_step=None, max_depth=15,
             min_child_weight=3, monotone_constraints=None,
             n_estimators=500, n_jobs=16, num_parallel_tree=None,
             random_state=0, reg_alpha=0, reg_lambda=0, scale_pos_weight=1,
             subsample=None, tree_method=None, validate_parameters=1,
             verbosity=None)

regressor.fit(X_train,y_train["speed"])
y_pred = regressor.predict(X_test)

from sklearn.metrics import r2_score
print("R2 score:", r2_score(y_test["speed"],y_pred, multioutput='variance_weighted'))

R2 score: 0.14258774171629718

正如您在运行随机搜索 3 小时后所看到的那样,准确度实际上有所下降。如果我将线性更改为树,值会上升到 0.65,那么为什么随机搜索不起作用?

我还收到以下警告:

这可能不准确,因为某些参数仅用于 语言绑定,但传递给 XGBoost 核心。或者一些 参数未使用,但通过此验证。请 如果您发现上述情况,请打开问题。

有人对这种超参数调优方法有什么建议吗?

【问题讨论】:

    标签: python machine-learning scikit-learn xgboost


    【解决方案1】:

    XGBoost Docs中所述

    参数调优是机器学习中的一门黑暗艺术,最优 模型的参数可能取决于多种场景。

    您要求针对您的特定场景提出建议,所以这里是我的一些建议。

    1. 从您的超参数搜索空间中删除维度booster。您可能想要使用默认的助推器“gbtree”。 如果您对线性模型的性能感兴趣,您可以尝试 linearridge 回归,但在 XGBoost 参数调整期间不要打扰它。
    2. 从您的超参数搜索空间中删除维度base_score。 对于足够多的提升迭代,这应该不会产生太大影响(请参阅XGB parameter docs)。
    3. 目前您的网格中有 3200 个超参数组合。期望通过查看 50 个随机的来找到一个好的可能有点过于乐观了。删除 boosterbase_score 维度后,您将降至
    hyperparameter_grid = {
        'n_estimators': [100, 500, 900, 1100, 1500],
        'max_depth': [2, 3, 5, 10, 15],
        'learning_rate': [0.05, 0.1, 0.15, 0.20],
        'min_child_weight': [1, 2, 3, 4]
        }
    

    有 400 种可能的组合。 对于第一个镜头,我会简化一点。例如,您可以尝试类似

    hyperparameter_grid = {
        'n_estimators': [100, 400, 800],
        'max_depth': [3, 6, 9],
        'learning_rate': [0.05, 0.1, 0.20],
        'min_child_weight': [1, 10, 100]
        }
    

    只剩下 81 种组合,并且删除了一些非常昂贵的组合(例如 1500 棵深度为 15 的树)。 当然我不知道你的数据,所以也许有必要考虑这么大/复杂的模型。 对于具有平方损失的回归任务,min_child_weight 只是子项中的实例数(再次参见XGB parameter docs)。 由于您有 500000 个观测值,因此无论 1、2、3 或 4 个观测值最终出现在一片叶子中,它可能不会产生(很大)差异。因此,我在这里建议[1, 10, 100]。 也许随机搜索会发现比这个网格中的默认参数更好的东西?

    1. 另一种策略可能是: 为每个组合运行交叉验证
    hyperparameter_grid = {
        'max_depth': [3, 6, 9],
        'min_child_weight': [1, 10, 100]
        }
    

    将学习率固定在某个恒定值(不要太低,例如 0.15)。对于每个设置,使用提前停止来确定适当数量的树。这可以使用xgboost.cv 方法的early_stopping_rounds 参数来实现。 然后你知道max_depthmin_child_weight 的一个很好的组合(例如,对于给定的问题,基础学习器需要有多复杂?),以及这种组合和固定学习率的大量树。 然后微调可能涉及在“接近”当前 (max_depth, min_child_weight) 解决方案和/或降低学习率的同时增加树的数量。

    1. 最后,由于答案有点长,如果详尽的网格搜索代价高昂,还有其他替代随机搜索的方法。例如。你可以看看halving grid searchsequential model based optimization

    【讨论】:

      猜你喜欢
      • 2021-02-15
      • 2021-12-25
      • 2021-02-11
      • 2019-09-04
      • 2019-03-10
      • 2020-01-29
      • 2018-11-12
      • 2020-09-10
      • 2020-06-10
      相关资源
      最近更新 更多