【机器学习系列】【调参GridsearchCV】随机森林、GBDT、LightGBM和XGBoost调参顺序,外加一些加速调参的小技巧(主要介绍坐标下降)

本文将记录一下几个可以将模型参数分开进行调参的树形模型的调参顺序。以及几个能够加快调参速度的小技巧。如果有帮到你,帮懒羊羊点个赞,关注一下我呗。

1.GridSearchCV简介、好处和弊端

1.1简介

1.1.1简单示例

1.1.2参数说明

1.1.3 属性

1.2GridsearchCV的好处和弊端

2.调参顺序

2.1调参加速小技巧

2.1随机森林、GBDT、LightGBM和XGBoost调参顺序

1.1简介

最为常见的调参方法就是使用网格搜索+交叉验证进行参数的优化(GridsearchCV)

GridSearchCV的sklearn官方网址:

 from sklearn import tree
 clf = tree.DecisionTreeClassifier(class_weight='balanced')
 #自动调参
tree_param_grid = {'criterion' : ["gini"],
                  'splitter': ["random"],
                  'max_depth' : range(5,30,5),
                  'min_samples_split': range(10,210,50),
                  'min_samples_leaf': [5,10],
                  }

tree_best = GridSearchCV(clf,param_grid = tree_param_grid,cv = 3,scoring="roc_auc",n_jobs= -1, verbose = 100)
#进行网格搜索交叉验证调参
tree_best.fit(feature_train,target_train)
print(tree_best.best_estimator_)
print(tree_best.best_params_,"  ","得分:",tree_best.best_score_)
y_predict = tree_best.predict(feature_test)     # 进行预测
y_prob = tree_best.predict_proba(feature_test)     # 进行预测

输出示例:
Fitting 3 folds for each of 40 candidates, totalling 120 fits DecisionTreeClassifier(class_weight=’balanced’, max_depth=15, min_samples_leaf=5, min_samples_split=160, splitter=’random’)
{‘criterion’: ‘gini’, ‘max_depth’: 15, ‘min_samples_leaf’: 5, ‘min_samples_split’: 160, ‘splitter’: ‘random’} 得分: 0.9651868978885353

class sklearn.model_selection.GridSearchCV(estimator, param_grid, scoring=None, fit_params=None, n_jobs=1, iid=True, refit=True, cv=None, verbose=0, pre_dispatch=’2*n_jobs’, error_score=’raise’, return_train_score=’warn’)

(1) estimator

选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。以随机森林为例,初始化一个带有你能尽可能先确定的参数的RandomForestClassifier:estimator=RandomForestClassifier(min_samples_split=100,min_samples_leaf=20,max_depth=8,max_features=’sqrt’,random_state=10),

(2) param_grid

需要最优化的参数的取值,值为字典或者列表,例如:param_grid =tree_param_grid ,tree_param_grid = {‘criterion’ : [“gini”],
‘splitter’: [“random”],
‘max_depth’ : range(5,30,5),
‘min_samples_split’: range(10,210,50),
‘min_samples_leaf’: [5,10],
}

(3) scoring=None

模型评价标准,默认None,这时需要使用score函数;或者如scoring=’roc_auc’.

可选:

Scoring

Function

Comment

Classification

‘accuracy’

‘balanced_accuracy’

‘top_k_accuracy’

‘average_precision’

‘neg_brier_score’

‘f1’

for binary targets

‘f1_micro’

micro-averaged

‘f1_macro’

macro-averaged

‘f1_weighted’

weighted average

‘f1_samples’

by multilabel sample

‘neg_log_loss’

requires predict_proba support

‘precision’ etc.

suffixes apply as with ‘f1’

‘recall’ etc.

suffixes apply as with ‘f1’

‘jaccard’ etc.

suffixes apply as with ‘f1’

‘roc_auc’

‘roc_auc_ovr’

‘roc_auc_ovo’

‘roc_auc_ovr_weighted’

‘roc_auc_ovo_weighted’

Clustering

‘adjusted_mutual_info_score’

‘adjusted_rand_score’

‘completeness_score’

‘fowlkes_mallows_score’

‘homogeneity_score’

‘mutual_info_score’

‘normalized_mutual_info_score’

‘rand_score’

‘v_measure_score’

Regression

‘explained_variance’

‘max_error’

‘neg_mean_absolute_error’

‘neg_mean_squared_error’

‘neg_root_mean_squared_error’

‘neg_mean_squared_log_error’

‘neg_median_absolute_error’

‘r2’

‘neg_mean_poisson_deviance’

‘neg_mean_gamma_deviance’

‘neg_mean_absolute_percentage_error’

(4) fit_params=None

(5) n_jobs=1

n_jobs: 并行数,int:个数,-1:跟CPU核数一致(即使用全部cpu进行模型训练), 1:默认值

