前言

前面的文章中介绍了决策树以及其它一些算法,但是,会发现,有时候使用使用这些算法并不能达到特别好的效果。于是乎就有了集成学习(Ensemble Learning),通过构建多个学习器一起结合来完成具体的学习任务。这篇文章将介绍集成学习,以及其中的一种算法 AdaBoost。

集成学习

首先先来介绍下什么是集成学习:

  • 构建多个学习器一起结合来完成具体的学习任务,常可获得比单一学习器显著优越的泛化性能,对“弱学习器” 尤为明显(三个臭皮匠,顶个诸葛亮)
  • 也称为Multi-Classifier System, Committee-Based Learning
  • 学习器可以是同类型的,也可以是不同类型

这么一看,就感觉集成学习与常说的模型融合很像,甚至可以理解为就是模型融合。

那么,常用的集成学习方法有哪些呢?

  1. Boosting,将各种弱分类器串联起来的集成学习方式,每一个分类器的训练都依赖于前一个分类器的结果,代表:AdaBoost,Gradient Boosting Machine
  2. Bagging,Bootstrap Aggregating 的缩写。这种方法采用的是随机有放回的选择训练数据然后构造分类器,最后进行组合,代表:Random Forest
  3. Voting/Averaging,在不改变模型的情况下,直接对各个不同的模型预测的结果进行投票或者平均
  4. Binning,最近看到的一种方法,还没细看,参考论文
  5. Stacking
  6. Blending

后面几种方法这里暂时不做介绍,后面会单独写博客来介绍这些方法

AdaBoost

算法思想

这里将介绍一个基于 Boosting 方法的一个学习算法 AdaBoost,于1995年由 Freund 和 Schapire 提出。其主要思想为:

  1. 先训练出一个基学习器
  2. 根据该学习器的表现对训练样本权重进行调整,使得现有基学习器做错的样本在后续学习器的训练中受到更多的关注
  3. 基于调整后的权重来训练下一个基学习器
  4. 重复 2、3 直至学习器数目达到事先指定的值 T
  5. 最终将这 T 个学习器进行加权结合

\[H(x)=\operatorname{sign}\left(\sum_{t=1}^{T} \alpha_{t} h_{t}(x)\right)
\]

具体算法

设训练数据集

\[\{x^{(i)}, y^{(i)}\}_{i=1}^{m},x^{(i)} \in \mathbb{R}^n, y \in \{-1, +1\}
\]

初始化训练数据的权值分布

\[\mathcal{D}_{1}\left(x^{(i)}\right)=\frac{1}{m}
\]

for t in range(T):

​ 假设训练得到分类器 \(h_t(x)\) ,则可计算 \(h_t(x)\) 在当前训练集上的分类误差:

\[\epsilon_{t}=P_{x \sim \mathcal{D}_{t}}\left[h_{t}(x) \neq y\right]=\sum_{y^{(i)} \neq h_{t}\left(x^{(i)}\right)} \mathcal{D}_{t}\left(x^{(i)}\right)
\]

​ 若 \(\epsilon_{t} > 0.5\), break; 否则计算分类器权重

\[\alpha_{t}=\frac{1}{2} \log \frac{1-\epsilon_{t}}{\epsilon_{t}}
\]

​ 然后更新样本权重

\[\mathcal{D}_{t+1}\left(x^{(i)}\right)=\frac{1}{Z_{t}} \mathcal{D}_{t}\left(x^{(i)}\right) \exp \left[-\alpha_{t} y^{(i)} h_{t}\left(x^{(i)}\right)\right]
\]

​ 其中 \(Z_t\) 为归一化因子

\[Z_{t}=\sum_{i} \mathcal{D}_{t}\left(x^{(i)}\right) \exp \left[-\alpha_{t} y^{(i)} h_{t}\left(x^{(i)}\right)\right]
\]

构建基本分类器的线性组合

\[f(x)=\sum_{t=1}^{T} \alpha_{t} h_{t}(x)
\]

得到最终分类器

\[H(x)=\operatorname{sign}\left(\sum_{t=1}^{T} \alpha_{t} h_{t}(x)\right)
\]

这里我们可以看到 \(\alpha_t\) 是大于 $\frac{1}{2} $ 的,如果误分类了,那么 \(-\alpha_{t} y^{(i)} h_{t}\left(x^{(i)}\right)\) 为大于 0 的数,那么样本的权重就会被放大,反之,则会被缩小。并且, \(\epsilon_t\) 越大,\(\alpha_t\) 就越小,即在最终构建强分类器的时候,误差率越小的弱分类器预测结果所占比重越高。

算法推导

思考两个个问题, \(\alpha_t\) 的公式是怎么来的?以及权重更新公式是怎么来的?下面通过公式推导来讲解

假设已经经过 \(t-1\) 轮迭代,得到\(f_{t-1}(x)\),根据前向分布加法算法

