鄙人调参新手,最近用lightGBM有点猛,无奈在各大博客之间找不到具体的调参方法,于是将自己的调参notebook打印成markdown出来,希望可以跟大家互相学习。
其实,对于基于决策树的模型,调参的方法都是大同小异。一般都需要如下步骤:
首先选择较高的学习率,大概0.1附近,这样是为了加快收敛的速度。这对于调参是很有必要的。
对决策树基本参数调参
正则化参数调参
最后降低学习率,这里是为了最后提高准确率
所以,下面的调参例子是基于上述步骤来操作。数据集为一个(4400+, 1000+)的数据集,全是数值特征,metric采用均方根误差。
(PS:还是吐槽一下,lightgbm参数的同义词(alias)实在是太多了,有时候不同的参数但同一个意思的时候真的很困扰,下面同义的参数我都用/划开,方便查看。)
Step1. 学习率和估计器及其数目
不管怎么样,我们先把学习率先定一个较高的值,这里取 learning_rate = 0.1,其次确定估计器boosting/boost/boosting_type的类型,不过默认都会选gbdt。
为了确定估计器的数目,也就是boosting迭代的次数,也可以说是残差树的数目,参数名为n_estimators/num_iterations/num_round/num_boost_round。我们可以先将该参数设成一个较大的数,然后在cv结果中查看最优的迭代次数,具体如代码。
在这之前,我们必须给其他重要的参数一个初始值。初始值的意义不大,只是为了方便确定其他参数。下面先给定一下初始值:
以下参数根据具体项目要求定:
'boosting_type'/'boosting': 'gbdt'
'objective': 'regression'
'metric': 'rmse'
以下参数我选择的初始值,你可以根据自己的情况来选择:
'max_depth': 6 ### 根据问题来定咯,由于我的数据集不是很大,所以选择了一个适中的值,其实4-10都无所谓。
'num_leaves': 50 ### 由于lightGBM是leaves_wise生长,官方说法是要小于2^max_depth
'subsample'/'bagging_fraction':0.8 ### 数据采样
'colsample_bytree'/'feature_fraction': 0.8 ### 特征采样
下面我是用LightGBM的cv函数进行演示:
params = {
'boosting_type': 'gbdt',
'objective': 'regression',
'learning_rate': 0.1,
'num_leaves': 50,
'max_depth': 6,
'subsample': 0.8,
'colsample_bytree': 0.8,
}
data_train = lgb.Dataset(df_train, y_train, silent=True)
cv_results = lgb.cv(
params, data_train, num_boost_round=1000, nfold=5, stratified=False, shuffle=True, metrics='rmse',
early_stopping_rounds=50, verbose_eval=50, show_stdv=True, seed=0)
print('best n_estimators:', len(cv_results['rmse-mean']))
print('best cv score:', cv_results['rmse-mean'][-1])
[50]cv_agg's rmse: 1.38497 + 0.0202823
best n_estimators: 43
best cv score: 1.3838664241
由于我的数据集不是很大,所以在学习率为0.1时,最优的迭代次数只有43。那么现在,我们就代入(0.1, 43)进入其他参数的tuning。但是还是建议,在硬件条件允许的条件下,学习率还是越小越好。
Step2. max_depth 和 num_leaves
这是提高精确度的最重要的参数。
max_depth :设置树深度,深度越大可能过拟合
num_leaves:因为 LightGBM 使用的是 leaf-wise 的算法,因此在调节树的复杂程度时,使用的是 num_leaves 而不是 max_depth。大致换算关系:num_leaves = 2^(max_depth),但是它的值的设置应该小于 2^(max_depth),否则可能会导致过拟合。
我们也可以同时调节这两个参数,对于这两个参数调优,我们先粗调,再细调:
这里我们引入sklearn里的GridSearchCV()函数进行搜索。不知道怎的,这个函数特别耗内存,特别耗时间,特别耗精力。
from sklearn.model_selection import GridSearchCV
### 我们可以创建lgb的sklearn模型,使用上面选择的(学习率,评估器数目)
model_lgb = lgb.LGBMRegressor(objective='regression',num_leaves=50,
learning_rate=0.1, n_estimators=43, max_depth=6,
metric='rmse', bagging_fraction = 0.8,feature_fraction = 0.8)
params_test1={
'max_depth': range(3,8,2),
'num_leaves':range(50, 170, 30)
}
gsearch1 = GridSearchCV(estimator=model_lgb, param_grid=params_test1, scoring='neg_mean_squared_error', cv=5, verbose=1, n_jobs=4)
gsearch1.fit(df_train, y_train)
gsearch1.grid_scores_, gsearch1.best_params_, gsearch1.best_score_
Fitting 5 folds for each of 12 candidates, totalling 60 fits
[Parallel(n_jobs=4)]: Done 42 tasks | elapsed: 2.0min
[Parallel(n_jobs=4)]: Done 60 out of 60 | elapsed: 3.1min finished
([mean: -1.88629, std: 0.13750, params: {'max_depth': 3, 'num_leaves': 50},
mean: -1.88629, std: 0.13750, params: {'max_depth': 3, 'num_leaves': 80},
mean: -1.88629, std: 0.13750, params: {'max_depth': 3, 'num_leaves': 110},
mean: -1.88629, std: 0.13750, params: {'max_depth': 3, 'num_leaves': 140},
mean: -1.86917, std: 0.12590, params: {'max_depth': 5, 'num_leaves': 50},
mean: -1.86917, std: 0.12590, params: {'max_depth': 5, 'num_leaves': 80},
mean: -1.86917, std: 0.12590, params: {'max_depth': 5, 'num_leaves': 110},
mean: -1.86917, std: 0.12590, params: {'max_depth': 5, 'num_leaves': 140},
mean: -1.89254, std: 0.10904, params: {&