(6) iid=True

iid:默认True,为True时,默认为各个样本fold概率分布一致,误差估计为所有样本之和,而非各个fold的平均。

(7) refit=True

默认为True,程序将会以交叉验证训练集得到的最佳参数,重新对所有可用的训练集与开发集进行,作为最终用于性能评估的最佳模型参数。即在搜索参数结束后,用最佳参数结果再次fit一遍全部数据集。

(8) cv=None

交叉验证参数,默认None,使用三折交叉验证。指定fold数量,默认为3,也可以是yield训练/测试数据的生成器。

(9) verbose=0, scoring=None

verbose:日志冗长度,int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出。

(10) pre_dispatch=’2*n_jobs’

指定总共分发的并行任务数。当n_jobs大于1时,数据将在每个运行点进行复制,这可能导致OOM,而设置pre_dispatch参数,则可以预先划分总共的job数量,使数据最多被复制pre_dispatch次

(11) error_score=’raise’

(12) return_train_score=’warn’

如果”False”,cv_results_属性将不包括训练分数

回到sklearn里面的GridSearchCV,GridSearchCV用于系统地遍历多种参数组合,通过交叉验证确定最佳效果参数。

1 cv_results_ : dict of numpy (masked) ndarrays

具有键作为列标题和值作为列的dict,可以导入到DataFrame中。

2 best_estimator_ : estimator

通过搜索选择的估计器,即在左侧数据上给出最高分数(或指定的最小损失)的估计器。 如果 refit = False,则不可用。

这个属性可以作为下一轮调参时的输入estimator。这是一个快速构建下一轮调参的小技巧。

3 best_score_ : floatbest_estimator的分数

4 best_params_ : dict在保存数据上给出最佳结果的参数设置

5 best_index_ : int对应于最佳候选参数设置的索引(cv_results_数组)。
search.cv_results _ [‘params’] [search.best_index_]中的dict给出了最佳模型的参数设置,给出了最高的平均分数(search.best_score_)。

6 scorer_ : function

Scorer function used on the held out data to choose the best parameters for the model.

7 n_splits_ : int

The number of cross-validation splits (folds/iterations).

(8)grid_scores_:给出不同参数情况下的评价结果

1.2GridsearchCV的好处和弊端

好处:

(1)一定会在给出的超参数集上给出最优参数解,不会陷入局部最优;

(2)理解起来比较容易

弊端:

(1)数据集一大,参数一多,调参所需时间复杂度就指数级上升,而许多模型的参数就是会很多。

树形模型的参数都比较多,如果使用在一轮gridsearchcv里将所有参数进行调参,会指数级提升运算复杂度,有可能一两天还调不出来一个随机森林的参数。因此将某些需要首先在一起调参的参数在一轮中调参,其他没有必要一起调参的参数或没有必要优先进行调参的参数在另一轮进行调整,以此类推,能够指数级节约调参时间。这一调参方法也被成称为数据量比较大的时候可以使用一个快速调优的方法——坐标下降,是一种贪心算法:拿当前对模型影响最大的参数调优,直到最优化;再拿下一个影响最大的参数调优,如此下去,直到所有的参数调整完毕。

2.1调参加速小技巧

(1)利用gridsearchcv的 best_estimator_ 属性。目前网上的很多代码都是先进行一轮调参,找到最优参数后再使用这一轮调参的最优参数构建新的estimator,然后进行下一轮调参,这在实际操作中非常不方便,代码不具备可重用性,并且每次训练都要重新进行参数的设置。利用 best_estimator_属性可以快速建立下一轮的调参,并且不用先查看上一轮的最优参数在进行估计器的构建。

(2)更改GridsearchcCV()参数cv。cv越小,进行交叉验证的次数越少,将cv改小可以减少寻优次数,个人实验证明在树形模型下,cv=3和cv=10的效果差不多,但不同的数据集可能有不同的结果。

(3)使用 sklearn.model_selection.RandomizedSearchCV替代GridsearchCV。引入随机性,对参数寻优进行随机搜索。RandomizedSearchCV的参数和属性与GridsearchCV几乎一样。

考察其源代码,其搜索策略如下:
(a)对于搜索范围是distribution的超参数,根据给定的distribution随机采样;
(b)对于搜索范围是list的超参数,在给定的list中等概率采样;
(c)对a、b两步中得到的n_iter组采样结果,进行遍历。

但这一方法有可能会使参数寻优陷入局部最优解,但实践中基本上没有很大区别。

2.1随机森林、GBDT、LightGBM和XGBoost调参顺序

随机森林:

比较重要的几个参数的调参顺序如下:

n_estimators–>min_samples_split–>max_features–>max_depth