\[f_t(x) = f_{t-1}(x) + \alpha_{t}h_t(x)
\]

目标是损失函数最小,即

\[\min{Loss} = \min\sum_{i=1}^{N}exp[-y_i(f_{t-1}(x_i)+\alpha_th_t)]
\]

所以,有

\[\begin{eqnarray}(\alpha_t,h_t(x)) & = & \arg {\min_{\alpha,h}\sum_{i=1}^{N}exp[-y_i(f_{t-1}(x_i)+\alpha_th_t()x_i)]} \\ & = & \arg {\min_{\alpha,h}\sum_{i=1}^{N}w_{t,i}exp[-y_i(\alpha_th_t(x_i))]} \end{eqnarray}
\]

\[w_{t,i} = \exp[-y_if_{t-1}(x_i)]
\]

我们先来化简损失函数

\[\begin{eqnarray}Loss & = &\sum_{y_i=h_t(x_i)}w_{t,i}exp(-\alpha_t)+\sum_{y_i \ne h_t(x_i)}w_{t,i}exp(\alpha_t)
\\ & = & \sum_{i=1}^{N}w_{t,i}(\frac{\sum_{y_i=h_t(x_i)}w_{t,i}}{\sum_{i=1}^{N}w_{t,i}}exp(-\alpha_t)+\frac{\sum_{y_i \ne h_t(x_i)}w_{t,i}}{\sum_{i=1}^{N}w_{t,i}}exp(-\alpha_t))
\end{eqnarray}
\]

仔细以看,后面那项 \(\frac{\sum_{y_i \ne h_t(x_i)}w_{t,i}}{\sum_{i=1}^{N}w_{t,i}}\) 就是分类误差率 \(\epsilon_{t}\),所以

\[Loss = \sum_{i=1}^{N}w_{t,i}[(1-\epsilon_t)exp(-\alpha_t)+\epsilon_texp(\alpha_t)]
\]

对 \(\alpha_t\) 求偏导

\[\begin{eqnarray}
\frac{\partial Loss}{\partial \alpha_t} & = & \sum_{i=1}^{N}w_{t,i}[-(1-\epsilon_t)exp(-\alpha_t)+\epsilon_texp(\alpha_t)]
\end{eqnarray}
\]

令 \(\frac{\partial Loss}{\partial \alpha_t} = 0\) ,则

\[-(1-\epsilon_t)exp(-\alpha_t)+\epsilon_texp(\alpha_t) = 0
\]

推得

\[\alpha_{t}=\frac{1}{2} \log \frac{1-\epsilon_{t}}{\epsilon_{t}}
\]

另,由前向分布加法算法

\[\begin{eqnarray}
w_{t,i} & = & \exp[-y_if_{t-1}(x_i)] \\
& = & \exp[-y_i(f_{t-2}(x_i)+\alpha_{t-1}h_{t-1}(x_i))] \\
& = & w_{t-1,i}\exp[\alpha_{t-1}h_{t-1}(x_i)]
\end{eqnarray}
\]

再加上规范化因子即为算法中的更新公式。(公式敲的要累死了~~~)

代码实现

这里为了方便起见,我使用了 sklearn 里面的决策树,之前使用的时候一直没发现 sklearn 里的决策树可以带权重训练 orz。。。决策树带权训练的代码我后面再研究研究

from sklearn.tree import DecisionTreeClassifier
def adaboost(X, y, M, max_depth=None):
"""
adaboost函数,使用Decision Tree作为弱分类器
参数:
X: 训练样本
y: 样本标签, y = {-1, +1}
M: 使用 M 个弱分类器
max_depth: 基学习器决策树的最大深度
返回:
F: 生成的模型
"""
num_X, num_feature = X.shape # 初始化训练数据的权值分布
D = np.ones(num_X) / num_X G = []
alpha = [] for m in range(M):
# 使用具有权值分布 D 的训练数据集学习,得到基本分类器
# 使用 DecisionTreeClassifier,设置树深度为 max_depth
G_m = DecisionTreeClassifier(max_depth=max_depth)
# 开始训练
G_m.fit(X, y, D)
# 计算G_m在训练数据集上的分类误差率
y_pred = G_m.predict(X)
e_m = np.sum(D[y != y_pred]) if e_m == 0:
break if e_m == 1:
raise ValueError("e_m = {}".format(e_m)) # 计算 G_m 的系数
alpha_m = np.log((1 - e_m) / e_m) / 2
# print(alpha_m)
# 更新训练数据集的权值分布
D = D * np.exp(-alpha_m * y * y_pred)
D = D / np.sum(D)
# 保存 G_m 和其系数
G.append(G_m)
alpha.append(alpha_m) # 构建基本分类器的线性组合
def F(X):
num_G = len(G)
score = 0
for i in range(num_G):
score += alpha[i] * G[i].predict(X)
return np.sign(score) return F

