一、集成学习与Boosting

集成学习是指将多个弱学习器组合成一个强学习器,这个强学习器能取所有弱学习器之所长,达到相对的最佳性能的一种学习范式。

集成学习主要包括Boosting和Bagging两种学习框架。Boosting是一种将弱学习器提升为强学习器的算法,所以也叫提升算法。

以分类问题为例,给定一个训练数据集,训练弱分类器要比训练强分类器相对容易很多,从第一个弱分类器开始,Boosting通过训练多个弱分类器,并在训练过程中不断改变训练样本的概率分布,使得每次训练时算法都会更加关注上一个弱分类器的错误。通过组合多个这样的弱分类器,便可以获得一个接近相对完美的强分类器。boosting方法的核心理念在于博采众长,正所谓"三个臭皮匠,顶个诸葛亮",这也使得boosting方法要好于大多数单模型算法。

二、AdaBoost模型

AdaBoost基本原理

AdaBoost的全称为Adaptive Boosting,可以翻译为自适应提升算法。(提升方法是将弱学习算法提升为强学习算法的统计学习方法。)

AdaBoost是一种通过改变训练样本权重来学习多个弱分类器并线性组合成强学习器的Boosting算法。

Boosting要解决两个关键问题:

  • 一是在训练过程中如何改变训练样本的权重或者概率分布。
  • 二是如何将多个弱分类器组合成一个强分类器。

针对这两个问题,Adaboost是做法非常朴素,第一个就是提高前一轮被弱分类器分类错误的样本的权重、而降低分类正确的样本权重;第二则是对多个弱分类器进行线性组合,提高分类效果好的弱分类器权重,减小分类误差率大的弱分类器权重。

给定训练数据集\(D={(x_1,y_1),(x_2,y_2),⋯,(x_N,y_N)}\),其中\(x_i∈χ⊆R^n,y_i∈Y={−1,+1}\),AdaBoost训练算法如下。

  1. 初始化训练数据样本的权值分布,即为每个训练样本分配一个初始权值:$D_1=(w_{11},⋯,w_{1i},⋯w_{1N}), w_{1i}=1/N, i=1, 2,⋯,N $

  2. 对于\(t=1, 2,⋯,T\),分别执行以下步骤。

  • 对包含权值分布\(D_m\)的训练数据集进行训练并得到弱分类器\(G_t(x)\)。

  • 计算\(G_t(x)\)在当前加权训练集上的分类误差率\(ϵ_t\):

    \(ϵ_t=P(G_t(x_i)≠y_i)=∑_{i=1}^Nw_{ti}I(G_t(x_i)≠y_i)\)

  • 根据分类误差率\(ϵ_t\)计算当前弱分类器的权重系数\(α_t\):

    \(α_t=1/2 log{(1−ϵ_t)/ϵ_t}\)

  • 调整训练数据集的权值分布:

    \(D_{t+1}=(w_{t+1},1,⋯,w_{t+1},i,⋯w_{t+1},N)\)

    \(w_{t+1},i=w_ti/{Z_t} exp(−α_t y_i G_t(x_i))\)

    分类正确的权重下降,分类错误权重上升

    其中\(Z_t\)为归一化因子,\(Z_t=∑_{i=1}^N w_{ti}exp(−α_t y_i G_t(x_i))\)。

  1. 最后构建T个弱分类器的线性组合:

    \(f(x)=∑_{i=1}^T α_t G_t(x)\)

最终的AdaBoost强分类器可以写为:

\(G(x)=sign(f(x))=sign(∑_{i=1}^N α_t G_t(x))\)

在弱分类器权重系数计算过程中,当弱分类器的分类误差率\(ϵ_t≤1/2\)时,\(α_t≥0\),且\(α_t\)随着\(ϵ_t\)的减小而变大,这也正是弱分类器权重系数计算公式的设计思想,它能够使得分类误差率较低的分类器有较大的权重系数。AdaBoost训练样本权值分布可以写为:

