【问题标题】:Unable to tune hyperparameters for CatBoostRegressor无法调整 CatBoostRegressor 的超参数
【发布时间】:2021-10-27 05:55:10
【问题描述】:

我正在尝试将 CatBoostRegressor 拟合到我的模型中。当我为基线模型执行 K 折叠 CV 时,一切正常。但是当我使用 Optuna 进行超参数调优时,它会做一些非常奇怪的事情。它运行第一次试验,然后抛出以下错误:-

[I 2021-08-26 08:00:56,865] Trial 0 finished with value: 0.7219653113910736 and parameters: 
{'model__depth': 2, 'model__iterations': 1715, 'model__subsample': 0.5627211605250965, 
'model__learning_rate': 0.15601805222619286}. Best is trial 0 with value: 0.7219653113910736. 
[W 2021-08-26 08:00:56,869] 

Trial 1 failed because of the following error: CatBoostError("You 
can't change params of fitted model.")
Traceback (most recent call last):

我对 XGBRegressor 和 LGBM 使用了类似的方法,它们运行良好。那么为什么我会收到 CatBoost 错误?

下面是我的代码:-

cat_cols = [cname for cname in train_data1.columns if 
train_data1[cname].dtype == 'object']
num_cols = [cname for cname in train_data1.columns if 
train_data1[cname].dtype in ['int64', 'float64']]


from sklearn.preprocessing import StandardScaler
num_trans = Pipeline(steps = [('impute', SimpleImputer(strategy = 
                             'mean')),('scale', StandardScaler())])
cat_trans = Pipeline(steps = [('impute', SimpleImputer(strategy = 
                             'most_frequent')), ('encode', 
                         OneHotEncoder(handle_unknown = 'ignore'))])

from sklearn.compose import ColumnTransformer

preproc = ColumnTransformer(transformers = [('cat', cat_trans, 
                           cat_cols), ('num', num_trans, num_cols)])


from catboost import CatBoostRegressor
cbr_model = CatBoostRegressor(random_state = 69, 
                             loss_function='RMSE', 
                             eval_metric='RMSE', 
                             leaf_estimation_method ='Newton', 
                             bootstrap_type='Bernoulli', task_type = 
                             'GPU')

pipe = Pipeline(steps = [('preproc', preproc), ('model', cbr_model)])


import optuna
from sklearn.metrics import mean_squared_error

def objective(trial):
    model__depth = trial.suggest_int('model__depth', 2, 10)
    model__iterations = trial.suggest_int('model__iterations', 100, 
                                          2000)
    model__subsample = trial.suggest_float('model__subsample', 0.0, 
                                           1.0)
    model__learning_rate =trial.suggest_float('model__learning_rate', 
                                              0.001, 0.3, log = True)

    params = {'model__depth' : model__depth,
              'model__iterations' : model__iterations,
              'model__subsample' : model__subsample, 
              'model__learning_rate' : model__learning_rate}

    pipe.set_params(**params)
    pipe.fit(train_x, train_y)
    pred = pipe.predict(test_x)

    return np.sqrt(mean_squared_error(test_y, pred))

cbr_study = optuna.create_study(direction = 'minimize')
cbr_study.optimize(objective, n_trials = 10)

【问题讨论】:

  • 你如何定义pipe?既适用于 CatBoost,也适用于例如LGBM
  • @Rafa 我已经编辑了我的问题以包含相关代码
  • 尝试在objective 中包含cbr_modelpipe 的定义并检查它是否有效
  • 但是我已经在全球范围内定义了这两个。为什么要在函数内部单独定义?

标签: python machine-learning hyperparameters catboost


【解决方案1】:

显然,CatBoost 具有这种机制,您必须为每次试验创建新的 CatBoost 模型对象。我在 Github 上打开了一个关于此问题的问题,他们说它的实施是为了保护结果长时间的训练。这对我来说毫无意义!

目前,解决此问题的唯一方法是您必须为每次试验创建新的 CatBoost 模型!

如果您使用Pipeline 方法和 Optuna,另一种更明智的方法是在 optuna 函数中定义最终管道实例和模型实例。然后在函数外再次定义最终的管道实例。

这样,如果您使用 50 个试验,您就不必定义 50 个实例!!

【讨论】:

    猜你喜欢
    • 2017-10-26
    • 2020-07-24
    • 1970-01-01
    • 2021-12-08
    • 2018-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-12
    相关资源
    最近更新 更多