Python实现Adaboost

1.Adaboost概念

提升方法的思路是综合多个分类器,得到更准确的分类结果。 即“三个臭皮匠顶个诸葛亮”。《统计学习方法》称AdaBoost是提升算法的代表,所谓提升算法,指的是一种常用的统计学习方法,应用广泛且有效。在分类问题中,它通过改变训练样本的权重,学习多个分类器,并将这些分类器进行线性组合,提髙分类的性能。
AdaBoost算法的基本思想:
1)多轮训练,多个分类器
2)每轮训练增加错误分类样本的权值,降低正确分类样本的权值
3)降低错误率高的分类器的权值,增加正确率高的分类器的权值

2.Adaboost算法流程

给定一个二类分类的训练数据集,T={(x1,y1),(x2,y2),…(xn,yn)}T=\{({x_1},y_1),({x_2},y_2),\dots({x_n},y_n)\}T={(x1,y1),(x2,y2),(xn,yn)},其中χi∈X⊆Rnχ_i∈X⊆ R^nχiXRn表示实例的特征向量,yi∈Y∈{+1,−1}y_i∈Y\in\{+1,-1\}yiY{+1,1},XXX是实例空间,YYY是标记集合。AdaBoost利用以下算法,从训练数据中学习一系列弱分类器或基本分类器,并将这些弱分类器线性组合成为一个强分类器。
AdaBoost算法
输入:训练数据集T={(x1,y1),(x2,y2),…(xn,yn)}T=\{({x_1},y_1),({x_2},y_2),\dots({x_n},y_n)\}T={(x1,y1),(x2,y2),(xn,yn)},其中χi∈X⊆Rnχ_i∈X⊆ R^nχiXRn,yi∈Y∈{+1,−1}y_i∈Y\in\{+1,-1\}yiY{+1,1};弱学习算法;
输出:最终分类器G(x)G(x)G(x)
(1)初始化训练数据的权值分布

D1=(W11,...,W1i,...,W1n)D_1=(W_{11},...,W_{1i},...,W_{1n})D1=(W11,...,W1i,...,W1n)

每个w的下标由两部分构成,前一个数表示当前迭代次数,与D的下标保持一致,后一个数表示第几个权值,与位置保持一致。初始情况下,每个权值都是均等的。
(2)对m=1,2,...Mm=1,2,...Mm=1,2,...M
(这里的M表示训练的迭代次数,是由用户指定的。每轮迭代产生一个分类器,最终就有M个分类器,当然我们也可以设置一些条件,满足某些条件时跳出迭代,例如,所有样本都分对了,误差为0时,跳出迭代):
(a)使用具有权值分布的训练数据集学习,得到基本分类器

Gm(x):X→{+1,−1}G_m(x):X{\rightarrow} \{+1,-1\}Gm(x):X{+1,1}

(b)在Gm(x)G_m(x)Gm(x)训练数据集上的分类误差率

em=∑iNP(Gm(xi)≠yi)=∑iNwmiI(Gm(xi)≠yi))e_m=\sum_i^NP(G_m(x_i){\neq}y_i)=\sum_i^Nw_{mi}I(G_m(x_i){\neq}y_i))em=iNP(Gm(xi)̸=yi)=iNwmiI(Gm(xi)̸=yi))

分类误差率这个名字可能产生误解,这里其实是个加权和。
(c)计算Gm(x)G_m(x)Gm(x)的系数

αm=12log1−emem\alpha_m = \frac{1}{2}log{\frac{1-e_m}{e_m}}αm=21logem1em

这里的对数是自然对数。ama_mam表示Gm(x)G_m(x)Gm(x)在最终分类器中的重要性。由式αm=12log1−emem\alpha_m = \frac{1}{2}log{\frac{1-e_m}{e_m}}αm=21logem1em可知,当em&lt;=1/2e_m&lt;=1/2em<=1/2时,am&gt;=0a_m&gt;=0am>=0,并且ama_mam随着eme_mem的减小而增大,所以分类误差率越小的基本分类器在最终分类器中的作用越大。

(d)更新训练数据集的权值分布

Dm+1=(Wm+1,1,...,Wm+1,i,...,Wm+1,n)D_{m+1}=(W_{m+1,1},...,W_{m+1,i},...,W_{m+1,n})Dm+1=(Wm+1,1,...,Wm+1,i,...,Wm+1,n)

