python-3.x - GridSearchCV - XGBoost - 提前停止

标签 python-3.x scikit-learn regression data-science xgboost

我正在尝试在 XGBoost 上使用 scikit-learn 的 GridSearchCV 进行超参数搜索。在网格搜索期间,我希望它尽早停止,因为它大大减少了搜索时间并且(期望)在我的预测/回归任务上获得更好的结果。我通过其 Scikit-Learn API 使用 XGBoost。

    model = xgb.XGBRegressor()
    GridSearchCV(model, paramGrid, verbose=verbose ,fit_params={'early_stopping_rounds':42}, cv=TimeSeriesSplit(n_splits=cv).get_n_splits([trainX, trainY]), n_jobs=n_jobs, iid=iid).fit(trainX,trainY)

我尝试使用 fit_params 提供提前停止参数,但随后抛出此错误,这基本上是因为缺少提前停止所需的验证集:
/opt/anaconda/anaconda3/lib/python3.5/site-packages/xgboost/callback.py in callback(env=XGBoostCallbackEnv(model=<xgboost.core.Booster o...teration=4000, rank=0, evaluation_result_list=[]))
    187         else:
    188             assert env.cvfolds is not None
    189 
    190     def callback(env):
    191         """internal function"""
--> 192         score = env.evaluation_result_list[-1][1]
        score = undefined
        env.evaluation_result_list = []
    193         if len(state) == 0:
    194             init(env)
    195         best_score = state['best_score']
    196         best_iteration = state['best_iteration']

如何使用 early_stopping_rounds 在 XGBoost 上应用 GridSearch?

注意:模型在没有 gridsearch 的情况下工作,GridSearch 也在没有 'fit_params={'early_stopping_rounds':42} 的情况下工作

最佳答案

这是一个在带有 GridSearchCV 的管道中工作的解决方案。当您拥有预处理训练数据所需的管道时,就会出现挑战。例如,当 X 是文本文档时,您需要 TFTDFVectorizer 对其进行矢量化。
覆盖 XGBRegressor 或 XGBClssifier.fit() 函数

  • 这一步使用 train_test_split() 选择指定数量的
    来自 X 的 eval_set 的验证记录,然后通过
    剩余的记录到 fit()。
  • .fit() 中添加了一个新参数 eval_test_size 来控制验证记录的数量。 (参见 train_test_split test_size 文档)
  • **kwargs 传递用户为 XGBRegressor.fit() 函数添加的任何其他参数。
  • from xgboost.sklearn import XGBRegressor
    from sklearn.model_selection import train_test_split
    
    class XGBRegressor_ES(XGBRegressor):
        
        def fit(self, X, y, *, eval_test_size=None, **kwargs):
            
            if eval_test_size is not None:
            
                params = super(XGBRegressor, self).get_xgb_params()
                
                X_train, X_test, y_train, y_test = train_test_split(
                    X, y, test_size=eval_test_size, random_state=params['random_state'])
                
                eval_set = [(X_test, y_test)]
                
                # Could add (X_train, y_train) to eval_set 
                # to get .eval_results() for both train and test
                #eval_set = [(X_train, y_train),(X_test, y_test)] 
                
                kwargs['eval_set'] = eval_set
                
            return super(XGBRegressor_ES, self).fit(X_train, y_train, **kwargs) 
    
    示例用法
    下面是一个多步管道,其中包括对 X 的多次转换。管道的 fit() 函数将新的评估参数作为 xgbr__eval_test_size=200 传递给上面的 XGBRegressor_ES 类。在这个例子中:
  • X_train 包含传递给管道的文本文档。
  • XGBRegressor_ES.fit() 使用 train_test_split() 从 X_train 中选择 200 条记录作为验证集并提前停止。 (这也可以是一个百分比,例如 xgbr__eval_test_size=0.2)
  • X_train 中的剩余记录传递给 XGBRegressor.fit() 以进行实际的 fit()。
  • 现在可能会在网格搜索中每个 cv 折叠的 75 轮不变提升之后发生提前停止。
  • from sklearn.pipeline import Pipeline
    from sklearn.feature_extraction.text import TfidfVectorizer
    from sklearn.feature_selection import VarianceThreshold
    from sklearn.preprocessing import StandardScaler
    from sklearn.feature_selection import SelectPercentile, f_regression
       
    xgbr_pipe = Pipeline(steps=[('tfidf', TfidfVectorizer()),
                         ('vt',VarianceThreshold()),
                         ('scaler', StandardScaler()),
                         ('Sp', SelectPercentile()),
                         ('xgbr',XGBRegressor_ES(n_estimators=2000,
                                                 objective='reg:squarederror',
                                                 eval_metric='mae',
                                                 learning_rate=0.0001,
                                                 random_state=7))    ])
    
    X_train = train_idxs['f_text'].values
    y_train = train_idxs['Pct_Change_20'].values
    
    安装管道示例:
    %time xgbr_pipe.fit(X_train, y_train, 
                        xgbr__eval_test_size=200,
                        xgbr__eval_metric='mae', 
                        xgbr__early_stopping_rounds=75)
    
    
    示例拟合 GridSearchCV:
    learning_rate = [0.0001, 0.001, 0.01, 0.05, 0.1, 0.2, 0.3]
    param_grid = dict(xgbr__learning_rate=learning_rate)
    
    grid_search = GridSearchCV(xgbr_pipe, param_grid, scoring="neg_mean_absolute_error", n_jobs=-1, cv=10)
    grid_result = grid_search.fit(X_train, y_train, 
                        xgbr__eval_test_size=200,
                        xgbr__eval_metric='mae', 
                        xgbr__early_stopping_rounds=75)
    

    关于python-3.x - GridSearchCV - XGBoost - 提前停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42993550/

    相关文章:

    Python:如何从字符串中删除数字周围的引号

    python - “float”类型错误 Python、pandas

    r - 如何用 R 找到回归线上的最低值和最高值?

    r - 从 glm 系数中提取引用水平

    python - Starmap 在传入参数之前修改参数?

    python - 如何使用 python 在 JSON 输出上显示所有字符串匹配

    python - 从另一个对象的变量设置一个对象的变量时奇怪的 Python 行为

    python - Sklearn set_params 正好接受 1 个参数?

    python - 用于无排名分类器(例如 OSVM)的 AUC-ROC

    r - 如何正确地将 `dput` 拟合线性模型(通过 `lm` )转换为 ASCII 文件并稍后重新创建?