集成学习_XGBoost
概述
eg:
对于一个问题,INPUT X: age, gender, occupation, ....
Target y: How does the person like computer games?
image-20220212182416599.png如上图,基学习器采用CART回归树。
微信截图_20220214101756.png
如上图,每个叶子节点对应预测的分数。
XGBoost的分裂节点算法
贪心方法
-
贪心方法,获取最优分割节点(split point)将所有样本按照gi从小到大排序,通过遍历,查看每个节点是否需要分割
-
对于特征值的个数为n时,总共有n−1种划分
-
Step1,对样本扫描一遍,得出GL,GR
-
Step2,根据Gain的分数进行分割
-
-
通过贪心法,计算效率得到大幅提升,XGBoost重新定义划分属性,即Gain,而Gain的计算是由目标损失函数obj决定的
近似算法
-
对于连续型特征值,样本数量非常大。该特征取值过多时,遍历所有取值会花费很多时间,且容易过拟合
-
方法: 在寻找split节点的时候,不会枚举所有的特征值,而会对特征值进行聚合统计,然后
-
形成若干个bucket(桶),只将bucket边界上的特征值作为split节点的候选,从而获得性能提升
-
从算法伪代码中该流程还可以分为两种,全局的近似是在新生成一棵树之前就对各个特征计算分位点并划分样本,之后在每次分裂过程中都采用近似划分,而局部近似就是在具体的某一次分裂节点的过程中采用近似算法。
XGBoost算法特点
XGBoost将树模型的复杂度加入到正则项中,从而避免过拟合,泛化性能好
损失函数是用泰勒展开式展开的,用到了一阶导和二阶导,可以加快优化速度
在寻找最佳分割点时,采用近似贪心算法,用来加速计算
不仅支持CART作为基分类器,还支持线性分类器,在使用线性分类器的时候可以使用L1,L2正则化
支持并行计算,XGBoost的并行是基于特征计算的并行,将特征列排序后以block的形式存储在内存中,在后面的迭代中重复使用这个结构。
在进行节点分裂时,计算每个特征的增益,选择增益最大的特征作为分割节点,各个特征的增益计算可以使用多线程并行
优点:速度快、效果好、能处理大规模数据、支持自定义损失函数等
缺点:算法参数过多,调参复杂,不适合处理超高维特征数据
XGBoost工具
参数分为:
-
通用参数:对系统进行控制
-
Booster参数:控制每一步的booster(tree/regression)
-
学习目标参数:控制训练目标的表现
通用参数
-
booster,模型选择,gbtree或者gblinear。gbtree使用基于树的模型进行提升计算,gblinear使用线性模型进行提升计算。[default=gbtree]
-
silent,缄默方式,0表示打印运行时,1表示以缄默方式运行,不打印运行时信息。[default=0]
-
nthread,XGBoost运行时的线程数,[default=缺省值是当前系统可以获得的最大线程数] num_feature,boosting过程中用到的特征个数,XGBoost会自动设置
Booster参数
-
eta [default=0.3],为了防止过拟合,更新过程中用到的收缩步长。在每次提升计算之后,算法会直接获得新特征的权重。 eta通过缩减特征的权重使提升计算过程更加保守,取值范围为[0,1]
-
gamma [default=0],分裂节点时,损失函数减小值只有大于等于gamma节点才分裂,gamma值越大,算法越保守,越不容易过拟合,但性能就不一定能保证,需要trade off,取值范围 [0,∞]
-
max_depth [default=6] ,树的最大深度,取值范围为[1,∞],典型值为3-10
-
min_child_weight [default=1],一个子集的所有观察值的最小权重和。如果新分裂的节点的样本权重和小于min_child_weight则停止分裂 。这个可以用来减少过拟合,但是也不能太高,会导致欠拟合,取值范围为[0,∞]
- image-20220212183959420.png
-
subsample [default=1],构建每棵树对样本的采样率,如果设置成0.5,XGBoost会随机选择50%的样本作为训练集
-
colsample_bytree [default=1],列采样率,也就是特征采样率
-
lambda [default=1, alias: reg_lambda],L2正则化,用来控制XGBoost的正则化部分
-
alpha [default=0, alias: reg_alpha],L1正则化,增加该值会让模型更加收敛
-
scale_pos_weight [default=1],在类别高度不平衡的情况下,将参数设置大于0,可以加快收敛
学习目标参数
-
objective [ default=reg:linear ],定义学习目标,reg:linear,reg:logistic,binary:logistic,binary:logitraw,count:poisson,multi:softmax,multi:softprob,rank:pairwise
-
eval_metric,评价指标,包括rmse,logloss,error,merror,mlogloss,auc,ndcg,map等
-
seed[ default=0 ],随机数的种子
-
dtrain,训练的数据
-
num_boost_round,提升迭代的次数,也就是生成多少基模型
-
early_stopping_rounds,早停法迭代次数
-
evals:这是一个列表,用于对训练过程中进行评估列表中的元素。形式是evals = [(dtrain,'train'),(dval,'val')]或者是evals = [(dtrain,'train')],对于第一种情况,它使得我们可以在训练过程中观察验证集的效果
-
verbose_eval ,如果为True,则对evals中元素的评估输出在结果中;如果输入数字,比如5,则每隔5个迭代输出一次
-
learning_rates:每一次提升的学习率的列表
代码参考
X_train, X_valid, y_train, y_valid = train_test_split(train_X, train_y, test_size=.2)
# 使用XGBoost
model = xgb.XGBClassifier(
max_depth=8, #树的最大深度
n_estimators=1000, #提升迭代的次数,也就是生成多少基模型
min_child_weight=300, #一个子集的所有观察值的最小权重和
colsample_bytree=0.8, #列采样率,也就是特征采样率
subsample=0.8, #构建每棵树对样本的采样率
eta=0.3, # eta通过缩减特征的权重使提升计算过程更加保守,防止过拟合
seed=42 #随机数种子
)
model.fit(
X_train, y_train,
eval_metric='auc', eval_set=[(X_train, y_train), (X_valid, y_valid)],
verbose=True,
#早停法,如果auc在10epoch没有进步就stop
early_stopping_rounds=10
)
model.fit(X_train, y_train)
prob = model.predict_proba(test_data)
官方代码
# 模型参数配置
param = {'boosting_type':'gbdt',
'objective' : 'binary:logistic', #任务目标
'eval_metric' : 'auc', #评估指标
'eta' : 0.01, #学习率
'max_depth' : 15, #树最大深度
'colsample_bytree':0.8, #设置在每次迭代中使用特征的比例
'subsample': 0.9, #样本采样比例
'subsample_freq': 8, #bagging的次数
'alpha': 0.6, #L1正则
'lambda': 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)
train_data = xgb.DMatrix(X_train, label=y_train)
valid_data = xgb.DMatrix(X_valid, label=y_valid)
test_data = xgb.DMatrix(test)
model = xgb.train(param, train_data, evals=[(train_data, 'train'), (valid_data, 'valid')], num_boost_round = 10000, early_stopping_rounds=200, verbose_eval=25)
predict = model.predict(test_data)
test['Attrition']=predict
# 转化为二分类输出
test['Attrition']=test['Attrition'].map(lambda x:1 if x>=0.5 else 0)
test[['Attrition']].to_csv('submit_lgb.csv')