wm+1,i=wm,iZme−αmyiGm(xi)w_{m+1, i}=\frac{w_{m, i}}{Z_m}e^{-\alpha_my_iG_m(x_i)}wm+1,i=Zmwm,ieαmyiGm(xi)

y只有正负一两种取值,所以上式可以写作:

wm+1,i={wmiZme−am,Gm(xi)=yiwmiZmeam,Gm(xi)≠yiw_{m+1,i}=\begin{cases} \frac{w_{mi}}{Z_m}e^{-a_m},G_m(x_i)=y_i \\ \frac{w_{mi}}{Z_m}e^{a_m},G_m(x_i){\neq}y_i \end{cases}wm+1,i={Zmwmieam,Gm(xi)=yiZmwmieam,Gm(xi)̸=yi

这里,ZmZ_mZm是规范化因子

Zm=∑i=1Nwmiexp(−αmyiGm(xi))Z_m=\sum_{i=1}^Nw_{m i}exp({-\alpha_my_iG_m(x_i)})Zm=i=1Nwmiexp(αmyiGm(xi))

它使Dm+1D_{m+1}Dm+1成为一个概率分布。
由此可知,被基本分类器误分类样本的权值得以扩大,而被正确分类样本的权值却得以缩小。两相比较,误分类样本的权值被放大e2am=1−ememe^{2am} = {\frac{1-e_m}{e_m}}e2am=em1em倍。因此,误分类样本在下一轮学习中起更大的作用。不改变所给的训练数据,而不断改变训练数据权值的分布,使得训练数据在基本分类器的学习中起不同的作用,这是AdaBoost的一个特点。

(3)构建基本分类器的线性组合:

f(x)=∑m=1MamGm(x)f(x)=\sum_{m=1}^{M}a_mG_m(x)f(x)=m=1MamGm(x)

得到最终分类器:

G(x)=sign(f(x))=sign(∑m=1MamGm(x))G(x)=sign(f(x))=sign(\sum_{m=1}^{M}a_mG_m(x))G(x)=sign(f(x))=sign(m=1MamGm(x))
这里需要注意的是,我们得到的是M个f(x)方程,需要将每个方程的结果求和,最好只取结果的正负号,在Adaboost中我们的预测结果与数值是无关的。

3.完整代码

代码运行结果:
在这里插入图片描述

# -*- coding: utf-8 -*-
"""@Time    : 2018/12/04 13:58@Author  : hanzi5@Email   : hanzi5@yeah.net@File    : Adaboost.py@Software: PyCharm
"""
import numpy as np
#import pandas as pd
import matplotlib
import matplotlib.pyplot as pltmatplotlib.rcParams['font.family']='SimHei'  # 用来正常显示中文
plt.rcParams['axes.unicode_minus']=False     # 用来正常显示负号def splitDataSet(dataSet, i, value,types='lt'):"""
#划分数据集,只进行一次划分的树,将划分后的结果返回:param dataSet: 数据:param i: 特征的下标:param value: 阈值:param types: 大于或小于:return: 分类结果,注意返回的直接就是1,-1分类结果"""retArray = np.ones((np.shape(dataSet)[0],1))     # 默认类型都为1if types=='lt':   # 使用(小于等于value)划分数据,满足条件的将结果值改为-1retArray[dataSet[:,i]<=value]= -1.0  elif types=='gt': # 使用(大于value)划分数据,满足条件的将结果值改为-1retArray[dataSet[:,i]>value]= -1.0  return retArray def bulidSimpleTree(dataSet,y,D):"""
创建一个最简单的树,只进行一次划分,相当于一个树桩:param dataSet: 数据特征矩阵:param y: 标签向量:param D: 训练数据的权重向量:return: 最佳决策树,最小的错误率加权和,最优预测结果"""m,n=dataSet.shape                      # 样本行数及列数numFeatures = len(dataSet[0]) - 1      # 最后一列为y,计算x特征列数numSteps=10                            # 用于计算步长,进行numSteps等分minError=np.inf                        # 初始化损失值bestTree={}                            # 使用dict存储最优的一系列树for i in range(numFeatures):           # 遍历所有x特征列# i=0rangeMin = dataSet[:, i].min()     # 该xi维的最小值rangeMax = dataSet[:, i].max()     # 该xi维的最大值stepSize = (rangeMax - rangeMin) / numSteps # 步长for j in range(-1,int(numSteps) + 1):    # 循环寻找最优切分点# j=-1for inequal in ['lt', 'gt']:         # 遍历(lt小于等于)及(gt大于)# inequal=1value = (rangeMin + float(j) * stepSize) # 切分值predictedVals = splitDataSet(dataSet, i, value, inequal)  # 获取切分后的数据errArr = np.mat(np.ones((m, 1)))errArr[predictedVals == y] = 0  # 预测正确的样本对应的错误率为0,否则为1weightedError=D.T*errArr        # 《统计学习方法》李航P138,8.1,计算训练数据上的分类误差率if weightedError < minError:    # 记录最优树桩决策树分类器minError = weightedError    # 计算错误率加权和bestClasEst = predictedVals.copy() # 最好的预测结果bestTree['column'] = i             # 维度xbestTree['splitValue'] = value     # 切分值bestTree['ineq'] = inequal         # 切分方法(lt小于等于)及(gt大于)return bestTree, minError, bestClasEst# 基于单层决策树的adaboost分类器
def adaboost(dataSet,maxLoop=100):"""
基于单层决策树的ada训练:param dataSet: 样本x及y:param maxLoop: 迭代次数:return: 一系列弱分类器及其权重,样本分类结果"""adaboostTree=[]m,n=dataSet.shape                     # 样本行数及列数y=dataSet[:,-1].reshape((-1,1))       # 将y提取出来,方便进行计算D = np.array(np.ones((m,1))/m)        # 将每个样本的权重初始化为均等,有多少条数据就有多少个daggClassEst = np.mat(np.zeros((m,1))) # 每个数据点的类别估计累计值for i in range(maxLoop):              # maxLoop超参数,总迭代次数bestTree, minError, bestClasEst=bulidSimpleTree(dataSet,y,D)alpha=0.5*np.log((1-minError)/(minError+0.00001)) # 《统计学习方法》李航P139,8.2,计算Gm的系数,分母加一个小数避免除数为0bestTree['alpha'] = alpha.getA()[0][0]            # 将matrix中的值提取出来,并加入到bestTree中adaboostTree.append(bestTree)                     # 将树存入list中存储D=D*np.exp(-alpha.getA()[0][0]*y*bestClasEst)     # 更新权重D,《统计学习方法》李航P139,8.3-8.5,计算Gm(x)的系数D=D/D.sum()                                       # 归一化权重值,统计学习方法》李航P139,8.5,计算Zm# 计算所有分类器的误差,如果为0则终止训练aggClassEst += alpha.getA()[0][0]*bestClasEst     # 分类估计累计值,adaboost是线性运行的,需要将每次的树预测结果相加aggErrors = np.multiply(np.sign(aggClassEst) != np.mat(y),np.ones((m,1))) # aggClassEst每个元素的符号代表分类结果,如果与y不等则表示错误,统计学习方法》李航P138,8.8errorRate = aggErrors.sum()/m                     # 平均分类误差print( "total error: ",errorRate)if errorRate == 0.0:                              # 平均分类误差等于0的,说明数据已经全部分类正确,跳出循环breakreturn adaboostTree,aggClassEstdef adaClassify(data, adaboostTree):"""
对预测数据进行分类:param data: 预测样本x及y:param adaboostTree: 使用训练数据,训练好的决策树:return: 预测样本分类结果"""dataMatrix = np.mat(data)  m = np.shape(dataMatrix)[0]aggClassEst = np.mat(np.zeros((m, 1)))for i in range(len(adaboostTree)):                     # 遍历所有adaboostTree,将估计值累加classEst = splitDataSet(dataMatrix, adaboostTree[i]['column'], adaboostTree[i]['splitValue'], adaboostTree[i]['ineq'])  aggClassEst += adaboostTree[i]['alpha'] * classEst # 分类估计累计值,adaboost是线性运行的,需要将每次的树预测结果相加result = np.sign(aggClassEst)                          # 只取正负号,《统计学习方法》李航P139,8.8return resultdef plotData(dataSet):"""
数据画图"""type1_x1 = []type1_x2 = []type2_x1 = []type2_x2 = []# 取两类x1及x2值画图type1_x1 = dataSet[dataSet[:,-1] == -1][:,:-1][:,0].tolist()type1_x2 = dataSet[dataSet[:,-1] == -1][:,:-1][:,1].tolist()type2_x1 = dataSet[dataSet[:,-1] == 1][:,:-1][:,0].tolist()type2_x2 = dataSet[dataSet[:,-1] == 1][:,:-1][:,1].tolist()# 画点fig = plt.figure()ax = fig.add_subplot(111)ax.scatter(type1_x1,type1_x2, marker='s', s=90)ax.scatter(type2_x1,type2_x2, marker='o', s=50, c='red')plt.title('Adaboost训练数据')if __name__ == '__main__':print('\n1、Adaboost,开始')dataSet = np.array([[ 1. , 2.1, 1 ],[ 2. , 1.1, 1 ],[ 1.3, 1. , -1],[ 1. , 1. , -1],[ 2. , 1. , 1 ]])#classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]# 画图print('\n2、Adaboost数据画图')plotData(dataSet)print('\n3、计算Adaboost树')adaboostTree,aggClassEst=adaboost(dataSet)# 对数据进行分类print('\n4、对[5,5],[0, 0]点,使用Adaboost进行分类:')print( adaClassify([[5,5],[0, 0]], adaboostTree))    

参考资料:
1、《机器学习实战》Peter Harrington著
2、《机器学习》西瓜书,周志华著
3、 斯坦福大学公开课 :机器学习课程
4、机器学习视频,邹博
5、《统计学习方法》李航
6、提升方法
7、分类——组合算法之提升1:AdaBoost提升算法以及Python实现

转载于:https://www.cnblogs.com/hanzi5/p/10105613.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450441.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android studio : clang++.exe: error: invalid linker name in argument '-fuse-ld=bfd

公司jenkins上的C编译器最近换成了clang&#xff0c;今天更新了代码发现本地的C/C代码用NDK编译不过了&#xff0c;提示&#xff1a; “clang.exe: error: invalid linker name in argument -fuse-ldbfd” 解决办法&#xff1a; 将Android.mk文件中的“LOCAL_LDFLAGS -fuse-ld…

(1)初始化项目

2019独角兽企业重金招聘Python工程师标准>>> &#xff08;1&#xff09;初始化项目 1 使用vue-cli初始化项目 vue init webpack my-renren得到以下输出&#xff1a; ? Project name my-renren ? Project description A Vue.js project ? Author neumeng <4048…

使用SpringBoot yml配置文件

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.上一次我们已经使用SpringBoot实现了一个简单的HelloWord程序&#xff0c;辣么接下来我们简单的使用一下他的yml格式的配置文件。 2.在…

软件行业资讯

为什么只有设计师才能发明流行的新语言 先回顾一下知名编程语言的作者和创造时间&#xff1a;Fortran 语言&#xff0c;50年代&#xff0c;IBM 研究员&#xff1b;Lisp 语言&#xff0c;50年代&#xff0c;MIT 的教授和学生&#xff1b;C语言&#xff0c;70年代&#xff0c;贝尔…

电子科大软件系统架构设计——软件建模详细设计

文章目录 软件建模详细设计概述软件建模详细设计目标软件建模详细设计原则开闭原则里氏 (Liskov) 替换原则依赖倒置原则接口分离原则单一职责原则最少知识原则&#xff08;迪米特法则&#xff09;高内聚原则松耦合原则可重用原则 软件建模详细设计内容 UML 软件静态结构视图建模…

120分钟React快速扫盲教程

在教程开端先说些题外话&#xff0c;我喜欢在学习一门新技术或读过一本书后&#xff0c;写一篇教程或总结&#xff0c;既能帮助消化&#xff0c;也能加深印象和发现自己未注意的细节&#xff0c;写的过程其实仍然是一个学习的过程。有个记录的话&#xff0c;在未来需要用到相关…

微信小程序 悬浮按钮

2019独角兽企业重金招聘Python工程师标准>>> 效果视频 https://pan.baidu.com/s/1yfrDaG9YAX0--v0EA3awZA 布局需要按照圆形排列&#xff0c;所以我们需要计算每个点的坐标 代码部分 <view styleposition:fixed; wx:for"{{list}}" wx:for-index"i…

Micronaut教程:如何使用基于JVM的框架构建微服务

\本文要点\\Micronaut是一种基于jvm的现代化全栈框架&#xff0c;用于构建模块化且易于测试的微服务应用程序。\\tMicronaut提供完全的编译时、反射无关的依赖注入和AOP。\\t该框架的开发团队和Grails框架的开发团队是同一个。\\tMicronaut框架集成了云技术&#xff0c;服务发现…

解决Coldfusion连接MySQL数据库的问题

在连接MySQL时&#xff0c;出现了如下错误&#xff1a; Connections to MySQL Community Server are not supported. Please contact MySQL to obtain a MySQL Enterprise or Commercial version. 解决方案&#xff1a; step 1: download the JDBC driver JDBC Driver for MySQ…

C语言union关键字

union 关键字的用法与struct 的用法非常类似。union 维护足够的空间来置放多个数据成员中的“一种”&#xff0c;而不是为每一个数据成员配置空间&#xff0c;在union 中所有的数据成员共用一个空间&#xff0c;同一时间只能储存其中一个数据成员&#xff0c;所有的数据成员具有…

Python学习第一天-第2节

*本节课内容参见&#xff1a;https://www.cnblogs.com/jin-xin/articles/7459977.html运行第一个Python程序 print(hello world) 将文本文件保存为以.py结尾的文件&#xff0c;如hello_world.py &#xff0c;在终端中&#xff0c;运行命令&#xff1a;Python hello_world.py&am…

JDK1.8使用Dubbo时需注意

2019独角兽企业重金招聘Python工程师标准>>> Dubbo自带的很多包都比较旧了&#xff0c;其中的javassist在JDK1.8上运行会报错 而且错误通常比较诡异&#xff0c;javassist是编辑和创建Java字节码的类库&#xff0c;常见的错误会从spring中报出 解决办法&#xff1a;…

深入了解RabbitMQ工作原理及简单使用

深入了解RabbitMQ工作原理及简单使用 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建深入了解RabbitMQ工作原理及简单使用RabbitMQ交换器Exchange介绍与实践RabbitMQ事务和Confirm发送方消息确认——深入解读使用Docker部署RabbitMQ集群你不知道的RabbitMQ集群架构全解RabbitM…

Spring3.2新注解@ControllerAdvice

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 ControllerAdvice&#xff0c;是spring3.2提供的新注解&#xff0c;从名字上可以看出大体意思是控制器增强。让我们先看看ControllerAdv…

C语言关键字

C语言do、while、for关键字—循环 C 语言中循环语句有三种&#xff1a;while 循环、do-while 循环、for 循环。while 循环&#xff1a;先判断while 后面括号里的值&#xff0c;如果为真则执行其后面的代码&#xff1b;否则不执行。while&#xff08;1&#xff09;表示死循环。…

jQuery核心

jQuery(selector) jQuery 的核心功能都是通过这个函数实现的。 jQuery中的一切都基于这个函数&#xff0c;或者说都是在以某种方式使用这个函数。这个函数最基本的用法就是向它传递一个表达式&#xff08;通常由 CSS 选择器组成&#xff09;&#xff0c;然后根据这个表达式来查…

预处理

C语言##预算符 和#运算符一样&#xff0c;##运算符可以用于宏函数的替换部分。这个运算符把两个语言符号组合成单个语言符号。看例子&#xff1a;#define XNAME(n) x ## n如果这样使用宏&#xff1a;XNAME(8)则会被展开成这样&#xff1a;x8看明白了没&#xff1f; ##就是个粘合…

cAdvisor+InfluxDB+Grafana 监控Docker

容器的监控方案其实有很多&#xff0c;有docker自身的docker stats命令、有Scout、有Data Dog等等&#xff0c;本文主要和大家分享一下比较经典的容器开源监控方案组合&#xff1a;cAdvisorInfluxDBGrafan 一、概念 1). InfluxDB是什么nfluxDB是用GO语言编写的一个开源分布式时…

计算机网络知识简单介绍

一、网络基础 1.网络指的是什么&#xff1f; 计算机与计算机之间通过物理链接介质&#xff08;网络设备&#xff09;连接到一起。 计算机与计算机之间基于网络协议通信&#xff08;网络协议就相当于计算机界的英语&#xff09; 2.osi七层协议&#xff1a; 互联网协议按照功能不…

Linux下安装FFmpeg

FFmpeg官网&#xff1a;http://www.ffmpeg.org 官网介绍 FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created. It supports the most obscure…