\[w_{t+1, i}=\left\{\begin{array}{ll}
\frac{w_{t i}}{Z_{t}} e^{-\alpha_{t}}, & G_{t}\left(x_{i}\right)=y_{i} \\
\frac{w_{t i}}{Z_{t}} e^{\alpha_{t}}, & G_{t}\left(x_{i}\right) \neq y_{i}
\end{array}\right.\]

当样本被弱分类器正确分类时,对应样本的权重变小;当样本被弱分类器错误分类时,对应样本的权重变大。相比之外,错误分类样本的权重扩大了\(e^{2α_t}\)倍,这就使得在下一轮训练中,算法将更加关注这些误分类的样本。

视频讲解:

简博士

https://www.bilibili.com/video/BV18g41197rC

https://www.bilibili.com/video/BV1pF411F7CY/

前向分步算法

从机器学习三要素(模型、策略、算法)的角度来看,AdaBoost可以看作为以加性模型为模型、指数函数为损失函数和前向分步为算法的分类学习算法。

所谓加性模型(additive model),就是由多个基模型求和的形式构造起来的。加性模型可以表示为:

\(f(x)=∑_{t=1}^T α_t b(x;γ_t)\)

其中\(b(x;γ_t)\)为基模型,\(γ_t\)为基模型参数,\(α_t\)为基模型系数,可知f(x)是由T个基模型求和的加性模型。

给定训练数据集和损失函数的条件下,加性模型的目标函数为如下最小化损失函数:

\(\min _{\alpha_{t}, \gamma_{t}} \sum_{i=1}^{N} L\left(y_{i}, \sum_{t=1}^{T} \alpha_{t} b\left(x_{i} ; \gamma_{t}\right)\right)\)

针对上式这样一个较为复杂的优化问题,可以采用前向分步算法进行求解。其基本思路如下:针对加性模型的特点,从前往后每次只优化一个基模型的参数,每一步优化叠加之后便可逐步逼近目标函数。每一步优化的表达式如下式所示:

\(\min _{α,γ} ∑_{i=1}^N L(y_i,αb(x_i;γ))\)

给定训练数据集\(D={(x_1,y_1),(x_2,y_2),⋯,(x_N,y_N)}\),其中\(x_i∈χ⊆R^n,y_i∈Y=\{−1,+1\}\),前向分步算法求解过程如下。

初始化模型\(f_0(x)=0\)。

对于t=1, 2,⋯,T,分别执行以下操作。

以\(α_t\)和\(γ_t\)为优化参数,最小化目标损失函数:

$(α_t,γ_t)=argmin_{α,γ}∑_{i=1}^N L(y_i,f_{t−1}(x_i)+αb(x_i;γ)) $

更新加性模型:

\(f_t(x)=f_{t−1}(x)+α_tb(x;γ_t)\)

可得到最后的加性模型为:

\(f(x)=f_T(x)=∑_{t=1}^Tα_tb(x;γ_t)\)

从前向分步算法的角度来理解AdaBoost,可以将AdaBoost看作前向分步算法的特例,这时加性模型是以分类器为基模型、以指数函数为损失函数的最优化问题。假设经过t−1次前向分步迭代后已经得到\(f_{t−1}(x)\),第t次迭代可以得到第t个基模型的权重系数\(α_t\)、第t个基模型\(G_t(x)\)和t轮迭代后的加性模型\(f_t(x)\)。优化目标是使

\(f_t(x)\)在给定训练数据集D上的指数损失最小化,有:

\(\left(\alpha_{t}, G_{t}(x)\right)=\underset{\alpha, G}{\operatorname{argmin}} \sum_{i=1}^{N} \exp \left(-y_{i}\left(f_{t-1}\left(x_{i}\right)+\alpha G\left(x_{i}\right)\right)\right)\)

求解上式的最小化指数损失即可得到AdaBoost的优化参数。

三、AdaBoost算法实现

先定义一个基分类器

### 定义决策树桩类
### 作为Adaboost弱分类器
class DecisionStump():
def __init__(self):
# 基于划分阈值决定样本分类为1还是-1
self.label = 1
# 特征索引
self.feature_index = None
# 特征划分阈值
self.threshold = None
# 指示分类准确率的值
self.alpha = None

定义AdaBoost算法类

### 定义AdaBoost算法类
class Adaboost:
# 弱分类器个数
def __init__(self, n_estimators=5):
self.n_estimators = n_estimators # Adaboost拟合算法
def fit(self, X, y):
m, n = X.shape
# (1) 初始化权重分布为均匀分布 1/N
w = np.full(m, (1/m))
# 处初始化基分类器列表
self.estimators = []
# (2) for m in (1,2,...,M)
for _ in range(self.n_estimators):
# (2.a) 训练一个弱分类器:决策树桩
estimator = DecisionStump()
# 设定一个最小化误差
min_error = float('inf')
# 遍历数据集特征,根据最小分类误差率选择最优划分特征
for i in range(n):
# 获取特征值
values = np.expand_dims(X[:, i], axis=1)
# 特征取值去重
unique_values = np.unique(values)
# 尝试将每一个特征值作为分类阈值
for threshold in unique_values:
p = 1
# 初始化所有预测值为1
pred = np.ones(np.shape(y))
# 小于分类阈值的预测值为-1
pred[X[:, i] < threshold] = -1
# 2.b 计算误差率
error = sum(w[y != pred]) # 如果分类误差大于0.5,则进行正负预测翻转
# 例如 error = 0.6 => (1 - error) = 0.4
if error > 0.5:
error = 1 - error
p = -1 # 一旦获得最小误差则保存相关参数配置
if error < min_error:
estimator.label = p
estimator.threshold = threshold
estimator.feature_index = i
min_error = error # 2.c 计算基分类器的权重
estimator.alpha = 0.5 * np.log((1.0 - min_error) / (min_error + 1e-9))
# 初始化所有预测值为1
preds = np.ones(np.shape(y))
# 获取所有小于阈值的负类索引
negative_idx = (estimator.label * X[:, estimator.feature_index] < estimator.label * estimator.threshold)
# 将负类设为 '-1'
preds[negative_idx] = -1
# 2.d 更新样本权重
w *= np.exp(-estimator.alpha * y * preds)
w /= np.sum(w) # 保存该弱分类器
self.estimators.append(estimator) # 定义预测函数
def predict(self, X):
m = len(X)
y_pred = np.zeros((m, 1))
# 计算每个弱分类器的预测值
for estimator in self.estimators:
# 初始化所有预测值为1
predictions = np.ones(np.shape(y_pred))
# 获取所有小于阈值的负类索引
negative_idx = (estimator.label * X[:, estimator.feature_index] < estimator.label * estimator.threshold)
# 将负类设为 '-1'
predictions[negative_idx] = -1
# 2.e 对每个弱分类器的预测结果进行加权
y_pred += estimator.alpha * predictions # 返回最终预测结果
y_pred = np.sign(y_pred).flatten()
return y_pred

数据测试

from sklearn.model_selection import train_test_split
# 导入sklearn模拟二分类数据生成模块
from sklearn.datasets._samples_generator import make_blobs
# 生成模拟二分类数据集
X, y = make_blobs(n_samples=150, n_features=2, centers=2,
cluster_std=1.2, random_state=40)
# 将标签转换为1/-1
y_ = y.copy()
y_[y_==0] = -1
y_ = y_.astype(float)
# 训练/测试数据集划分
X_train, X_test, y_train, y_test = train_test_split(X, y_,
test_size=0.3, random_state=43)
# 设置颜色参数
colors = {0:'r', 1:'g'}
# 绘制二分类数据集的散点图
plt.scatter(X[:,0], X[:,1], marker='o', c=pd.Series(y).map(colors))
plt.show();

自定义Adaboost模型测试

# 导入sklearn准确率计算函数
from sklearn.metrics import accuracy_score
# 创建Adaboost模型实例
clf = Adaboost(n_estimators=5)
# 模型拟合
clf.fit(X_train, y_train)
# 模型预测
y_pred = clf.predict(X_test)
# 计算模型预测准确率
accuracy = accuracy_score(y_test, y_pred)
print("Accuracy of AdaBoost by numpy:", accuracy)

Accuracy of AdaBoost by numpy: 0.9777777777777777

导入sklearn adaboost分类器测试

from sklearn.ensemble import AdaBoostClassifier
# 创建Adaboost模型实例
clf_ = AdaBoostClassifier(n_estimators=5, random_state=0)
# 模型拟合
clf_.fit(X_train, y_train)
# 模型预测
y_pred_ = clf_.predict(X_test)
# 计算模型预测准确率
accuracy = accuracy_score(y_test, y_pred_)
print("Accuracy of AdaBoost by sklearn:", accuracy)

Accuracy of AdaBoost by sklearn: 0.9777777777777777

监督学习集成模型——AdaBoost的更多相关文章

  1. 吴裕雄 python 机器学习——集成学习AdaBoost算法回归模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklear ...

  2. 吴裕雄 python 机器学习——集成学习AdaBoost算法分类模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklear ...

  3. Python机器学习(基础篇---监督学习(集成模型))

    集成模型 集成分类模型是综合考量多个分类器的预测结果,从而做出决策. 综合考量的方式大体分为两种: 1.利用相同的训练数据同时搭建多个独立的分类模型,然后通过投票的方式,以少数服从多数的原则作出最终的 ...

  4. DeepMind提出空间语言集成模型SLIM,有效编码自然语言的空间关系

    前不久,DeepMind 提出生成查询网络 GQN,具备从 2D 画面到 3D 空间的转换能力.近日.DeepMind 基于 GQN 提出一种新模型.可以捕捉空间关系的语义(如 behind.left ...

  5. 『Kaggle』分类任务_决策树&集成模型&DataFrame向量化操作

    决策树这节中涉及到了很多pandas中的新的函数用法等,所以我单拿出来详细的理解一下这些pandas处理过程,进一步理解pandas背后的数据处理的手段原理. 决策树程序 数据载入 pd.read_c ...

  6. 【集成模型】Bootstrap Aggregating(Bagging)

    0 - 思想 如下图所示,Bagging(Bootstrap Aggregating)的基本思想是,从训练数据集中有返回的抽象m次形成m个子数据集(bootstrapping),对于每一个子数据集训练 ...

  7. 吴裕雄 python 机器学习——半监督学习LabelSpreading模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import metrics from sklearn import d ...

  8. 决策树与树集成模型(bootstrap, 决策树(信息熵,信息增益, 信息增益率, 基尼系数),回归树, Bagging, 随机森林, Boosting, Adaboost, GBDT, XGboost)

    1.bootstrap   在原始数据的范围内作有放回的再抽样M个, 样本容量仍为n,原始数据中每个观察单位每次被抽到的概率相等, 为1/n , 所得样本称为Bootstrap样本.于是可得到参数θ的 ...

  9. 集成学习-Adaboost

    Adaboost 中文名叫自适应提升算法,是一种boosting算法. boosting算法的基本思想 对于一个复杂任务来说,单个专家的决策过于片面,需要集合多个专家的决策得到最终的决策,通俗讲就是三 ...

随机推荐

  1. SQL中如何修改数据库名、表名、列名?

    文章目录 1.SQL中如何修改数据库的名字? 2.SQL中如何修改表的名字? 3.SQL中如何修改列的名字? 4.SQL中如何修改列的数据类型?(未完成,待续) 1.SQL中如何修改数据库名? 语法 ...

  2. 从单例谈double-check必要性,多种单例各取所需

    theme: fancy 前言 前面铺掉了那么多都是在讲原则,讲图例.很多同学可能都觉得和设计模式不是很搭边.虽说设计模式也是理论的东西,但是设计原则可能对我们理解而言更加的抽象.不过好在原则东西不是 ...

  3. android系统中有哪些日志

    日志目录 android系统中还有很多常用的日志目录.我们可以通过adb命令把这些日志信息提取出来. data/system/dropbox data/system/usagestats data/s ...

  4. c++ RMQ

    关于 RMQ ,即 Range Maxnum (Minnum) Query .用于查询静态区间最大(最小)值, 思路基于动态规划 (DP) 思路 设 F[i][j] 为 [i,i+2j] 区间内的的最 ...

  5. SQL语句修改MySQL用户密码

    SQL语句修改MySQL用户密码 前言 上数据库安全实验课,用命令行和DataGrip试图修改用户密码,一直语法报错.最后用Navicat才修改成功,预览Navicat的SQL语句,发现语句和网上都不 ...

  6. iOS全埋点解决方案-采集奔溃

    前言 ​ 采集应用程序奔溃信息,主要分为以下两种场景: ​ NSException 异常 ​ Unix 信号异常 一.NSException 异常 ​ NSException 异常是 Objectiv ...

  7. Vue搭建后台系统需要做的几点(持续更新中)

    前言 持续更新 一.UI框架 推荐 Elemnet ui 二.图表 vue-schart npm install vue-schart -S <template> <div id=& ...

  8. UiPath文本操作Get Text的介绍和使用

    一.Get Text操作的介绍 从指定的UI元素提取文本值 二.Get Text在UiPath中的使用 1. 打开设计器,在设计库中新建一个Sequence,为序列命名及设置Sequence存放的路径 ...

  9. sql server2016 数据库日志 清空语句

    /*1.查询数据库日志文件名称*/--TC_MES_DEV为数据库名--这里的 数据库日志名,可以用以下注释的语句进行查询(_log那个)USE [TC_MES_DEV]GOSELECT file_i ...

  10. vim插件pathogen的Helptags不起作用

    如果你安装了中文vim帮助,并且在其中添加了自己的帮助文件,并且当你使用了pathogen的时候. 会发现Helptags不起作用. 原因是Helptags的实现没有考虑到中文的情况 解决办法如下: ...