OOF的问题
在Bayesian Optimization或者Grid Search调参时,通常会结合交叉验证OOF来找到最优的参数。
OOF会利用K-Fold训练K个模型,最后计算每个模型在验证集上的metrics。
lgb在做OOF的时候,每个模型都有自己的early stopping,会有一定的过拟合。如果后面还要做Stacking,会影响最终模型的精度。
什么是lgb.cv
lightgbm.cv()
会同时在每个round训练K个模型,并记录每个round中最优的模型的metric。这样指定的early stopping通常会更早停止,这样避免过拟合,而且训练速度会更快一些。
除了lightgbm,也有xgboost.cv
catboost.cv
等等。
lgb.cv
例子
需要提取准备的包括:
kf
: K Fold,可以是sklearn.model_selection.KFold
或者sklearn.model_selection.StratifiedKFold
num_boost_round
:因为有early stopping,可以设置的比较大early_stopping_rounds
data_train
:lgb的训练集params
参数
from sklearn.model_selection import KFold
import lightgbm as lgb
# K Fold
kf = KFold(5, shuffle=True, random_state=0)
# 有early stopping, num_boost_round一般会设置比较大
num_boost_round = 100000
early_stopping_rounds = 100
# 训练集
data_train = lgb.Dataset(x_train, label=y_train)
# params
params = {
'boosting_type': 'gbdt',
"objective" : "xxx",
'max_depth' : xxx,
...
}
通过lgb.cv
找到最优的round。lgb.cv
的返回值history
的类别是dict
。它的key是metric的名字,value是每个round的最优模型的metric记录值。
history = lgb.cv(params, data_train,
num_boost_round=num_boost_round,
folds=kf, metrics=xxx,
early_stopping_rounds=early_stopping_rounds,
verbose_eval=xxx,
show_stdv=True, # 显示metric的标准差
seed=0)
# 最佳round,具体名字和metric有关
best_round = np.argmax(history['xxx-mean'])
# 避免最坏情况
if best_round == 0:
best_round = 1
最终训练的模型固定最大的round,不设置early stopping
bst = lgb.train(param, data_train, num_boost_round=best_round,
verbose_eval=None,
early_stopping_rounds=None,
)