小节

上面介绍了集成学习的一些知识点以及 AdaBoost 的基本原理及实现,下一篇将介绍集成学习中基于 Bagging 的随机森林(Random Forest)。

谈谈模型融合之一 —— 集成学习与 AdaBoost的更多相关文章

  1. 集成学习值Adaboost算法原理和代码小结(转载)

    在集成学习原理小结中,我们讲到了集成学习按照个体学习器之间是否存在依赖关系可以分为两类: 第一个是个体学习器之间存在强依赖关系: 另一类是个体学习器之间不存在强依赖关系. 前者的代表算法就是提升(bo ...

  2. 集成学习之AdaBoost

    AdaBoost 当做出重要决定时,大家可能会考虑吸取多个专家而不只是一个人的意见,机器学习也是如此,这就是集成学习的基本思想.使用集成方法时有多种形式:可以是不同算法的集成,也可以是同一算法在不同设 ...

  3. 机器学习回顾篇(13):集成学习之AdaBoost

    .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...

  4. 集成学习之Adaboost算法原理小结

    在集成学习原理小结中,我们讲到了集成学习按照个体学习器之间是否存在依赖关系可以分为两类,第一个是个体学习器之间存在强依赖关系,另一类是个体学习器之间不存在强依赖关系.前者的代表算法就是是boostin ...

  5. 集成学习之Adaboost算法原理

    在boosting系列算法中,Adaboost是最著名的算法之一.Adaboost既可以用作分类,也可以用作回归. 1. boosting算法基本原理 集成学习原理中,boosting系列算法的思想:

  6. 集成学习算法——adaboost

    adaboost是boosting类集成学习方法中的一种算法,全称是adaptive boost,表示其是一种具有自适应性的算法,这个自适应性体现在何处,下面来详细说明. 1.adaboost算法原理 ...

  7. 谈谈模型融合之三 —— GBDT

    前言 本来应该是年后就要写的一篇博客,因为考完试后忙了一段时间课设和实验,然后回家后又在摸鱼,就一直没开动.趁着这段时间只能呆在家里来把这些博客补上.在之前的文章中介绍了 Random Forest ...

  8. 机器学习—集成学习(Adaboost)

    一.原理部分: 二.sklearn实现: from sklearn.ensemble import AdaBoostClassifier from sklearn.datasets import lo ...

  9. 决策树(中)-集成学习、RF、AdaBoost、Boost Tree、GBDT

    参考资料(要是对于本文的理解不够透彻,必须将以下博客认知阅读): 1. https://zhuanlan.zhihu.com/p/86263786 2.https://blog.csdn.net/li ...

随机推荐

  1. python 里内嵌函数是可以修改外部环境里的变量的

    python 里内嵌函数是可以修改外部环境里的变量的 关键是细节. 如果是简单变量类型, 那么不可以. 但是如果是容器类变量, 则没问题了. 代码如下: class G: pass def f(): ...

  2. Docker容器中安装新的程序

    在容器里面安装一个简单的程序(ping). 之前下载的是ubuntu的镜像,则可以使用ubuntu的apt-get命令来安装ping程序:apt-get install -y ping. $docke ...

  3. HLSL像素着色器

    原文:HLSL像素着色器 昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心 手机淘宝二维码 扫描       或者打开连接:程序设计开发 ,掌声鼓励,欢迎光临.     像素着色器替代了固定渲染管线的  ...

  4. spring boot初步

    spring boot介绍 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程. 该框架使用了特定的方式来进行配置,从而 ...

  5. EF的多线程与分库架构设计实现(2)

    距离上次讲解EF6分库架构(https://www.cnblogs.com/gbat/p/6374607.html)实现已经过去2年了..上次发出来后,一直到现在依然有很多人陆陆续续的加我好友,问我要 ...

  6. [ Laravel 5.1 文档 ] 服务 —— 帮助函数

    http://laravelacademy.org/post/205.html 1.简介 Laravel自带了一系列PHP帮助函数,很多被框架自身使用,然而,如果你觉得方便的话也可以在应用中随心所欲的 ...

  7. poj 1787 Charlie's Change (多重背包可作完全背包)

    Charlie's Change Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 3792   Accepted: 1144 ...

  8. poj 3181 Dollar Dayz(完全背包)

    Dollar Dayz Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5419   Accepted: 2054 Descr ...

  9. [转载] CentOS系统开机自动挂载光驱 和 fstab文件详解

    参考 http://blog.itpub.net/12272958/viewspace-676977/ 一.开机自动挂载光驱 1.按习惯,root用户,在/media目录下建立目录cdrom——mkd ...

  10. Django使用cors解决跨域问题

    1.安装Django-cors-headers模块 pip install django-cors-headers 2.配置settings.py文件 INSTALLED_APPS = [ ... ' ...