xgboost,GBDT在广告中的应用:
把用户和广告提出特征来,做组合,例如:男性&IT类, 统计这个类型下的点击率;来一个新样本,对应在这个特征上的点击率,作为一个特征值; 所有特征值就是GBDT输入特征向量;
GBDT的目标:最小化平方误差损失函数L=
残差版本:把拆分成
, L转化为:
;即每个弱分类器
只需要拟合残差
即可;
梯度下降版本:视为自变量,L视为因变量,所有样本i的dL/d
构成的向量,就是梯度方向;即
沿着该梯度方向的反方向进行变化可最大程度减少误差;即
=
- 梯度*步长;即所有样本i的
需要拟合样本i的梯度*步长;
关于以上两个版本的对比:残差版本拟合的是全局最优值;梯度下降版本拟合的是向局部最优迈进的一步;前者最大问题是,由于它依赖残差,cost function一般固定为反映残差的均方差,因此很难处理纯回归问题之外的问题。而后者求解方法为梯度下降,只要可求导的cost function都可以使用。
梯度下降版本的损失函数是平方损失函数时,梯度值就是残差(此时两个版本等价)。
GBDT要用CART树去拟合所有样本的残差(或者梯度);CART树是回归树;每个节点会有一个叶子值,最终拟合误差是所有样本(y[i]-叶子值)^2之和;
建树用的还是贪心法:每个中间节点,对所有特征的所有分界点进行“试分”,即试着分成左右两个子节点,每个子节点选择使得自己节点内所有样本的均方误差最小的叶子值(也就是样本均值,用求导等于0求解得到的),计算一遍左右子节点的总误差;最终选择使这个总误差最小的划分;
2014年Facebook的paper (GBDT+LR): 把GBDT的输出作为稀疏特征,输入到LR;
把损失函数拆成2部分: ;
视为x,
视为
x, 套入到f(x+
x)的二阶泰勒展开,得到关于L(
)的一阶导和二阶导和
的一次项和二次项的式子,再加上所有叶子值得平方正则项;把
使用样本落在的最终叶子上得叶子值w[k]来代替,可以转化为关于每个w[k]做未知数得二次方程,求解二次方程的最优自变量值(可以用求导等于0,也可使用初中的公式),得到每个w[k]的最优取值,带入方程得到该叶子节点对应的最优L。
建树的时候,每次划分使用贪心策略,即找在当前一分二能得到的最小误差,而不管最终的全局误差;具体实现是枚举所有特征,每次对父节点的所有样本,在该特征上进行排序,每次累加左子树(累减右子树)的一阶导项G[i]和二阶导项H[i],计算左右子树误差和;最终取所有特征所有划分里误差最小的那个划分点即可;(G[i]和H[i]们,不取决于特征,只和上次回归结果有关,所以在计算本轮弱分类器之前就先计算好)
xgboost和GBDT的区别:
1)将树模型的复杂度加入到正则项中,来避免过拟合,因此泛化性能会优于GBDT。
2)损失函数是用泰勒展开式展开的,同时用到了一阶导和二阶导,可以加快优化速度。
3)和GBDT只支持CART作为基分类器之外,还支持线性分类器,在使用线性分类器的时候可以使用L1,L2正则化。
4)引进了特征子采样,像RandomForest那样,这种方法既能降低过拟合,还能减少计算。
5)在寻找最佳分割点时,考虑到传统的贪心算法效率较低,实现了一种近似贪心算法,用来加速和减小内存消耗,除此之外还考虑了稀疏数据集和缺失值的处理,对于特征的值有缺失的样本,XGBoost依然能自动找到其要分裂的方向。
6)XGBoost支持并行处理,XGBoost的并行不是在模型上的并行,而是在特征上的并行,将特征列排序后以block的形式存储在内存中,在后面的迭代中重复使用这个结构。这个block也使得并行化成为了可能,其次在进行节点分裂时,计算每个特征的增益,最终选择增益最大的那个特征去做分割,那么各个特征的增益计算就可以开多线程进行。
xgboost在训练之前,预先对数据进行排序,然后保存block结构,后面的迭代中重复的使用这个结构,大大减小计算量。这个block结构也使得并行称为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
人家也用了2种方法:1. 按本特征值排序,顺序扫描,精细化找split点;2.直方图,按特征值的分布进行分桶,最后桶们aggregate,再顺序扫桶找split点(适用于多机分布式并行)
所有特征是训练刚开始的时候排序的,建好指向原始样本的索引;树的每层,只扫描一遍索引,该样本属于哪个叶子就更新哪个叶子;所有特征可以多机多线程并行扫描;
缺失值的处理:先把该特征上的所有缺失值的样本算作右子树,扫一遍;再全都算作左子树,扫一遍;2组score连起来求最优即可;
他也意识到了,数据集大到让操作系统文件缓存不够用(排空),才能精确测试I/O性能!
使用xgboost做二分类任务:
样本在所有树的叶子节点值之加权和,要经过sigmoid函数,得到(0,1)范围的预测值;
损失函数就是极小化"负对数似然函数", 也叫交叉熵损失函数;式子里的y[i]是{0,1}取值的label, 是(-
,+
)范围的叶子节点值;
其他步骤和回归任务完全一样:将该损失函数对 求一阶导和二阶导,得到g[i]和h[i],本子树要拟合的w[i],带入泰勒展开式子,得到最优w[i]取值和对应的最优L值;枚举所有特征的所有划分点,得到最最优的划分和左右子树的w[i]取值;最终样本们分到哪个叶子节点,就用哪个w做自己的y[t][i]; y[i] = y[t-1][i] + y[t][i]; y[i]经过sigmoid函数可得(0,1)的分类概率;
做多分类任务:对于k分类问题,每一轮迭代中,是构建了k个树,每一颗树的预测值代表对每个分类的打分,记为fk(x),那么其loss就是对应的softmax的loss。(某个样本,它在k组树的打分之加权和,就是它的k个类的打分, 把这k个打分经过softmax函数得到k个概率值就是分类结果)(损失函数用的还是极小化"负对数似然函数")