集成学习_LightGBM
2017年经微软推出,XGBoost的升级版 Light => 在大规模数据集上运行效率更高 GBM => Gradient Boosting Machine
Motivation
常用的机器学习算法,例如神经网络等算法,都可以以mini-batch的方式训练,训练数据的大小不会受到内存限制
GBDT在每一次迭代的时候,都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小;
如果不装进内存,反复地读写训练数据又会消耗非常大的时间。对于工业级海量的数据,普通的GBDT算法是不能满足其需求的
LightGBM的提出是为了解决GBDT在海量数据遇到的问题,让GBDT可以更好更快地用于工业场景
LightGBM与XGBoost比较
模型精度:两个模型相当
训练速度:LightGBM训练速度更快 => 1/10
内存消耗:LightGBM占用内存更小 => 1/6
特征缺失值:两个模型都可以自动处理特征缺失值
分类特征:XGBoost不支持类别特征,需要对其进行OneHot编码,而LightGBM支持分类特征
XGBoost模型的复杂度
-
模型复杂度 = 树的棵数 X 每棵树的叶子数量 X 每片叶子生成复杂度
-
每片叶子生成复杂度 = 特征数量 X 候选分裂点数量 X 样本的数量
-
针对XGBoost的优化:
-
Histogram算法,直方图算法 => 减少候选分裂点数量
-
GOSS算法,基于梯度的单边采样算法 => 减少样本的数量
-
EFB算法,互斥特征捆绑算法 => 减少特征的数量
-
LightGBM = XGBoost + Histogram + GOSS + EFB
XGBoost的预排序(pre-sorted)算法
-
将样本按照特征取值排序,然后从全部特征取值中找到最优的分裂点位
-
预排序算法的候选分裂点数量=样本特征不同取值个数减1
eg: i列中x_i、g_i、h_i分别对应原函数、一阶导、二阶导
i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
---|---|---|---|---|---|---|---|---|
x_i | 0.1 | 2.1 | 2.5 | 3.0 | 3.0 | 4.0 | 4.5 | 5.0 |
g_i | 0.01 | 0.03 | 0.06 | 0.05 | 0.04 | 0.7 | 0.6 | 0.07 |
h_i | 0.2 | 0.04 | 0.05 | 0.02 | 0.08 | 0.02 | 0.03 | 0.03 |
LightGBM的Histogram算法
-
替代XGBoost的预排序算法
-
思想是先连续的浮点特征值离散化成k个整数,同时构造一个宽度为k的直方图,即将连续特征值离散化到k个bins上(比如k=255)
-
当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点
-
XGBoost需要遍历所有离散化的值,LightGBM只要遍历k个直方图的值
-
候选分裂点数量 = k-1
GOSS算法
-
Gradient-based One-Side Sampling,基于梯度的单边采样算法
-
思想是通过样本采样,减少目标函数增益Gain的计算复杂度
-
单边采样,只对梯度绝对值较小的样本按照一定
-
比例进行采样,而保留了梯度绝对值较大的样本 因为目标函数增益主要来自于梯度绝对值较大的样本 => GOSS算法在性能和精度之间进行了很好的trade off
EFB算法
Exclusive Feature Bundling,互斥特征绑定算法
思想是特征中包含大量稀疏特征的时候,减少构建直方图的特征数量,从而降低计算复杂度
数据集中通常会有大量的稀疏特征(大部分为0,少量为非0)我们认为这些稀疏特征是互斥的,
即不会同时取非零值
EFB算法可以通过对某些特征的取值重新编码,将多个这样互斥的特征绑定为一个新的特征
类别特征可以转换成onehot编码,这些多个特征的onehot编码是互斥的,可以使用EFB将他们绑定为一个特征
在LightGBM中,可以直接将每个类别取值和一个bin关联,从而自动地处理它们,也就无需预处理成onehot编码
LightGBM工具
参数
-
boosting_type,训练方式,gbdt
-
objective,目标函数,可以是binary,regression
-
metric,评估指标,可以选择auc, mae,mse,binary_logloss,multi_logloss
-
max_depth,树的最大深度,当模型过拟合时,可以降低 max_depth
-
min_data_in_leaf,叶子节点最小记录数,默认20
-
lambda,正则化项,范围为0~1
-
min_gain_to_split,描述分裂的最小 gain,控制树的有用的分裂
-
max_cat_group,在 group 边界上找到分割点,当类别数量很多时,找分割点很容易过拟合时
-
num_boost_round,迭代次数,通常 100+
-
num_leaves,默认 31
-
device,指定cpu 或者 gpu
-
max_bin,表示 feature 将存入的 bin 的最大数量
-
categorical_feature,如果 categorical_features = 0,1,2, 则列 0,1,2是 categorical 变量 //与xgb的不同
-
ignore_column,与 categorical_features 类似,只不过不是将特定的列视为categorical,而是完全忽略
Bagging参数
-
bagging_fraction+bagging_freq(需要同时设置)
-
bagging_fraction,每次迭代时用的数据比例,用于加快训练速度和减小过拟合
-
bagging_freq:bagging的次数。默认为0,表示禁用bagging,非零值表示执行k次bagging,可以设置为3-5
-
feature_fraction,设置在每次迭代中使用特征的比例,例如为0.8时,意味着在每次迭代中随机选择80%的参数来建树
-
early_stopping_round,如果一次验证数据的一个度量在最近的round中没有提高,模型将停止训练
模型参数配置
param = {'boosting_type':'gbdt',
'objective' : 'binary', #任务类型
'metric' : 'auc', #评估指标
'learning_rate' : 0.01, #学习率
'max_depth' : 15, #树的最大深度
'feature_fraction':0.8, #设置在每次迭代中使用特征的比例
'bagging_fraction': 0.9, #样本采样比例
'bagging_freq': 8, #bagging的次数
'lambda_l1': 0.6, #L1正则
'lambda_l2': 0, #L2正则
}
模型训练,得出预测结果
X_train, X_valid, y_train, y_valid = train_test_split(train.drop('Attrition',axis=1), train['Attrition'], test_size=0.2, random_state=42)
trn_data = lgb.Dataset(X_train, label=y_train)
val_data = lgb.Dataset(X_valid, label=y_valid)
model = lgb.train(param,train_data,valid_sets=[train_data,valid_data],num_boost_round = 10000 ,early_stopping_rounds=200,verbose_eval=25, categorical_feature=attr)
predict=model.predict(test)
test['Attrition']=predict
# 转化为二分类输出
test['Attrition']=test['Attrition'].map(lambda x:1 if x>=0.5 else 0)
test[['Attrition']].to_csv('submit_lgb.csv')
参数对比
xgb | lgb | XGBClassifier(xgb.sklearn) | LGBMClassifier(lgb.sklearn) |
---|---|---|---|
booster='gbtree' | boosting='gbdt' | booster='gbtree' | boosting_type='gbdt' |
objective='binary:logistic' | application='binary' | objective='binary:logistic' | objective='binary' |
max_depth=7 | num_leaves=2**7 | max_depth=7 | num_leaves=2**7 |
eta=0.1 | learning_rate=0.1 | learning_rate=0.1 | learning_rate=0.1 |
num_boost_round=10 | num_boost_round=10 | n_estimators=10 | n_estimators=10 |
gamma=0 | min_split_gain=0.0 | gamma=0 | min_split_gain=0.0 |
min_child_weight=5 | min_child_weight=5 | min_child_weight=5 | min_child_weight=5 |
subsample=1 | bagging_fraction=1 | subsample=1.0 | subsample=1.0 |
colsample_bytree=1.0 | feature_fraction=1 | colsample_bytree=1.0 | colsample_bytree=1.0 |
alpha=0 | lambda_l1=0 | reg_alpha=0.0 | reg_alpha=0.0 |
lambda=1 | lambda_l2=0 | reg_lambda=1 | reg_lambda=0.0 |
scale_pos_weight=1 | scale_pos_weight=1 | scale_pos_weight=1 | scale_pos_weight=1 |
seed | bagging_seed | ||
feature_fraction_seed | random_state=888 | random_state=888 | |
nthread | num_threads | n_jobs=4 | n_jobs=4 |
evals | valid_sets | eval_set | eval_set |
eval_metric | metric | eval_metric | eval_metric |
early_stopping_rounds | early_stopping_rounds | early_stopping_rounds | early_stopping_rounds |
verbose_eval | verbose_eval | verbose | verbose |
调参经验
LGBMClassifier经验参数
clf = lgb.LGBMClassifier(
num_leaves=2**5-1, reg_alpha=0.25, reg_lambda=0.25, objective='binary',
max_depth=-1, learning_rate=0.005, min_child_samples=3, random_state=2021,
n_estimators=2000, subsample=1, colsample_bytree=1,
)
'''
num_leavel=2**5-1 # 树的最大叶子数,对比XGBoost一般为2^(max_depth)
reg_alpha,L1正则化系数
reg_lambda,L2正则化系数
max_depth,最大树的深度
n_estimators,树的个数,相当于训练的轮数
subsample,训练样本采样率(行采样)
colsample_bytree,训练特征采样率(列采样)
'''
XGBoost VS LightGBM
XGBoost效果相对LightGBM可能会好一些
xgb = xgb.XGBClassifier(
max_depth=6, learning_rate=0.05, n_estimators=2000,
objective='binary:logistic', tree_method='gpu_hist',
subsample=0.8, colsample_bytree=0.8,
min_child_samples=3, eval_metric='auc', reg_lambda=0.5
)
'''
max_depth,树的最大深度
learning_rate, 学习率
reg_lambda,L2正则化系数
n_estimators,树的个数,相当于训练的轮数
objective,目标函数, binary:logistic 用于二分类任务
tree_method, 使用功能的树的构建方法,hist代表使用直方图优化的近似贪婪算法
subsample,训练样本采样率(行采样)
colsample_bytree,训练特征采样率(列采样)
subsample, colsample_bytree是个值得调参的参数,
典型的取值为0.5-1(取0.7效果可能更好)
模型参数调参:
n_estimatores:总共迭代的次数,即决策树的个数
early_stopping_rounds:
含义:在验证集上,连续n次迭代,分数没有提高,就终止训练
调参:防止overfitting
max_depth
含义:树的深度,默认值为6,典型值3-10
调参:值越大,越容易过拟合;值越小,越容易欠拟合
min_child_weight
含义:默认值为1
调参:值越大,越容易欠拟合;值越小,越容易过拟合(值较大时,避免模型学习到局部的特殊样本)
subsample
含义:训练每棵树时,使用的数据占全部训练集的比例。默认值为1,典型值为0.5-1
调参:防止overfitting
colsample_bytree
含义:训练每棵树时,使用的特征占全部特征的比例。默认值为1,典型值为0.5-1
调参:防止overfitting
learning_rate
含义:学习率,控制每次迭代更新权重时的步长,默认0.3
调参:值越小,训练越慢, 典型值为0.001-0.05
objective 目标函数
回归任务:reg:linear (默认),reg:logistic
二分类:
binary:logistic 概率 ,binary:logitraw 类别
多分类
multi:softmax num_class=n 返回类别
multi:softprob num_class=n 返回概率
eval_metric
回归任务(默认rmse):rmse--均方根误差,mae--平均绝对误差
分类任务(默认error)
auc--roc曲线下面积
error--错误率(二分类)
merror--错误率(多分类)
logloss--负对数似然函数(二分类)
mlogloss--负对数似然函数(多分类)
gamma,惩罚项系数,指定节点分裂所需的最小损失函数下降值
alpha,L1正则化系数,默认为1
lambda,L2正则化系数,默认为1
'''