集成学习
集成学习可以简单的理解为综合一些不是很好的学习模型,将他们整合起来,进行一个多数投票的方式来构架一个集成的框架进行学习训练处新的模型.当然,具体的集成学习方式并不是使用的多数投票
对于弱分类器而言,当某个模型对数据的分类效果不理想,但是总还是比随机分类强,那么这种模型多少还是有点分类效果,如果某个模型对某个类别区分效果很好,而对其他类别区分效果不行,那么集成学习就可以只让这个模型去区分分类效果好的类,其他的类交给其他模型去区分,从而完成对整个数据的分类
下面介绍常见的集成学习方式:
Bagging
名字的意思就是袋子,可以想象成从袋子中拿球,进行有放回的抽样
如果我们存在一个数据集D,而这个数据集的训练样本效果并不理想,那么我们就采用的有放回抽样的方式进行每次从D中取出N个样本组成一个新的数据集D1,利用这个D1数据进行训练得到一个模型M1
放回D1数据到D中,然后再次进行从D中抽取N个样本组成数据集D2,对这个数据D2进行数据训练,得到一个新的模型M2
重复上面的步骤k次,我们就会得到k个模型{M1,M2,M3…Mk}
存在k个模型的集合之后,如果有新的数据进来,那么将这个数据交给k个模型将会得到k个预测分类
1 可以利用多数投票的方式进行投票,如果这个k个模型中预测为A类的数量最多,那么就认为这个数据应该被分为A类
2 可以利用均值来判定结果,这是针对回归问题的预测
随机森林
bagging的原始方式中有放回的抽样存在一定的问题,每次取出的样本可能会有重复,对于某个数据而言,大多数样本还是属于是正常样本,离群的样本比较少,那么每次抽取还是抽到正常样本的可能性最高,因此所有子模型和将D直接用于训练的模型相似度还是比较高,考虑到所有模型的分类属性都是相同的,那么可不可以不采用全属性来训练模型,而是采用指定某几个属性来训练模型
某个模型要对数据的全部属性进行精准的区别划分往往比较困难,有些属性对某个类别的贡献度很高,有些属性对这个类别贡献几乎没有,那么将所有属性都放进模型进行原来就不太合适
因为是集成学习,我们只需要训练出来某个模型针对某个类别区分效果好就行了,而至于这个类别对其他类的区分效果如何根本不在意,其他类可以交给其他模型去区分.
那么如何才能选出合适的属性?这一点事先我们是不知道是哪个属性对哪个类别影响大的,不然那直接给权重就行了何必训练模型,既然不知道那么我们就可以换一种方式,原来bagging是用了全部的属性进行模型训练,现在随机森林 的做法是将属性进行随机选择,那么这就有一定的几率随机到某几个针对某个分类贡献度很大的属性,那么这个子模型对这个类别的区分度就会很高
那么其他的模型会不会影响到这个模型呢,其实不会,因为随机构成的模型足够多,其他模型在这个类别上的区分不足,造成结果预测为凌乱的其他类别,这就使得预测正确的比重会高于其他类,最后的结果就能能够有效的识别这种类
随机森林的步骤
1 从D集中选出n个样本构成子数据集D1,并放回样本
2 使用子数据D1训练模型,但是需要随机k个属性用作训练D1的特征属性
3 重复1和2num次
4 得到num个决策树形成的随机森林,将所有模型进行集成打包构成新模型,该模型输出结果采用多数投票形式
一些变种
Extra Tree
主要的思维与RF相同,实际应用过程中存在一定的区别
1 样本不是进行抽样采集,而是直接使用原始的数据集进行采集的
2 RF在构建数的时候,不管是CART,ID3,C4.5,特征属性分类的度量采用的信息熵,信息增益,基尼系数等,Exta Tree并不是,其直接是采用的随机特征进行分类划分,根本就不用计算什么信息熵等
优势在于,每个模型都使用的是全数据,样本量足够多,但是如果训练模型还是使用最佳划分的特征属性进行划分,那么每个模型都将一样,根本构建不出森林,所以这里直接使用随机的一个特征作为划分,不考虑是不是当前最优.这种方式是为了避免过拟合的问题
如果在当前的数据集是特征最优,就算是随机森林已经随机了特征,但是这个特征个数一般而言也不会少,很有可能很多次都使用了同一个特征最为最佳的划分特征,这就容易导致当前的模型在当前的数据集上拟合很好,这并不能保证在实际中模型鲁棒性好
一般不用这种,随机森林本来就已经是集成学习,已经随机了特征,这里再随机特征分类,并且使用了全数据,非常激进的算法,只有在随机森林解决不了的情况下才使用这种算法
Totally Random Trees Embedding (TRTE)
决策树还是决策树,随机的还是随机的,区别在于对每个决策树的处理不同,RF采用的是多数投票的方式,该算法做了一定的改进
思维方面:
每一个数据进入到最后的模型,在模型中每个决策树都会对这个数据进行分类,比如某个数是二分类,结果数实际存在3层,那么至少也是存在4个叶子节点,某一个或者多个叶子节点可能指向的类是相同的,那么越是在底层被分出来的说明其特征越不明显,因此虽然树能够区分这个样本属于哪个类,但是区分的难以程度上还是存在不同.
我们又理由认为越是容易区分的样本其可信度越高,越是难以区分的样本其被分错的可能性就更大,即使被分到某个类,其对应的叶子节点也不相同.
TRTE就构建这些叶子节点的位置信息,现在如果是有10个三层5节点的决策树,那么当一个样本进来之后最终不管结果如何,在这10颗树上面最终一定会停在某个叶子节点上,我们就能标记这些叶子节点,将树结构从左向右读,每一个叶子节点都是一个位置,可以给这些位置一个编码,比如样本最后停在某颗树的最左边节点,那么就给其一个编码(10000),这样有就是1,没有就是0,而且不存在出现两个1的情况,样本不可能同时停留在两个叶子节点
那么这10颗树就有这个样本的10个位置信息,将这些位置信息保存下来
下一个样本来了,继续在每一颗树上构建自己的编码,也会得到10个位置信息,那么我们怎么知道这两个样本是不是相近呢?现在两个样本的位置信息都有了,那么拿着信息去一一比对,如果大部分位置信息都相同,那么就有理由相信这两个样本很接近
比对是人为去看,这显然不理想,那么我们就引入一种度量方式去计算,编码的样子像极了向量,好的,我们就把它当做向量或者超空间重的点,如果两个位置信息相同,那么点重合,如果位置不同,那么两个点之间的距离 就是2^1/2,我们把这些距离加起来,这就能得到一个与每个位置距离相关的值,这个值越小说明重合的点越多,值越大说明差异越大.
TRTE的核心就是把决策树的位置信息作为一个新的特征,把原来RF多数投票的方式换成位置信息特征判别方式,感觉这样更科学.其实完全还可以针对没颗决策树的层位置进行编码,一样可以作为新的特征来处理
Boosting
叫做提升学习,可以用于回归和分类问题,其思路在于当某个模型的效果不好的时候,那么原始的数据集D在这个模型上存在一个预测效果,那么更改原始数据集D,再次训练一个新的模型,并赋予权重,完成后再更改原始数据集D,再训练,再赋予权重,继续迭代下去,那么每一次训练出来的模型都会存在权重,最后将所有模型汇总打包,那么任意来一个样本通过这些模型之后都有预测值,根据各自的权重进行求和,最后能够预测出值.
adaboost
原理:
1 对于训练样本集合D而言训练一个模型
2 该模型能够对训练集进行区分,但是效果并不好,将训练集D中标记正确的样本权重降低,将该模型区分错误的样本权重提升,重构训练数据集D
3 将重构的训练数据集D进行训练一个新模型,重复2,3步骤
那么每一次迭代的模型都是基于上一次训练的结果的,基本思路在于上一次的模型针对某些训练样本具有良好的区分能力,那么下一次迭代的训练模型就不需要在过多关注上个模型已经区分好的数据,其重点应该放在那些上个模型没有区分成功的数据上,因此需要将训练数据集D进行改造,增加上一次模型区分错误样本的权重
每一次迭代都更偏向于那些难以区分的样本,因此最后得到的一系列模型进行集成成为一个模型集合,其区分能力就能显著提升
我们就可以定义最终的集成分类器的预测函数为f(x)
f
(
x
)
=
∑
m
=
1
M
α
m
G
m
(
x
)
f(x) = \sum_{m=1}^M{α_m G_m(x)}
f(x)=m=1∑MαmGm(x)
其中G(x)表示模型集合中的子模型函数,α表示权重,如果某个模型G的错误非常高,比如第一次训练的模型错误率都比较高,那么其α权重值就会比较小,G错误率低的模型权重就会比较高,因此求和之后的f(x)就已经包含了子模型的权重和模型函数,这种是非常典型的线性组合,但是计算出来的f(x)是一个连续变量,不符合实际
对于分类而言,要么就是这个类,要么就不是这个类,只有两种结果是和不是,这种方式非常符合阶跃函数,大于零就是1,小于0就是-1
通过整理,定义最后的继承分类器为G(x)
G
(
x
)
=
s
i
g
n
(
f
(
x
)
)
=
s
i
g
n
(
∑
m
=
1
M
α
m
G
m
(
x
)
)
G(x) = sign(f(x)) = sign(\sum_{m=1}^M{α_m G_m(x)})
G(x)=sign(f(x))=sign(m=1∑MαmGm(x))
其中的sign(x)为阶跃函数,要么是1,要么是-1
那么如何评价这个G(x)的好坏呢?
定义一个函数I(x)
I
(
G
(
x
)
≠
y
)
I(G(x)≠y)
I(G(x)̸=y)
表示为如果G(x)预测值不等于实际值y,则I(x)就等于1,如果相等就为0
那么我们的测试集存在很多样本,如果总的样本数为n,则我们可以构建一个损失函数
l
o
s
s
(
x
)
=
1
n
∑
n
=
1
n
I
(
G
(
x
i
)
≠
y
i
)
loss(x) = {1 \over n} \sum_{n=1}^n{I(G(x_i)≠y_i)}
loss(x)=n1n=1∑nI(G(xi)̸=yi)
最悲催的就是loss(x)值为1,表示所有样本都错了,那还搞个锤子
因为I(x)要么是0,要么是1,而G(x)要么是-1,要么是1
于是继续构造
l
o
s
s
(
x
)
=
1
n
∑
n
=
1
n
I
(
G
(
x
i
)
≠
y
i
)
≤
1
n
∑
n
=
1
n
e
−
y
i
f
(
x
)
loss(x) = {1 \over n} \sum_{n=1}^n{I(G(x_i)≠y_i)} \leq {1 \over n}\sum_{n=1}^n{e^{-y_i f(x)}}
loss(x)=n1n=1∑nI(G(xi)̸=yi)≤n1n=1∑ne−yif(x)
这里之所以是f(x)不是G(x),因为f(x)如果大于零,则G(x)就为1,反之为-1,f(x)表示的是线性组合的集成了所有的分类器,这是最终的结果,这个结果如果为正,表示预测为正,此时如果y本身为负,那么很显然是预测错了,根据I(x),此时的I(x)取值就为1,对应的等式右边就为大于1的值,如果预测是正确的,对应等式右边就是大于0,小于1的值,因此上面的不等式是成立的,而且不等式的函数增减性质与损失函数的增减性是相同的,那么就将损失函数等于这个不等式右边的式子,凡是损失函数都是自己构造的,怎么方便怎么来,怎么分析问题优势怎么来,函数值根本不重要,重要的是函数的单调性,更明确的就是一阶导数很重要
既然有了损失函数,那么还需要思考一个问题,adaboost的算法实质就是迭代,每次去迭代前一次的结果,那么这个损失函数是构建的最后的模型,那么在迭代过程进行中的时候,比如显示是第k次迭代,那么前面的k-1次迭代其实是已经完成了,如果是在k-1次就截止,那么就能得到前面k-1的损失函数,换言之就意味着损失函数其实是每一次迭代的时候就能计算出来的.
如此就非常牛皮了,上面撸了半天还不是想解决如何使得我们的模型集合效果最好,模型集合实际上就是一堆模型,这些模型都存在着权重,那么这些权重是否就是最优的权重分布呢?那不一定吧,如何才能找到最优的权重分布呢?
好的,既然模型都已经训练出来了,模型就看出定量,而权重则看成变量,模型的集成方式是线性组合,很好,这个问题就变成了处理线组合了,只是原来的线性组合的x是样本,这里变成了子模型Gm(x),可以想象成原来输入的值经过Gm()加工后输出一个新值,利用这个新值构成新的x
上面已经撸出了损失函数,最优的时候就是使得损失函数最小的时候,就是一阶导为零的时候
那么我们再把adaboost的过程考虑进去,既然每一次迭代都是依赖于上一次的结果,那么我们可以构建第m次的损失函数loss()
l
o
s
s
(
α
m
,
G
(
x
)
)
=
1
n
∑
n
=
1
n
e
−
y
i
(
f
m
−
1
(
x
)
+
α
m
G
m
(
x
)
)
loss(α_m ,G(x)) ={1 \over n}\sum_{n=1}^n{e^{-y_i (f_{m-1}(x)+α_m G_m(x))}}
loss(αm,G(x))=n1n=1∑ne−yi(fm−1(x)+αmGm(x))
很显然,对这个损失函数求一阶导数,在导函数为0的值就是最优的系数.求导过程就有点不好整了,没关系,人家api早就知道我们这些数学渣是撸不平的,所以早就内置好了,这里只要知道思路就行
缺点
这个算法最坑爹的地方就是对异常数据非常敏感,因为异常数据在本身就少,是非常难区分的,但是每次迭代过程中这个异常数据都会被增加权重,那么越往后,权重越高,这就非常坑爹了
GBDT
梯度提升迭代决策树,mmp,听着名字就蛋疼,其实从理解起来反而比上面那个好理解一点,我个人观点哈
前提
梯度提升迭代决策树要求决策树必须是CART树,否则没用
原理: 该方法使用的也是迭代,跟adaboost不同的是,该方法使用的不是加权再训练,而是采用的取残差,设定步长,也可以说是学习度,再训练的方式
具体的方法是:
1 将数据进行整合输入模型会得到一个预测值,这个预测值与实际值之间会存在差异,通过预测值减去实际值的差称为残差,那么
2 所有的数据都计算出残差后,接下来进行替换操作,将残差替换称为训练数据真实值,这样就构成了一个新的数据集,训练这个数据集得到第二个模型
3 重复1和2,直到迭代次数达到或者残差低于某个阈值
很容易看出的是每一次的迭代都会产生新的数据集,每一次新的数据集训练模型预测的结果都是更接近真实值,这就非常像是梯度下降的感觉,每一次迭代都会距离最低点近一些
想象一个二次函数,呈现的是一个开口向上的曲线,现在在曲线上的某一点开始进行梯度下降,不管是跨度大还是小,前提是学习率别整太大整成发散了,只要沿着梯度下降的方向进行迭代,值就会一次次逼近最低点.放到GBDT中实际上就是残差会越来越小,不管是正还是负,最后都是向零进行逼近.
这里直接将数据集的真实值替换成残差是可以的,但是还是不太满意,在梯度下降的过程中我们是给了学习率的,这里同样也可以给一个学习率一样的东西,在这里就定义为步长,表示每一次迭代的时候向着0移动的效率,步长如果为1,则就是残差
引入的目的实际上是为了减少过拟合
现在定义F(x)就是集成的训练模型输出函数,至于这么多子模型的投票权重是什么还不知道,先包含到F(x)中
那么损失函数就可以构建成
l
o
s
s
(
y
,
F
(
x
)
)
=
1
2
(
y
−
F
(
x
)
)
2
loss(y, F(x)) ={1 \over 2}(y - F(x))^{2}
loss(y,F(x))=21(y−F(x))2
那么我们用f(x)定义为子模型函数
F
(
x
)
=
v
∑
m
=
1
M
f
i
(
x
)
F(x) =v\sum_{m=1}^M{f_i(x)}
F(x)=vm=1∑Mfi(x)
而v表示的是学习率
定义F的最优解为
a
r
g
F
m
i
n
L
(
y
,
F
(
x
)
)
arg_FminL(y, F(x))
argFminL(y,F(x))
和adaboost一样,都是属于迭代形式,那么就意味着当前的损失函数是基于上一次迭代的最优解,那么第m次的迭代对应的输出函数就为
F
m
(
x
)
=
F
m
−
1
(
x
)
+
a
r
g
f
m
i
n
∑
i
=
1
m
L
(
y
,
F
m
−
1
(
x
i
)
+
f
m
(
x
i
)
)
F_m(x)=F_{m-1}(x) + arg_fmin\sum_{i=1}^m{L(y, F_{m-1}(x_i)+f_m(x_i))}
Fm(x)=Fm−1(x)+argfmini=1∑mL(y,Fm−1(xi)+fm(xi))
注意到F(x)中的学习率,实际上是多少我们根本不知道,这里需要找到最优的学习率
注意到损失函数中实际上是包含学习率的,那么对损失函数进行对F(x)求偏导数,求第m次迭代的第i个模型的学习率
v
i
m
=
[
∂
L
(
y
i
,
F
(
x
i
)
)
∂
F
(
x
i
)
]
F
(
x
)
=
F
m
−
1
(
x
)
v_{im} = [\frac{\partial L(y_i,F(x_i))}{\partial F(x_i)}]_{F(x)=F_{m-1}(x)}
vim=[∂F(xi)∂L(yi,F(xi))]F(x)=Fm−1(x)
后面的F部分是下标,表示求的是F(x)与Fm-1次的时候的学习率
找到最适合的学习率就能够找到最优的模型
缺点
boosting的通病,因为后一次的结果是以前一次结果作为参数的,所以没有办法使用并行的计算,这就导致执行效率不高
Stacking
这个算法就有点像神经网络了
1 训练多个模型
2 每一个模型都存在输出,利用这些输出构建成新的数据集继续训练次级模型
3 如果想的是多层,则继续执行训练下去,最后输出结果
这种算法的思路很像是神经网络,既然如此还不如就用神经网络,这个效果会更好
模型的重要区别
Stacking的思维更像是神经网络,所以这里暂时不和bagging与boosting进行区分
从数据选择上面
bagging采用的是有放回的抽样方式,这种方式其实已经对训练数据的分布造成了影响
boosting采用的是全数据训练,这样的方式使得数据分布更加符合数据本身
样本权重
bagging采用的是随机抽样,权重都一样
boosting采用的迭代方式,第一次大家权重相同,根据模型预测效果进行迭代的时候就会改变原来样本的权重,adaboost就是典型的越往后对难区分样本的权重就会越高,GBDT使用的是残差方式,造成的效果是梯度下降,每次的学习率都不同,隐含的就是权重
结果预测
bagging采用的多数投票,权重相同
boosting采用的错误率越低的模型,其权重越高,表示区分能力越强
核心
bagging的方式中,都是采用的是随机,从样本的随机到特征的随机,这些种种都是在降低样本的variance方差,就是降低模型的过拟合,方差越大表示模型越偏向于训练数据本身,那么熟悉里面暗含的特征就被模型学习的非常好,而这些特征可能并不是我们需要的,这就导致模型出现过拟合,随机的方式能够有效降低方差,从而降低过拟合
boosting的方式是降低bais偏度,从第一个分类器开始就没有想过要有多好的区分度,因此从第一个分类器开始就是弱分类器,经过修改数据集后把数据喂给第二个分类器,这个分类器其实如果对原数据来说还是一个弱分类器,因此在boosting中所有的分类器都是弱分类器,这就导致实际上的每一个分类器都是欠拟合的,但是通过迭代,将欠拟合的分类器渐渐改进成为强分类器,因此boosting降低的是偏度
前面GBDT部分还是没吃透,后续学习过程中再加强总结,感觉现在的理解还是有失偏颇