#随机森林
def my_randomforest(feature_train,target_train,feature_test,target_test):
    from sklearn import ensemble
    rf = ensemble.RandomForestClassifier(class_weight='balanced')

    rf_param_grid1 = {'n_estimators':[100,200,400,800,1000,1200,1500],}
    rf_best = GridSearchCV(rf,param_grid = rf_param_grid1,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    rf_best.fit(feature_train,target_train)
    print(type(rf_best.best_params_))

    rf_param_grid2 = {'min_samples_split':range(30,111,20)}
    rf_best2 = GridSearchCV(rf_best.best_estimator_,param_grid = rf_param_grid2,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    rf_best2.fit(feature_train,target_train)

    rf_param_grid3 = {'max_features':range(5,76,10),}
    rf_best3 = GridSearchCV(rf_best.best_estimator_,param_grid = rf_param_grid3,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    rf_best3.fit(feature_train,target_train)

    rf_param_grid4 = {'max_depth':range(3,22,3)}
    rf_best4 = GridSearchCV(rf_best.best_estimator_,param_grid = rf_param_grid6,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)

    rf_best4.fit(feature_train,target_train)
    print(rf_best4.best_estimator_)
    print(rf_best4.best_params_,"  ","得分:",rf_best4.best_score_)
    y_predict = rf_best4.predict(feature_test)     # 进行预测
    y_prob = rf_best4.predict_proba(feature_test)     # 进行预测
    result_evaluation(target_test,y_prob,y_predict)
    return rf_best6.best_params_,rf_best6,y_prob

gbdt:

比较重要的几个参数的调参顺序如下:

n_estimators–>max_depth和min_samples_split–>min_samples_split和min_samples_leaf–>max_features–>subsample->learning_rate

#GBDT
#https://blog.csdn.net/olizxq/article/details/89222908
def my_gbdt(feature_train,target_train,feature_test,target_test):
    from sklearn.ensemble import GradientBoostingClassifier
    gbdt = GradientBoostingClassifier()

    gbdt_param_grid1 = {'n_estimators':[50,100,200,400,800],}
    gbdt_best = GridSearchCV(gbdt,param_grid = gbdt_param_grid1,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    gbdt_best.fit(feature_train,target_train)

    gbdt_param_grid2 = {'max_depth':[5,10,15,20,25],
               'min_samples_split':range(100,801,200)}
    gbdt_best2 = GridSearchCV(gbdt_best.best_estimator_,param_grid = gbdt_param_grid2,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    gbdt_best2.fit(feature_train,target_train)

    gbdt_param_grid3 = {'min_samples_split':range(300,1701,200),
               'min_samples_leaf':range(60,101,10)}
    gbdt_best3 = GridSearchCV(gbdt_best2.best_estimator_,param_grid = gbdt_param_grid3,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    gbdt_best3.fit(feature_train,target_train)

    gbdt_param_grid4 = {'max_features':range(7,20,2)}
    gbdt_best4 = GridSearchCV(gbdt_best3.best_estimator_,param_grid = gbdt_param_grid4,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    gbdt_best4.fit(feature_train,target_train)

    gbdt_param_grid5 = {'subsample':[0.6,0.7,0.75,0.8,0.85,0.9]}
    gbdt_best5 = GridSearchCV(gbdt_best4.best_estimator_,param_grid = gbdt_param_grid5,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    gbdt_best5.fit(feature_train,target_train)

    gbdt_param_grid6 = {'learning_rate':[0.001,0.01,0.1,0.25]}
    gbdt_best6 = GridSearchCV(gbdt_best5.best_estimator_,param_grid = gbdt_param_grid6,cv = 3,scoring="roc_auc",n_jobs= -1, verbose=100)
    gbdt_best6.fit(feature_train,target_train)

    print(gbdt_best6.best_estimator_)
    print(gbdt_best6.best_params_,"  ","得分:",gbdt_best6.best_score_)
    y_predict = gbdt_best6.predict(feature_test)     # 进行预测
    y_prob = gbdt_best6.predict_proba(feature_test)     # 进行预测
    result_evaluation(target_test,y_prob,y_predict)

    return gbdt_best6.best_params_,gbdt_best6,y_prob

LightGBM就不给代码示例了,顺序是:

n_estimators–>max_depth和min_samples_split–>min_samples_split和min_samples_leaf–>max_features–>subsample->learning_rate

XGBoost就不给代码示例了,顺序是:

n_estimators–>max_depth和min_child_weight–>gamma–>subsample–>reg_alpha–>learning_rate

Original: https://blog.csdn.net/standingflower/article/details/124562971
Author: 学金融的程序员懒羊羊
Title: 【机器学习系列】【调参GridsearchCV】随机森林、GBDT、LightGBM和XGBoost调参顺序,外加一些加速调参的小技巧(主要介绍坐标下降)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/615013/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球