在现代生活中,很多地方都涉及一个概念:冗余 (Redundancy),它原本是一种贬义词,指的是某些东西(信息、语言、代码、结构、服务、软件、硬件等等)重复且多余。
然而在通信存储等领域,它则成了中性词,是指对某些东西进行人为增加重复的部分,比如对某样东西进行备份,从而增强其安全性。对于这个概念,其中一个应用比较广泛的地方是航天系统。
SpaceX是一家著名的太空探索技术公司,其中比较知名的有其生产的Dragon系列载人龙飞船。因为太空的环境安全标准比地球严格非常多,所以制造飞船的材料也很特殊和昂贵,除此之外,还需要功能强大的超级计算机安置在飞船内部供宇航员进行监测和操控,以便维持飞船的正常轨迹运行。
然而在太空环境中,某些影响因素会导致计算机出现一些错误,比较典型的有:太空粒子翻转 (SEU,Single-Event Upsets),它是指在空间环境下存在着大量高能带电粒子,计算机中的电子元器件受到地球磁场、宇宙射线等照射,引起电位状态的跳变,“0"变成"1”,或者"1"变成"0"(太空探索早期人们已经注意到了这个问题)。
在地球表面,有磁场和大气层的保护,能够到达地面的高能粒子很少,一般来说对计算机的影响不大(当然除了人为制造或自然界的放射性物质,还有极低概率的宇宙粒子穿透地地球表面的大气层和磁场来到我们的生活区),所以在计算机设计中,并不需要过多考虑这种特殊场景,常规的硬件纠错机制配合操作系统,足以应付这种偶然的误差。计算机对于错误若实在改不过来,蓝屏重启,可能也就复原了。
然而在太空环境下,单粒子翻转的概率会大得多,那么校验算法会极其困难,因为单粒子翻转的可能不止一位,那么如何解决该问题,提高可靠性呢?
飞船的计算机和我们使用的计算机可靠性要求是不一样的,我们使用的计算机可以死机蓝屏,大不了重启一下就可以了,但飞船本身的控制计算机是必须持续可靠运行的,一旦出了问题,肯定是致命的。
SpaceX设计了一套整体容错三重冗余计算机架构(an overall Fault tolerance triple redundant computer architecture),即由多台计算机运行同一个软件,结果由多数表决系统处理产生一个单一的输出,正确的大多数计算结果会纠正和掩盖其他少数错误的故障。(某些领域使用N重冗余,结果计算方法类似,即多数表决)。虽然每台处理器都可能发生位翻转,但我们知道飞机上同时有两枚炸弹的概率是极低的。
某航天器在执行为期5天的航空任务中,单粒子翻转出现了161次之多,可见在外太空环境下,计算机计算结果的可靠性非常重要。
所以,与其花费巨大的人力物力制造一台几乎不受任何辐射粒子影响的先进超级计算机,不如带几台相对普通的超级计算机一起工作,无论是可靠性还是成本等其他方面,都比先进计算机要更好。
于是,借助这个思想,后面便引申出了机器学习算法中,集成学习(ensemble)的概念。
太空计算机为什么性能都这么低?(zhihu)
SINGLE EVENT UPSETS: HIGH ENERGY PARTICLES FROM OUTER SPACE FLIPPING BITS (hackaday)
Single-event_upset (wikipedia)
SpaceX_Dragon (wikipedia)
Triple_modular_redundancy (wikipedia)
在数据挖掘等应用中,直接建立一个高性能的分学习器是很困难的,但是,如果能找到一系列性能较差的学习器(弱学习器),并把它们集合起来,组合之后的效果可能高于性能较强的学习器(强学习器)。
“三个臭皮匠,胜过诸葛亮”便是对这种思想最好的解释。
弱学习器 (Weak Learner)
强学习器 (Strong Learner)
弱学习器是指,分类正确率仅比随机猜测略高的学习算法,
集成学习的具体步骤为:
(每个模型也被称为个体学习器(Individual learner)或者基学习器)
Bagging的核心思想为并行地训练一系列各自独立的同类型,然后再将各个模型的输出结果按照某种策略进行聚合。
Bagging字面意思为装袋法,按照其组合的策略,同时也称为引导聚合算法(Bootstrap Aggregating),所以主要分为两个阶段:
有放回
的随机采样
取出大小为 n ′ ( n ′ = n ) n^{'}(n^{'} = n) n′(n′=n) 的 m m m 个子训练集。注意:
重点 | 说明 |
---|---|
1 | 既然 n ′ = n n^{'}=n n′=n, 那么每个子训练集的大小和整体训练集样本大小一样大 |
2 | 既然每个子训练集的采样是有放回的,那么,每个样例的权重相等,但是同一样本可能在一个子训练集中多次出现,进而平均每个弱学习器只使用了原数据集中的63.2%的样本,同理训练集中大约有36.8%的数据没有被采集到。这样就存在一部分“袋外数据”(OOB)始终不被取到,它们可以直接用于测试误差,而无需单独的测试集或验证集。 |
推导:
每次被采集到的概率是 1 n \frac{1}{n} n1,那么不被采集到的概率为 1 − 1 n 1−\frac{1}{n} 1−n1,所以n次采样都没有 被采集中的概率是 ( 1 − 1 n ) n (1−\frac{1}{n})^{n} (1−n1)n,当 n → ∞ n \rightarrow \infty n→∞时,求极限:
根据等价无穷小, n ln ( 1 − 1 n ) = n × − 1 n = − 1 n\ln(1-\frac{1}{n})=n\times-\frac{1}{n}=-1 nln(1−n1)=n×−n1=−1
lim n → ∞ ( 1 − 1 n ) n = e lim n → ∞ n ln ( 1 − 1 n ) = e − 1 = 0.368 \begin{aligned}\lim_{n \rightarrow \infty}(1-\frac{1}{n})^{n}=e^{\lim_{n \rightarrow \infty}n\ln(1-\frac{1}{n})}\end{aligned}=e^{^{-1}}=0.368 n→∞lim(1−n1)n=elimn→∞nln(1−n1)=e−1=0.368
同类模型
(应用在决策树分类中即为CART算法等决策树算法), 并行的
训练各自的数据集,生成 m m m个弱学习器 { h ( S , θ m ) , k = 1 , 2 , . . . , m } \{h(S,\theta_m), k=1,2,...,m\} {h(S,θm),k=1,2,...,m},测试集喂给该 m m m 个基模型,将返回 m m m 个结果。对于这 m m m 个结果需要通过某些集成策略综合为最终的结果:
分类
问题,则采用投票法
(vote),即这 m m m 个预测结果中占多数的为分类结果。回归
问题,则采用简单平均法
(mean)或加权平均法()
,即这 m m m 个预测结果的平均或加权平均值为最终的回归结果。重点 | 说明 |
---|---|
1 | 对不同子训练集进行模型训练的模型一般为同类模型(不是严格意义上要求) |
2 | 对于每个训练出来的基模型,运用到测试集得出结果后,若是分类问题则采用投票法,若是回归问题则采用平均法 |
3 | 因为是多次采样,并且并行训练模型后投票或平均,某些离散值很可能被消掉,误差减少,因此噪声数据的影响下降,泛化能力变强,能减少模型的方差,提高模型的稳定性,不太容易受到过拟合的影响,它因此适用于偏差低、方差高的模型的融合,但也因如此,它对偏差高的模型融合后的拟合效果不好。 |
偏差: 模型预测值的期望与真实值之间的差异,反应的是模型的拟合能力。
方差: 反应的是训练集的变化所导致的学习性能的变化,即刻画了数据扰动所造成的影响,模型过拟合时会出现较大的方差。
随机森林(Random Forest)是在Bagging算法的基础上作了修改,Bagging算法只进行了一种采样:随机样本采样。而随机森林进具有二重随机性,除了Bagging的采样,更进一步包含随机特征采样。除此之外,流程和步骤都基本一致。
随机
选择 k k k 个属性 ( k k k通常取 ∣ l o g 2 ( M ) ∣ + 1 |log_2(M)|+1 ∣log2(M)∣+1, M M M为特征总数),再从这些属性中选取一个最优属性来分裂节点,构造一棵CART决策树。
随机森林简单、容易实现、计算开销小,令人惊奇的是,它在很多现实任务中展现出强大的性能,被誉为“代表集成学习技术水平的方法”。可以看出,随机森林对Bagging只做了小改动,但是与Bagging中基学习器的“多样性”仅通过样本扰动(通过对初始训练集采样)不同,随机森林中学习器的多样性不仅来自样本扰动,还来自属性扰动,这就使得最终集成的泛化性能可通过个体学习器之间差异度的增加进一步提升。
注意:
重点 | 说明 |
---|---|
1 | 由于构造每棵决策树时,随机抽取训练样本集和属性子集的过程都是独立的,且都来自于同分布的总体,因此基模型 { h ( S , θ m ) , k = 1 , 2 , . . . , m } \{h(S,\theta_m), k=1,2,...,m\} {h(S,θm),k=1,2,...,m}是一个独立同分布的随机变量序列。 |
2 | 两个随机性(随机采样,样本最优特征选择)的引入,使得随机森林抗噪声能力强,方差小泛化能力强,不易陷入过拟合(因此不需要剪枝) |
3 | 由于可以随机选择决策树节点划分的特征,因此能够处理高维度(特征多)的数据,事先不用做特征选择;而且连续和离散数据均可,且无需归一化数据。 |
4 | 由于随机森林对误差率是无偏估计,因此在算法中不需要再进行交叉验证或者设置单独的测试集来获取测试集上误差的无偏估计 |
5 | 训练后,可以给出各个特征对于输出结果的重要性排序,并且能够检测到特征间的相互影响 。 |
6 | 由于随机森林对误差率是无偏估计,因此在算法中不需要再进行交叉验证或者设置单独的测试集来获取测试集上误差的无偏估计。 |
7 | 在某些噪音比较大的样本集上,RF模型容易陷入过拟合。 |
8 | 取值划分比较多的特征容易对RF的决策产生更大的影响,从而影响拟合的模型的效果。 |
9 | 随机森林的训练效率优于Bagging,因为在个体决策树的构建过程中,Bagging使用的是“确定型”的决策树,在选择属性划分时要对节点的所有属性进行考察,而随机森林使用的“随机型”的决策树则只需考察一个子集。 |
Boosting的核心思想为串行地训练一系列前后依赖的同类模型,即后一个模型用来对前一个模型的输出结果进行纠正。
它与装袋法相比,每次的训练样本均为同一组,并且引入了权重的概念,给每个单独的训练样本都会分配一个相同的初始权重。
Boosting的学习过程是:
由此可知,每一轮训练后,都会生成一个分类模型,而每次生成的这个分类模型都会更加注意之前分类错误的样本从而提高样本分类的准确率。
提升法有两个主要问题需要解决:
为了解决上面两个问题,提升法有着多种算法实现。
AdaBoost算法(Adaptive Boosting)是一种有效而实用的Boosting算法,它以一种高度自适应的方式按顺序训练弱学习器。针对分类问题,AdaBoost算法根据前一次的分类效果调整数据的权重,在上一个弱学习器中分类错误的样本的权重会在下一个弱学习器中增加,分类正确的样本的权重则相应减少,并且在每一轮迭代时会向模型加入一个新的弱学习器。不断重复调整权重和训练弱学习器,直到误分类数低于预设值或迭代次数达到指定最大值,最终得到一个强学习器。
Adaboost是Adaptive Boosting(自适应提升)的缩写,它采用以一种高度自适应的方式按顺序迭代顺序训练弱学习器的思想,每次迭代只训练一个弱分类器,训练好的弱分类器将参与下一次迭代的使用(与Bagging的并行互不干扰不同)。也就是说,在第 K K K 次迭代中,一共有 K K K 个分类器,前 K − 1 K-1 K−1 个是已经训练好的,其各种参数都不再改变,则本次只训练第 K K K 个分类器。
弱分类器之间的关系是:第 K K K 个更可能将第 K − 1 K-1 K−1 个弱分类器所没分对的数据分类正确。“更可能分对”是通过调整训练数据的权重分布实现的。最终分类输出要看这 K K K 个分类器的综合效果。
Adaboost算法的主要流程原理如下:
Adaboost算法很好的的利用了弱分类器进行级联,可以将不同的分类算法作为弱分类器,并具有很高的精度。
注意:
重点 | 说明 |
---|---|
1 | Adaboost不用对特征进行筛选,也不存在过拟合的现象。 |
2 | Adaboost算法速度很慢,在一定程度上依赖于训练数据集和弱学习器的选择,训练数据不足或者弱学习器太“弱”,都将导致其训练精度的下降 |
3 | Adaboost会使得难于分类样本的权值呈指数增长,训练将会过于偏向这类困难的样本,易受到噪声的影响,因为它在迭代过程中总是给噪声分配较大的权重,使得这些噪声在以后的迭代中受到更多关注。 |
RandomForestClassifier
RandomForestRegressor
梯度提升决策树(Gradient Boost Decision Tree, GBDT) 也是一种迭代决策树算法,主要用于回归
,经过改进后
也可以用于实现分类任务
。GBDT的实现思想是构建多棵决策树,并将所有决策树的输出结果进行综合,得到最终的结果。
GBDT算法的构建过程与分类决策树类似,主要区别在于回归树节点的数据类型为连续型数据,每一个节点均有一个具体数值,此数值是该叶子节点上所有样本数值的平均值
。同时,衡量每个节点的每个分支属性表现,不再使用熵、信息增益或Gini指数等纯度指标,而是通过最小化每个节点的损失函数值
来进行每个节点处的分裂。
回归树分裂终止的条件为每个叶子节点上的样本数值唯一
,或者达到预设的终止条件,如决策树层数、叶子结点个数达到上限。若最终存在叶子节点上的样本数值不唯一,则仍以该节点上的所有样本的平均值作为该节点的回归预测结果。
提升决策树(Boosting Decision Tree)使用提升法的思想,结合多棵决策树来共同进行决策。首先介绍GBDT算法中的残差
概念,残差值为真实值与决策树预测值之间的差。GBDT算法采用平方误差
作为损失函数,每一棵回归树均学习之前所有所有决策树累加起来的残差,拟合得到当前的残差决策树。提升决策树是利用加法模型和前项分布算法来实现学习和过程优化。当提升树使用的是平方误差
这种损失函数时,提升树的每一步优化会比较简单,然而当提升树中使用的损失函数为绝对值损失函数
时,每一步的优化往往不那么简单。
针对此问题,弗里德曼(Friedman)于1999年提出了梯度提升决策树算法
,利用梯度下降的思想,使用损失函数的负梯度在当前模型的值,作为提升树中残差的近似值,以此来拟合回归决策树。梯度提升决策树的算法过程如下:
AdaBoost算法根据分类效果调整权重并不断迭代,最终生成强学习器;GBDT算法则将损失函数的负梯度作为残差的近似值,不断使用残差迭代和拟合回归树,最终生成强学习器。简单来说,AdaBoost算法是调整权重,而GBDT算法则是拟合残差。
算法具体步骤和应用可以参考我的其他博文:机器学习从零到入门 GBDT 梯度提升决策树
在GBDT的基础上衍生了几个非常强大的模型:XGBoost,LightGBM,CatBoost,NGBoost。他们也都是基于Gradient Boosting的集成学习。
主要是前三个模型,第四个模型一般不会用到。
对于GBDT算法的具体实现,最为出色的是XGBoost树提升系统,此模型的性能已得到广泛认可,并被大量应用于Kaggle等数据挖掘比赛中,取得了极好的效果。在XGBoost系统实现的过程中,对于GBDT算法进行了多方面的优化。
由于诸多方面的优化实现,XGBoost无论在性能和运行速度上都优于一般的GBDT算法。论文可参考:XGBoost: A Scalable Tree Boosting System
具体的优化如下:
(1)、损失函数加入正则项
XGBoost将树模型的复杂度加入到正则项中,从而避免过拟合,泛化能力好。
目标函数 = 损失函数(拟合数据) + 正则化项
(惩罚复杂模型)
O b j ( Θ ) = L ( Θ ) + Ω ( Θ ) Obj(\Theta)=\quad\quad L(\Theta)\quad\quad+\quad\quad\color{red}{\Omega(\Theta)} Obj(Θ)=L(Θ)+Ω(Θ)
损失函数尽量拟合训练数据,正则化项鼓励简单的模型。
Ω ( f 1 ) \Omega(f_1) Ω(f1)用于控制树的复杂度,防止过拟合,使得模型更简化,也使得最终的模型的预测结果更加稳定:
Ω ( f 1 ) = γ T + 1 2 γ ∑ j = 1 T w j 2 \begin{aligned}\Omega(f_1)=\gamma T + \frac{1}{2}\gamma\sum^T_{j=1}w^2_j\end{aligned} Ω(f1)=γT+21γj=1∑Twj2
T T T: 叶子数量
w j w_j wj: 叶子分数的 L 2 L2 L2正则项
γ \gamma γ: 加入新叶子节点引入的复杂度代价
损失函数越小,那么拟合的误差越的小;模型越简单,那么正则化项越小。综合两者的和为目标函数的值也就越小,训练出来的值越接近真实值。
(2)、损失函数使用泰勒公式展开到二阶
损失函数是用泰勒展开式展开的,用到了一阶导和二阶导,可以加快优化速度。
(3)、贪心算法与近似算法寻找最佳分割点
贪心算法:
在寻找最佳分割点时,采用近似贪心算法,用来加速计算。
(4)、基分类器种类的增加
不仅支持CART作为基分类器,还支持线性分类器,在使用线性分类器的时候可以使用 L 1 L1 L1, L 2 L2 L2正则化。
(5)、模型运行的加速
支持并行计算,XGBoost的并行是基于特征计算的并行,将特征列排序后以block的形式存储在内存中,在后面的迭代中重复使用这个结构。
在进行节点分裂时,计算每个特征的增益,选择增益最大的特征作为分割节点,各个特征的增益计算可以使用多线程并行。
(6)、特征与样本的二重采样以及收缩步长
xgboost借鉴了随机森林的做法,支持对数据与特征进行采样:
列采样:按层随机(对同一层内每个结点分裂之前,先随机选择一部分特征),建树前随机选择特征(在建树前就随机选择一部分特征,然后之后所有叶子结点的分裂都只使用这部分特征)。
行采样:bagging 抽取部分样本采样。
这样做不仅能降低过拟合,还能减少计算。
除此之外,为了防止过拟合,更新过程中用到了收缩步长。
在每次提升计算之后,算法会直接获得新特征的权重。 eta通过缩减特征的权重使提升计算过程更加保守,取值范围为[0,1]
优点与缺点:
优点:
速度快、效果好、能处理大规模数据、支持自定义损失函数等。
传统的GBDT没有设计对缺失值进行处理,xgboost能够自动学习出缺失值的处理策略
缺点:
算法参数过多,调参复杂,不适合处理超高维特征数据。
所以XGBoost对超高维特征的数据处理速度慢,效果不是很好,而这些缺点在后面两个模型中都得到了很好的解决与提升。
LightGBM是2017年由微软推出的,它是XGBoost的升级版。论文可参考:LightGBM: A Highly Efficient Gradient Boosting Decision Tree
GBM表示Gradient Boosting Machine表示它是基于GBDT的,Light表示它在大规模数据集上运行效率更高。
为何提出LightGBM?
LightGBM的提出是为了解决GBDT在海量数据遇到的问题,让GBDT可以更好更快地用于工业场景。
针对XGBoost的优化:
LightGBM = XGBoost + Histogram + GOSS + EFB
(这里是原版的XGBoost,而新版的XGBoost-approx实现了Histogram)
XGBoost的与排序(pre-sorted)算法:
说明:第一个bin里面,1/3的概率选择了i=2而没选到其他两个值,于是 N i N_i Ni的加号左侧表示大于阈值而直接保留的值的数量,没有,则为0;右侧为小于阈值的数量,只选择了i=2,由于是1/3的概率,所以乘以三补全为1整体样本的数量。 G i G_i Gi大写表示和,三倍的i=2为0.09,。 H i H_i Hi大写也表示和,为0.12。
EFB算法:
CatBoost(Categorical Boost)算法是俄罗斯科技公司Yandex开源的机器学习库(2017),可参考:CatBoost: unbiased boosting with categorical features
该算法能高效的处理分类特征(categorical features), 首先对分类特征做统计,计算某个分类特征(category)出现的频率,然后加上超参数,生成新的数值型特征(numerical features)。同时视同组合类别特征,丰富了特征维度。
采用的基模型是对称决策树,算法的参数少、支持分类变量,通常可以防止过拟合。
CatBoost,LightGBM,XGBoost对比:
使用2015年航班延误数据,包含分类和数值变量,参考链接:2015 Flight Delays and Cancellations
它一共有约500万条记录,使用10%的数据,即50条记录
Cateboost过拟合程度最小,在测试集上准确度最高0.816,同时预测用时最短,但这个表现仅仅在有分类特征,而且调节了one-hot最大量时才会出现。
如果不利用CatBoost算法在这些特征上的优势,表现效果就会变成最差,AUC为0.752
使用CatBoost需要数据中包含分类变量,同时适当地调节这些变量时,才会表现不错。
所以我们可以总结:
太空计算机为什么性能都这么低?(zhihu)
SINGLE EVENT UPSETS: HIGH ENERGY PARTICLES FROM OUTER SPACE FLIPPING BITS (hackaday)
Single-event_upset (wikipedia)
SpaceX_Dragon (wikipedia)
Triple_modular_redundancy (wikipedia)
RandomForestClassifier
RandomForestRegressor
线性搜索
机器学习从零到入门 GBDT 梯度提升决策树
XGBoost: A Scalable Tree Boosting System
LightGBM: A Highly Efficient Gradient Boosting Decision Tree
CatBoost: unbiased boosting with categorical features