1.实验内容
本实验介绍AdaBoost算法,并通过实验了解算法的实现过程以及使用scikit-learn工具实现该算法。2.实验目标
通过本实验掌握AdaBoost算法的基本实现,学会使用scikit-learn实现基于AdaBoost的分类器。
3.实验知识点
- AdaBoost
4.实验环境
- python 3.6.5
5.预备知识
- 初等数学知识
- Linux命令基本操作
- Python编程基础
【原理】什么是Adaboost
当我们做重要决定时,大家可能都会多方吸取意见,机器学习处理问题也是如此,我们可以很自然地将不同的分类器组合起来,而这种组合结果则被成为集成方法(ensemble method)或者元算法(meta-algorithm)。
集成方法(ensemble method)通过组合多个基分类器(base classifier)来完成学习任务,颇有点“三个臭皮匠顶个诸葛亮”的意味。基分类器一般采用的是弱可学习(weakly learnable)分类器,通过集成方法,组合成一个强可学习(strongly learnable)分类器。所谓弱可学习,是指学习的正确率仅略优于随机猜测的多项式学习算法;强可学习指正确率较高的多项式学习算法。集成学习的泛化能力一般比单一的基分类器要好,这是因为大部分基分类器都分类错误的概率远低于单一基分类器的。
集成方法主要包括Bagging和Boosting两种方法,Bagging和Boosting都是将已有的分类或回归算法通过一定方式组合起来,形成一个性能更加强大的分类器,更准确的说这是一种分类算法的组装方法,即将弱分类器组装成强分类器的方法。
1、Bagging
自举汇聚法(bootstrap aggregating),也称为bagging方法。Bagging对训练数据采用自举采样(boostrap sampling),即有放回地采样数据,主要思想:
从原始样本集中抽取训练集。每轮从原始样本集中使用Bootstraping的方法抽取n个训练样本(在训练集中,有些样本可能被多次抽取到,而有些样本可能一次都没有被抽中)。共进行k轮抽取,得到k个训练集。(k个训练集之间是相互独立的)
每次使用一个训练集得到一个模型,k个训练集共得到k个模型。(注:这里并没有具体的分类算法或回归方法,我们可以根据具体问题采用不同的分类或回归方法,如决策树、感知器等)
对分类问题:将上步得到的k个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果。(所有模型的重要性相同)
2、Boosting
Boosting是一种与Bagging很类似的技术。Boosting的思路则是采用重赋权(re-weighting)法迭代地训练基分类器,主要思想:
每一轮的训练数据样本赋予一个权重,并且每一轮样本的权值分布依赖上一轮的分类结果。
基分类器之间采用序列式的线性加权方式进行组合。
3、Bagging、Boosting二者之间的区别
样本选择上:
Bagging:训练集是在原始集中有放回选取的,从原始集中选出的各轮训练集之间是独立的。
Boosting:每一轮的训练集不变,只是训练集中每个样例在分类器中的权重发生变化。而权值是根据上一轮的分类结果进行调整。
样例权重:
Bagging:使用均匀取样,每个样例的权重相等。
Boosting:根据错误率不断调整样例的权值,错误率越大则权重越大。
预测函数:
Bagging:所有预测函数的权重相等。
Boosting:每个弱分类器都有相应的权重,对于分类误差小的分类器会有更大的权重。
并行计算:
Bagging:各个预测函数可以并行生成。
Boosting:各个预测函数只能顺序生成,因为后一个模型参数需要前一轮模型的结果。
4、总结
这两种方法都是把若干个分类器整合为一个分类器的方法,只是整合的方式不一样,最终得到不一样的效果,将不同的分类算法套入到此类算法框架中一定程度上会提高了原单一分类器的分类效果,但是也增大了计算量。
下面是将决策树与这些算法框架进行结合所得到的新的算法:
Bagging + 决策树 = 随机森林
AdaBoost + 决策树 = 提升树
Gradient Boosting + 决策树 = GBDT
集成方法众多,本文主要关注Boosting方法中的一种最流行的版本,即AdaBoost。
AdaBoost
AdaBoost算法是基于Boosting思想的机器学习算法,AdaBoost是adaptive boosting(自适应boosting)的缩写,其运行过程如下:
1、计算样本权重
训练数据中的每个样本,赋予其权重,即样本权重,用向量D表示,这些权重都初始化成相等值。假设有n个样本的训练集:
设定每个样本的权重都是相等的,即1/n。
2、计算错误率
利用第一个弱学习算法h1对其进行学习,学习完成后进行错误率ε的统计:
3、计算弱学习算法权重
弱学习算法也有一个权重,用向量α表示,利用错误率计算权重α:
4、更新样本权重
在第一次学习完成后,需要重新调整样本的权重,以使得在第一分类中被错分的样本的权重,在接下来的学习中可以重点对其进行学习:
其中,ht(xi) = yi表示对第i个样本训练正确,不等于则表示分类错误。Zt是一个归一化因子:
这个公式我们可以继续化简,将两个公式进行合并,化简如下:
5、AdaBoost算法
重复进行学习,这样经过t轮的学习后,就会得到t个弱学习算法、权重、弱分类器的输出以及最终的AdaBoost算法的输出,分别如下:
其中,sign(x)是符号函数。具体过程如下所示:
AdaBoost算法总结如下:
准备工作
点击屏幕右上方的下载实验数据模块,选择下载AdaBoost.tgz到指定目录下,然后再依次选择点击上方的File->Open->Upload,上传刚才下载的数据集压缩包,再使用如下命令解压:
!tar -zxvf AdaBoost.tgz
【实验步骤】基于单层决策树构建弱分类器
根据之前的实验我们已经了解了决策树的概念,单层决策树即它仅基于单个特征来做决策,也就是我们的决策树只在树根处分裂一次。
在构造AdaBoost的代码时,我们先使用简单的数据集来确保算法可以正确实现,添加如下代码:
from numpy import *
"""
加载简单数据集
parameters:
null
return:
datMat -数据集
classLabels -数据标签
"""
def loadSimpData():
datMat = matrix([[ 1. , 2.1],
[ 2. , 1.1],
[ 1.3, 1. ],
[ 1. , 1. ],
[ 2. , 1. ]])
classLabels = [1.0, 1.0, -1.0, -1.0, 1.0]
return datMat,classLabels
在下图我们可以看到数据分布情况。此时如果想要试着从某个坐标轴上选择一个值(即单个特征值,此处是与坐标轴平行的直线)来将不同的数据分开,显然是无法满足的。这就是单层决策树难以处理的一个著名问题。
"""
通过阈值比较对数据进行分类
parameters:
dataMatrix -数据矩阵
dimen -第i个特征
threshVal -阈值
threshIneq -不等号标识符(lt 小于、gt大于)
return:
retArray -数据集的分类列表
"""
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):#just classify the data
retArray = ones((shape(dataMatrix)[0],1))#将retArray初始化为(样本数量,1)的全1向量/矩阵
if threshIneq == 'lt':
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #如果threshIneq == 'lt',将dimen维小于threshVal的样本置为-1
else:
retArray[dataMatrix[:,dimen] > threshVal] = -1.0 #如果threshIneq == 'gt',将dimen维大于threshVal的样本置为-1
return retArray
"""
遍历输入值,寻找最佳单层决策树
parameters:
dataArr -数据集
classLabels -分类标签列表
D -权重向量
return:
bestStump -用于存储给定D时得到的最佳单层决策树相关信息
minError -最小的错误率
bestClassEst -类别估计值
"""
def buildStump(dataArr,classLabels,D):
dataMatrix = mat(dataArr);
labelMat = mat(classLabels).T
m,n = shape(dataMatrix)
numSteps = 10.0;
bestStump = {}; #bestStump空词典,用于存储最佳单层决策树的相关信息
bestClasEst = mat(zeros((m,1))) #bestClasEst存储最佳决策树的预测结果
minError = inf #数据分类的错误率,初始化为正无穷大,用于寻找最小错误率
for i in range(n): #遍历数据集中的每一个特征,将每个特征分别作为根节点进行分类
rangeMin = dataMatrix[:,i].min(); #当前特征的特征值的最小值
rangeMax = dataMatrix[:,i].max(); #当前特征的特征值的最大值
stepSize = (rangeMax-rangeMin)/numSteps #根据最值长度来计算步长,我们假定步数为10,即numSteps
for j in range(-1,int(numSteps)+1): #遍历当前特征的每一个步长
for inequal in ['lt', 'gt']: #在大于和小于之间切换不等式
threshVal = (rangeMin + float(j) * stepSize)
predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)
errArr = mat(ones((m,1)))
errArr[predictedVals == labelMat] = 0 #分类错误的样本对应的元素为1,分类正确的样本对应的元素为0
weightedError = D.T*errArr #计算加权错误率
print ("过程—特征 :%d, 阈值为: %.2f, 阈值符号: %s, 加权错误率为: %.3f" % (i, threshVal, inequal, weightedError))
if weightedError < minError:
minError = weightedError
bestClasEst = predictedVals.copy()
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal
return bestStump,minError,bestClasEst
但是如果通过多棵单层决策树,我们就可以构建出一个能够对该数据集正确分类的分类器。而AdaBoost正是如此实现,它需要将多个单层决策树组合起来才能对数据进行正确分类。
那么有了数据,接下来就可以通过构建函数来建立单层决策树。
第一个函数将用于测试是否有某个值小于或者大于我们正在测试的阈值,第二个函数则在一个加权数据集中循环,找到具有最低错误率的单层决策树。
继续在我们的文件中添加如下代码:
"""
通过阈值比较对数据进行分类
parameters:
dataMatrix -数据矩阵
dimen -第i个特征
threshVal -阈值
threshIneq -不等号标识符(lt 小于、gt大于)
return:
retArray -数据集的分类列表
"""
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):#just classify the data
retArray = ones((shape(dataMatrix)[0],1))#将retArray初始化为(样本数量,1)的全1向量/矩阵
if threshIneq == 'lt':
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0 #如果threshIneq == 'lt',将dimen维小于threshVal的样本置为-1
else:
retArray[dataMatrix[:,dimen] > threshVal] = -1.0 #如果threshIneq == 'gt',将dimen维大于threshVal的样本置为-1
return retArray
"""
遍历输入值,寻找最佳单层决策树
parameters:
dataArr -数据集
classLabels -分类标签列表
D -权重向量
return:
bestStump -用于存储给定D时得到的最佳单层决策树相关信息
minError -最小的错误率
bestClassEst -类别估计值
"""
def buildStump(dataArr,classLabels,D):
dataMatrix = mat(dataArr);
labelMat = mat(classLabels).T
m,n = shape(dataMatrix)
numSteps = 10.0;
bestStump = {}; #bestStump空词典,用于存储最佳单层决策树的相关信息
bestClasEst = mat(zeros((m,1))) #bestClasEst存储最佳决策树的预测结果
minError = inf #数据分类的错误率,初始化为正无穷大,用于寻找最小错误率
for i in range(n): #遍历数据集中的每一个特征,将每个特征分别作为根节点进行分类
rangeMin = dataMatrix[:,i].min(); #当前特征的特征值的最小值
rangeMax = dataMatrix[:,i].max(); #当前特征的特征值的最大值
stepSize = (rangeMax-rangeMin)/numSteps #根据最值长度来计算步长,我们假定步数为10,即numSteps
for j in range(-1,int(numSteps)+1): #遍历当前特征的每一个步长
for inequal in ['lt', 'gt']: #在大于和小于之间切换不等式
threshVal = (rangeMin + float(j) * stepSize)
predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)
errArr = mat(ones((m,1)))
errArr[predictedVals == labelMat] = 0 #分类错误的样本对应的元素为1,分类正确的样本对应的元素为0
weightedError = D.T*errArr #计算加权错误率
print ("过程—特征 :%d, 阈值为: %.2f, 阈值符号: %s, 加权错误率为: %.3f" % (i, threshVal, inequal, weightedError))
if weightedError < minError:
minError = weightedError
bestClasEst = predictedVals.copy()
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal
return bestStump,minError,bestClasEst
上述程序中,第一个函数stumpClassify()通过阈值对数据分类,所有在阈值一边的数据将被分到类别-1,另一边的数据则分到类别1,对数据分堆。在分类时,根据传入参数可以基于数据集中的任一元素进行比较,也可以将不等号在大于、小于之间切换。
第二个函数buildStump()将会遍历stumpClassify()函数的所有的可能输入值,并找到数据集上最佳的单层决策树。这里“最佳”是基于权重向量D来定义的。后面可以看到权重向量的具体定义。
在嵌套的三层for循环之内,我们在数据集及三个循环变量上调用stumpClassify()函数来得到分类预测结果。
在代码实现中,我们构建了一个与分类预测结果相同长度的列向量errArr,如果predictedVals中的值不等于labelMat中的真正类别标签值,errArr中对应位置值为1,否则为0.
并计算加权错误率。该错误率是AdaBoost和分类器交互的地方。我们将用于更新权重向量D的值。
到目前为止,我们已经构建了单层决策树的生成函数,即所谓的弱分类器。那么我们说的最重要的权重向量D到底是什么呢?
【实验步骤】基于错误提升分类器的性能
在上一节我们构建了基于加权输入值进行决策的分类器,接下来我们开始实现完整的AdaBoost算法。
整个实现的伪代码如下:
对每次迭代:
利用buildStump()函数找到最佳单层决策树
将最佳单层决策树加入到单层决策数组
计算α
更新权重向量D
更新累计类别估计值
如果错误率等于0.0,则退出循环
那么根据伪代码,继续在我们的文件中添加如下代码:
"""
基于单层决策树的AdaBoost训练过程
parameters:
dataArr - 数据集
classLabels -类别标签
numIt -迭代次数
return:
weakClassArr -分类所需要的所有信息
"""
def adaBoostTrainDS(dataArr,classLabels,numIt=40):
weakClassArr = []#弱分类器数组
m = shape(dataArr)[0]#样本数量
D = mat(ones((m,1))/m) #最初对权重向量D赋予相等的值
aggClassEst = mat(zeros((m,1)))
for i in range(numIt):
#1.建立单层决策树
bestStump,error,classEst = buildStump(dataArr,classLabels,D)
print ("权重向量D:",D.T)
#2.计算alpha值,并避免出现error=0的情况(为了避免分母出现error=0的情况,分母取error和1e-16中的最大值)
alpha = float(0.5*log((1.0-error)/max(error,1e-16)))
bestStump['alpha'] = alpha #存储当前最佳单层决策树的alpha
weakClassArr.append(bestStump) #存储最佳单层决策树
print ("分类标签classEst: ",classEst.T)
#3.根据alpha值来更新D的值,注意计算完D后要对D进行归一化
expon = multiply(-1*alpha*mat(classLabels).T,classEst)
D = multiply(D,exp(expon))
D = D/D.sum()
#在训练错误率为0时,需要提前结束for循环
aggClassEst += alpha*classEst
print ("类别估计累积值aggClassEst: ",aggClassEst.T)
aggErrors = multiply(sign(aggClassEst) != mat(classLabels).T,ones((m,1)))
errorRate = aggErrors.sum()/m
print ("错误率total error: ",errorRate)
if errorRate == 0.0: break
return weakClassArr
实验步骤】实现基于Adaboost分类
添加如下代码:
"""
AdaBoost分类函数
parameters:
datToClass -待分类的数据集
classifierArr -多个弱分类器组成的数组
return:
sign(aggClassEst) -分类结果
"""
def adaClassify(datToClass,classifierArr):
dataMatrix = mat(datToClass) #将待分类样例转换成Numpy矩阵
m = shape(dataMatrix)[0] #得到其中待分类样例的个数
aggClassEst = mat(zeros((m,1)))
for i in range(len(classifierArr)): #迭代每一个弱分类器
#4.使用stumpClassify函数得到每个弱分类器的输出结果,ClassifierArr中保存了各个弱分类器的dimen,threshVal,threshIneq等信息
classEst = stumpClassify(dataMatrix,classifierArr[i]['dim'],\
classifierArr[i]['thresh'],\
classifierArr[i]['ineq'])
#5.计算所有样本的类别估计累计值aggClassEst,每个弱分类器的alpha存储于ClassifierArr的'alpha'中
aggClassEst += classifierArr[i]['alpha']*classEst
print (aggClassEst)
return sign(aggClassEst)
if __name__ =='__main__':
datMat,classLabels =loadSimpData()
classifierArr = adaBoostTrainDS(datMat,classLabels,30)
sign = adaClassify([[0,0],[5,5]],classifierArr)
print(sign)
过程—特征 :0, 阈值为: 0.90, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :0, 阈值为: 0.90, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :0, 阈值为: 1.00, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :0, 阈值为: 1.00, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :0, 阈值为: 1.10, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :0, 阈值为: 1.10, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :0, 阈值为: 1.20, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :0, 阈值为: 1.20, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :0, 阈值为: 1.30, 阈值符号: lt, 加权错误率为: 0.200
过程—特征 :0, 阈值为: 1.30, 阈值符号: gt, 加权错误率为: 0.800
过程—特征 :0, 阈值为: 1.40, 阈值符号: lt, 加权错误率为: 0.200
过程—特征 :0, 阈值为: 1.40, 阈值符号: gt, 加权错误率为: 0.800
过程—特征 :0, 阈值为: 1.50, 阈值符号: lt, 加权错误率为: 0.200
过程—特征 :0, 阈值为: 1.50, 阈值符号: gt, 加权错误率为: 0.800
过程—特征 :0, 阈值为: 1.60, 阈值符号: lt, 加权错误率为: 0.200
过程—特征 :0, 阈值为: 1.60, 阈值符号: gt, 加权错误率为: 0.800
过程—特征 :0, 阈值为: 1.70, 阈值符号: lt, 加权错误率为: 0.200
过程—特征 :0, 阈值为: 1.70, 阈值符号: gt, 加权错误率为: 0.800
过程—特征 :0, 阈值为: 1.80, 阈值符号: lt, 加权错误率为: 0.200
过程—特征 :0, 阈值为: 1.80, 阈值符号: gt, 加权错误率为: 0.800
过程—特征 :0, 阈值为: 1.90, 阈值符号: lt, 加权错误率为: 0.200
过程—特征 :0, 阈值为: 1.90, 阈值符号: gt, 加权错误率为: 0.800
过程—特征 :0, 阈值为: 2.00, 阈值符号: lt, 加权错误率为: 0.600
过程—特征 :0, 阈值为: 2.00, 阈值符号: gt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 0.89, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 0.89, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.00, 阈值符号: lt, 加权错误率为: 0.200
过程—特征 :1, 阈值为: 1.00, 阈值符号: gt, 加权错误率为: 0.800
过程—特征 :1, 阈值为: 1.11, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.11, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.22, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.22, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.33, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.33, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.44, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.44, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.55, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.55, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.66, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.66, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.77, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.77, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.88, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.88, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 1.99, 阈值符号: lt, 加权错误率为: 0.400
过程—特征 :1, 阈值为: 1.99, 阈值符号: gt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 2.10, 阈值符号: lt, 加权错误率为: 0.600
过程—特征 :1, 阈值为: 2.10, 阈值符号: gt, 加权错误率为: 0.400
权重向量D: [[0.2 0.2 0.2 0.2 0.2]]
分类标签classEst: [[-1. 1. -1. -1. 1.]]
类别估计累积值aggClassEst: [[-0.69314718 0.69314718 -0.69314718 -0.69314718 0.69314718]]
错误率total error: 0.2
过程—特征 :0, 阈值为: 0.90, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :0, 阈值为: 0.90, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :0, 阈值为: 1.00, 阈值符号: lt, 加权错误率为: 0.625
过程—特征 :0, 阈值为: 1.00, 阈值符号: gt, 加权错误率为: 0.375
过程—特征 :0, 阈值为: 1.10, 阈值符号: lt, 加权错误率为: 0.625
过程—特征 :0, 阈值为: 1.10, 阈值符号: gt, 加权错误率为: 0.375
过程—特征 :0, 阈值为: 1.20, 阈值符号: lt, 加权错误率为: 0.625
过程—特征 :0, 阈值为: 1.20, 阈值符号: gt, 加权错误率为: 0.375
过程—特征 :0, 阈值为: 1.30, 阈值符号: lt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.30, 阈值符号: gt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.40, 阈值符号: lt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.40, 阈值符号: gt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.50, 阈值符号: lt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.50, 阈值符号: gt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.60, 阈值符号: lt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.60, 阈值符号: gt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.70, 阈值符号: lt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.70, 阈值符号: gt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.80, 阈值符号: lt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.80, 阈值符号: gt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.90, 阈值符号: lt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 1.90, 阈值符号: gt, 加权错误率为: 0.500
过程—特征 :0, 阈值为: 2.00, 阈值符号: lt, 加权错误率为: 0.750
过程—特征 :0, 阈值为: 2.00, 阈值符号: gt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 0.89, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 0.89, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.00, 阈值符号: lt, 加权错误率为: 0.125
过程—特征 :1, 阈值为: 1.00, 阈值符号: gt, 加权错误率为: 0.875
过程—特征 :1, 阈值为: 1.11, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.11, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.22, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.22, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.33, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.33, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.44, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.44, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.55, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.55, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.66, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.66, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.77, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.77, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.88, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.88, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 1.99, 阈值符号: lt, 加权错误率为: 0.250
过程—特征 :1, 阈值为: 1.99, 阈值符号: gt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 2.10, 阈值符号: lt, 加权错误率为: 0.750
过程—特征 :1, 阈值为: 2.10, 阈值符号: gt, 加权错误率为: 0.250
权重向量D: [[0.5 0.125 0.125 0.125 0.125]]
分类标签classEst: [[ 1. 1. -1. -1. -1.]]
类别估计累积值aggClassEst: [[ 0.27980789 1.66610226 -1.66610226 -1.66610226 -0.27980789]]
错误率total error: 0.2
过程—特征 :0, 阈值为: 0.90, 阈值符号: lt, 加权错误率为: 0.143
过程—特征 :0, 阈值为: 0.90, 阈值符号: gt, 加权错误率为: 0.857
过程—特征 :0, 阈值为: 1.00, 阈值符号: lt, 加权错误率为: 0.357
过程—特征 :0, 阈值为: 1.00, 阈值符号: gt, 加权错误率为: 0.643
过程—特征 :0, 阈值为: 1.10, 阈值符号: lt, 加权错误率为: 0.357
过程—特征 :0, 阈值为: 1.10, 阈值符号: gt, 加权错误率为: 0.643
过程—特征 :0, 阈值为: 1.20, 阈值符号: lt, 加权错误率为: 0.357
过程—特征 :0, 阈值为: 1.20, 阈值符号: gt, 加权错误率为: 0.643
过程—特征 :0, 阈值为: 1.30, 阈值符号: lt, 加权错误率为: 0.286
过程—特征 :0, 阈值为: 1.30, 阈值符号: gt, 加权错误率为: 0.714
过程—特征 :0, 阈值为: 1.40, 阈值符号: lt, 加权错误率为: 0.286
过程—特征 :0, 阈值为: 1.40, 阈值符号: gt, 加权错误率为: 0.714
过程—特征 :0, 阈值为: 1.50, 阈值符号: lt, 加权错误率为: 0.286
过程—特征 :0, 阈值为: 1.50, 阈值符号: gt, 加权错误率为: 0.714
过程—特征 :0, 阈值为: 1.60, 阈值符号: lt, 加权错误率为: 0.286
过程—特征 :0, 阈值为: 1.60, 阈值符号: gt, 加权错误率为: 0.714
过程—特征 :0, 阈值为: 1.70, 阈值符号: lt, 加权错误率为: 0.286
过程—特征 :0, 阈值为: 1.70, 阈值符号: gt, 加权错误率为: 0.714
过程—特征 :0, 阈值为: 1.80, 阈值符号: lt, 加权错误率为: 0.286
过程—特征 :0, 阈值为: 1.80, 阈值符号: gt, 加权错误率为: 0.714
过程—特征 :0, 阈值为: 1.90, 阈值符号: lt, 加权错误率为: 0.286
过程—特征 :0, 阈值为: 1.90, 阈值符号: gt, 加权错误率为: 0.714
过程—特征 :0, 阈值为: 2.00, 阈值符号: lt, 加权错误率为: 0.857
过程—特征 :0, 阈值为: 2.00, 阈值符号: gt, 加权错误率为: 0.143
过程—特征 :1, 阈值为: 0.89, 阈值符号: lt, 加权错误率为: 0.143
过程—特征 :1, 阈值为: 0.89, 阈值符号: gt, 加权错误率为: 0.857
过程—特征 :1, 阈值为: 1.00, 阈值符号: lt, 加权错误率为: 0.500
过程—特征 :1, 阈值为: 1.00, 阈值符号: gt, 加权错误率为: 0.500
过程—特征 :1, 阈值为: 1.11, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.11, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 1.22, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.22, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 1.33, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.33, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 1.44, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.44, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 1.55, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.55, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 1.66, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.66, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 1.77, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.77, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 1.88, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.88, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 1.99, 阈值符号: lt, 加权错误率为: 0.571
过程—特征 :1, 阈值为: 1.99, 阈值符号: gt, 加权错误率为: 0.429
过程—特征 :1, 阈值为: 2.10, 阈值符号: lt, 加权错误率为: 0.857
过程—特征 :1, 阈值为: 2.10, 阈值符号: gt, 加权错误率为: 0.143
权重向量D: [[0.28571429 0.07142857 0.07142857 0.07142857 0.5 ]]
分类标签classEst: [[1. 1. 1. 1. 1.]]
类别估计累积值aggClassEst: [[ 1.17568763 2.56198199 -0.77022252 -0.77022252 0.61607184]]
错误率total error: 0.0
[[-0.69314718]
[ 0.69314718]]
[[-1.66610226]
[ 1.66610226]]
[[-2.56198199]
[ 2.56198199]]
[[-1.]
[ 1.]]
从运行结果,我们可以看出:
在第一轮迭代中,D中的所有值都相等。于是,只有第一个数据点被错分了。
因此在第二轮迭代中,D向量给第一个数据点0.5的权重。这就可以通过变量aggClassEst的符号来了解总的类别。
第二次迭代之后,我们就会发现第一个数据点已经正确分类了,但此时最后一个数据点却是错分了。
D向量中的最后一个元素变为0.5,而D向量中的其他值都变得非常小。
最后,第三次迭代之后aggClassEst所有值的符号和真是类别标签都完全吻合,那么训练错误率为0,程序终止运行。
最后训练结果包含了三个弱分类器,其中包含了分类所需要的所有信息。一共迭代了3次,所以训练了3个弱分类器构成一个使用AdaBoost算法优化过的分类器,分类器的错误率为0。
一旦拥有了多个弱分类器以及其对应的alpha值,进行测试就变得想当容易了。
该函数遍历所有训练得到的弱分类器,利用单层决策树,输出的类别估计值乘以该单层决策树的分类器权重alpha,然后累加到aggClassEst上,最后通过sign函数最终的结果。可以看到,分类没有问题,(5,5)属于正类,(0,0)属于负类。