监督学习集成模型——AdaBoost
一、集成学习与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训练算法如下。
初始化训练数据样本的权值分布,即为每个训练样本分配一个初始权值:$D_1=(w_{11},⋯,w_{1i},⋯w_{1N}), w_{1i}=1/N, i=1, 2,⋯,N $
对于\(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))\)。
最后构建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训练样本权值分布可以写为:
\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的更多相关文章
- 吴裕雄 python 机器学习——集成学习AdaBoost算法回归模型
import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklear ...
- 吴裕雄 python 机器学习——集成学习AdaBoost算法分类模型
import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklear ...
- Python机器学习(基础篇---监督学习(集成模型))
集成模型 集成分类模型是综合考量多个分类器的预测结果,从而做出决策. 综合考量的方式大体分为两种: 1.利用相同的训练数据同时搭建多个独立的分类模型,然后通过投票的方式,以少数服从多数的原则作出最终的 ...
- DeepMind提出空间语言集成模型SLIM,有效编码自然语言的空间关系
前不久,DeepMind 提出生成查询网络 GQN,具备从 2D 画面到 3D 空间的转换能力.近日.DeepMind 基于 GQN 提出一种新模型.可以捕捉空间关系的语义(如 behind.left ...
- 『Kaggle』分类任务_决策树&集成模型&DataFrame向量化操作
决策树这节中涉及到了很多pandas中的新的函数用法等,所以我单拿出来详细的理解一下这些pandas处理过程,进一步理解pandas背后的数据处理的手段原理. 决策树程序 数据载入 pd.read_c ...
- 【集成模型】Bootstrap Aggregating(Bagging)
0 - 思想 如下图所示,Bagging(Bootstrap Aggregating)的基本思想是,从训练数据集中有返回的抽象m次形成m个子数据集(bootstrapping),对于每一个子数据集训练 ...
- 吴裕雄 python 机器学习——半监督学习LabelSpreading模型
import numpy as np import matplotlib.pyplot as plt from sklearn import metrics from sklearn import d ...
- 决策树与树集成模型(bootstrap, 决策树(信息熵,信息增益, 信息增益率, 基尼系数),回归树, Bagging, 随机森林, Boosting, Adaboost, GBDT, XGboost)
1.bootstrap 在原始数据的范围内作有放回的再抽样M个, 样本容量仍为n,原始数据中每个观察单位每次被抽到的概率相等, 为1/n , 所得样本称为Bootstrap样本.于是可得到参数θ的 ...
- 集成学习-Adaboost
Adaboost 中文名叫自适应提升算法,是一种boosting算法. boosting算法的基本思想 对于一个复杂任务来说,单个专家的决策过于片面,需要集合多个专家的决策得到最终的决策,通俗讲就是三 ...
随机推荐
- Dubbo3 源码系列 -- 环境准备
Dubbo3 源码系列 -- 环境准备 前言 工作中一直使用Dubbo项目,借着这次机会通过源码的方式来学习下Dubbo的源码内容.目前市面上很多都是的Dubbo2系列的教程:就连目前的Dubbo的官 ...
- python中collections.OrderedDict()
import collections #from collections import OrderededDict my_orderDict=collections.OrderedDict(house ...
- 【摸鱼神器】UI库秒变LowCode工具——列表篇(二)维护json的小工具
上一篇介绍了一下如何实现一个可以依赖 json 渲染的列表控件,既然需要 json 文件,那么要如何维护这个 json 文件就成了重点,如果没有好的维护方案的话,那么还不如直接用UI库. 所以需要我们 ...
- Redis的使用(二)
一.redis简单应用 其实在写这个redis专题时我想了很久,我觉得redis没什么好说的,因为现在是个人都会用redis,但是我在写netty专题时发现,netty里面很多东西和概念有很多跟red ...
- Django——模板应用
一.前言 前提:已经用命令提前创建好了项目DjangoTest,以下是基于该项目进行实战演练. 二.项目下创建templates文件夹 1.创建templates文件夹 2.创建HelloWorld. ...
- 6.文本三剑客之sed
文本三剑客之sed 目录 文本三剑客之sed sed编辑器 sed概述 sed工作流程 sed用法 sed打印 sed删除 sed替换 sed增加行内容 sed剪切粘贴与复制粘贴 sed字符/字符串交 ...
- Vuex的各个模块封装
一.各个模块的作用: state 用来数据共享数据存储 mutation 用来注册改变数据状态(同步) getters 用来对共享数据进行过滤并计数操作 action 解决异步改变共享数据(异步) 二 ...
- SAP FPM 相关包 APB_FPM_CORE
related interface: APB_FPM_COREAPB_FPM_CORE_4_EXT_SCAPB_FPM_CORE_INTERNALAPB_FPM_CORE_RESTRICTED
- Kali信息收集
前言 渗透测试最重要的阶段之一就是信息收集,需要收集关于目标主机的基本细腻些.渗透测试人员得到的信息越多,渗透测试成功的概率也就越高. 一.枚举服务 1.1 DNS枚举工具DNSenum DNSenu ...
- js与java encodeURI 进行编码与解码
JS escape()使用转义序列替换某些字符来对字符串进行编码 JavaScript 中国 编码后 JavaScript %u4E2D%u56FD unescape()对使用 encodeUR ...