失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 机器学习实战 -- 利用AdaBoost 元算法提高分类性能

机器学习实战 -- 利用AdaBoost 元算法提高分类性能

时间:2022-09-22 12:13:58

相关推荐

机器学习实战 -- 利用AdaBoost 元算法提高分类性能

组合相似的分类器来提高分类性能应用AdaBoost算法处理非均衡分类问题

元算法是对其他算法进行组合的一种方式。

基于数据集多重抽样的分类器

我们可以将不同的分类器组合起来,而这种组合结果被称为集成方法或者元算法。使用集成方法时会有很多种形式:可以是不同算法的集成,也可以是同一算法在不同设置下的集成,还可以数据集不同部分分配给不同分类器之后的集成。

AdaBoost

优点:泛化错误低,易于编程,适用于大多数分类器,无需参数调整

缺点:对异常值敏感

适用范围:数值和标称值

bagging : 基于数据随机重抽样的分类器构建方法

自举汇聚法(Bootstrap aggreging),即Bagging 方法 .

(1)生成S 新数据集:从原始数据集中抽取数据S次,生成S个新数据集。新数据集的大小与原始数据集相同,数据是从原始数据集中随机抽取得到。新数据集允许包含重复数据,或不包含原始数据集中的某些数据。

(2)训练:新建S 个数据集后,分别对每个数据集应用一种学习算法,得到S 个分类器。

(3)推理:S 个分类器分别对新数据预测,然后投票多数表决。

Boosting

Boosting:各分类器依次串行训练,每个新分类器都专注于处理其之前分类器错分的数据。Boosting的输出是所有分类器输出的加权和,各分类器权重(weights)取决于前次迭代各分类器的表现。

AdaBoost 的一般流程

收集数据集 :

准备数据 : 依赖于所使用的弱分类器的类型,本次使用的是单层决策树,这种分类器可以处理任何数据类型。

分析数据 :

训练算法 : AdaBoost 的大部分时间都用在训练上,分类器将多次在同年以数据集上训练弱分类器。

测试算法 : 计算分类的错误率

使用算法 : 预测两个类别中的一个

训练算法 : 基于错误提升分类器的性能

算法步骤 :

训练数据集中的每一个样本,并赋予其一个权重,这些权重构成了向量 D 。

数据集 : , i = 1 ,2 , .. ,m 。为训练集中每条样本 分配一个权重 di , 组成向量 D =

初始化 : 一开始这些权重都是相同值

首先在训练集上训练出一个弱分类器并计算该分类器的错误率,然后在同一数据集上再次训练弱分类器。

然后在同一数据集上再次训练弱分类器。第二次训练当中,将会调整每个样本的权重, 其中第一次分对的权重会降低,

分错的权重会提高。

为了从所有的弱分类器中得到最终的分类结果,AdaBoost 为每个分类器都分配了一个权重值 alpha ,这些alpha 值是基于每个弱分类器的错误率进行计算的。错误率 :

未正确分类的样本数目/ 所有的样本数目

而 alpha 的计算公式:

计算流程图 :

左侧为数据集,条形图的宽度表示每条样本的权重。样本加权后经弱分类器预测, 预测结果经加权(α \alphaα)累加作为最终输出。

计算出 alpha 后 ,可以对权重向量 D 进行更新 ,以使那些正确分类的样本的权重降低而错误分类的样本的权重升高。

如果某个样本被正确分类 , 那么该样本的权重改为 :

如果某个样本被错误分类,那么该样本的权重更改为 :

终止条件:训练错误为0或弱分类器的数量达到用户定义的值。

基于单层决策树构建弱分类器

import numpy as npimport matplotlib.pyplot as pltdef loadSimpData() :datMat = np.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,classLabelsdef plotData(datMat ,classLabels):x1 = [] ; x2 = []y1 = [] ; y2 = []DataSize = len(classLabels)datArr = np.array(datMat)for i in range(DataSize) :if int(classLabels[i]) == 1 :x1.append(datArr[i,0])y1.append(datArr[i,1] )elif int(classLabels[i]) == -1:x2.append(datArr[i,0])y2.append(datArr[i,1])plt.scatter(x1,y1,c='r',marker='o',label="Class 1")plt.scatter(x2,y2,c='b',marker='s',label ="Class 2")plt.legend()plt.show()datMat ,classLabels = loadSimpData()plotData(datMat,classLabels)

有了数据,接下来就可以通过构建多个函数来建立单层决策树。

第一个函数用来测试是否有某个值小于或者大于我们正在测试的阈值。第二个函数则更加复杂一点,她会在一个加权数据集中循环,并找到具有最低错误率的单层决策树。

伪代码:

将最小错误率minError 设为 inf FOR 遍历训练数据集样本特征:FOR 遍历判决门限:FOR 遍历不等式类型:单层决策树对训练数据集分类对训练数据集分类结果加权IF 误差 < $minError$:SET 最佳单层决策树 = 该单层决策树ENDENDENDENDRETURN 最佳单层决策树

单层决策树生成函数

# 单层决策树生成函数def stumpClassify(dataMatrix, dimen, threshVal, thershIneq):''':param dataMatrix::param dimen::param threshVal: 阈值:param thershIneq::return:'''retArray = np.ones((dataMatrix.shape[0], 1))if thershIneq == "lt":retArray[dataMatrix[:, dimen] <= threshVal] = - 1else:retArray[dataMatrix[:, dimen] > threshVal] = - 1return retArraydef buildStump(dataArr, classLabels, D):dataMatrix = np.matrix(dataArr)labelMat = np.matrix(classLabels).transpose()m, n = dataMatrix.shapenumSteps = 10bestStump = {}bestClasEst = np.matrix(np.zeros((m, 1)))minError = np.inffor i in range(n):rangeMin = dataMatrix[:, i].min()rangeMax = dataMatrix[:, i].max()stepSize = (rangeMax - rangeMin) / numStepsfor j in range(-1, numSteps + 1):for inequal in ["lt", "gt"]:threshVal = rangeMin + j * stepSizepredictedVals = stumpClassify(dataMatrix, i, threshVal, inequal)errArr = np.matrix(np.ones((m, 1)))errArr[predictedVals == labelMat] = 0# calculate weighted errorweightedError = np.dot(D.T, errArr)# print("split: dim {}, thresh {}, thresh ineqal: {}, the weighted error is {}" \# .format(i, threshVal, inequal, weightedError))if weightedError < minError:minError = weightedErrorbestClasEst = predictedVals.copy()bestStump["dim"] = ibestStump["thresh"] = threshValbestStump["ineq"] = inequalreturn bestStump, minError, bestClasEst

D = np.matrix(np.ones((5, 1)) / 5)print(buildStump(datMat, classLabels, D))({'dim': 0, 'thresh': 1.3, 'ineq': 'lt'}, matrix([[0.2]]), array([[-1.],[ 1.],[-1.],[-1.],[ 1.]]))

stumpClassify():单层决策树分类器

输入:训练数据集所有样本,特征索引,判决门限,不等式类型

输出:训练数据集所有样本预测标签向量

buildStump():构建最佳单层决策树分类器

输入:训练数据集(样本、标签),样本权值

输出:最佳单层决策树分类器

buildStump()首先遍历样本特征;然后对于每个特征,设置不同的门限和不等式类型,比较分类结果;计算加权分类误差,,得到最佳单层决策树。

AdaBoost算法实现

FOR EACH 迭代:调用buildStump()计算最佳单层决策树将最佳单层决策树加入单层决策树列表计算$\alpha$计算新的权值向量$\mathbf{D}$更新累积类别估计IF 错误率 == 0BREAKEND IFEND FOR

# 基于单层决策树的AdaBoost 训练过程def adaBoostTrainDS(dataArr, classLabels, numIt=40):weakClassArr = []m = dataArr.shape[0]D = np.matrix(np.ones((m, 1)) / m)aggClassEst = np.matrix(np.zeros((m, 1)))for i in range(numIt):print("D: {}".format(D.T))bestStump, error, classEst = buildStump(dataArr, classLabels, D)alpha = float(0.5 * np.log((1 - error) / max(error, 1e-16)))bestStump["alpha"] = alphaweakClassArr.append(bestStump)print("classEst: {}".format(classEst.T))# calculate D for next iterationexpon = -1 * alpha * np.multiply(np.matrix(classLabels).T,classEst)D = np.multiply(D, np.exp(expon))D = D / D.sum()# aggregate error calculationaggClassEst += alpha * classEstprint("aggClassEst: {}".format(aggClassEst.T))aggErrors = np.multiply(np.sign(aggClassEst) != np.matrix(classLabels).T,np.ones((m, 1)))errorRate = aggErrors.sum() / mprint("total error: {}\n".format(errorRate))if errorRate == 0:breakreturn weakClassArr

ans = classifierArray = adaBoostTrainDS(datMat,classLabels,9)print(ans)

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.2D: [[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.2D: [[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[{'dim': 0, 'thresh': 1.3, 'ineq': 'lt', 'alpha': 0.6931471805599453}, {'dim': 1, 'thresh': 1.0, 'ineq': 'lt', 'alpha': 0.9729550745276565}, {'dim': 0, 'thresh': 0.9, 'ineq': 'lt', 'alpha': 0.8958797346140273}]

AdaBoost分类测试

def adaClassify(datToClass, classifierArr):dataMatrix = np.matrix(datToClass)m = dataMatrix.shape[0]aggClassEst = np.matrix(np.zeros((m, 1)))for i in range(len(classifierArr)):classEst = stumpClassify(dataMatrix,classifierArr[i]["dim"],classifierArr[i]["thresh"],classifierArr[i]["ineq"])aggClassEst += classifierArr[i]["alpha"] * classEst# print(aggClassEst)return np.sign(aggClassEst)

classifierArr = adaBoostTrainDS(datMat,classLabels,30) classifir = adaClassify([[0,0],[5,5]],classifierArr)print(classifir)

[[-1.][ 1.]]

可以看到分类结果还可以。

示例 : 在一个难数据集上应用AdaBoost

利用多个单层决策树和 AdaBoost 预测患有马疝病的马是否能够存活。

采集:

预处理:确保样本标签是+1 和−1

分析:

训练:使用adaBoostTrainDS()函数训练分类器

测试:与逻辑回归预测结果同类比较(apples-to-apples comparison)

使用:二元分类

def loadDataSet(fileName):dataMat = []labelMat = []with open(fileName, "r") as fr:for line in fr.readlines():curLine = line.strip().split('\t')dataMat.append([float(item) for item in curLine[0: -1]])labelMat.append(float(curLine[-1]))dataMat = np.array(dataMat)labelMat = np.array(labelMat)labelMat[labelMat == 0] = -1return dataMat, labelMat

datArr, labelArr = loadDataSet("horseColicTraining.txt")classifierArray = adaBoostTrainDS(datArr, labelArr)print(classifierArray)

[{'dim': 9, 'thresh': 3.0, 'ineq': 'gt', 'alpha': 0.4616623792657674}, {'dim': 17, 'thresh': 52.5, 'ineq': 'gt', 'alpha': 0.31248245042467104}, {'dim': 3, 'thresh': 55.199999999999996, 'ineq': 'gt', 'alpha': 0.286809739577}, {'dim': 18, 'thresh': 62.300000000000004, 'ineq': 'lt', 'alpha': 0.23297004638939506}, {'dim': 10, 'thresh': 0.0, 'ineq': 'lt', 'alpha': 0.19803846151213741}, {'dim': 5, 'thresh': 2.0, 'ineq': 'gt', 'alpha': 0.18847887349020634}, {'dim': 12, 'thresh': 1.2, 'ineq': 'lt', 'alpha': 0.15227368997476778}, {'dim': 7, 'thresh': 1.2, 'ineq': 'gt', 'alpha': 0.15510870821690512}, {'dim': 5, 'thresh': 0.0, 'ineq': 'lt', 'alpha': 0.13536197353359405}, {'dim': 4, 'thresh': 28.799999999999997, 'ineq': 'lt', 'alpha': 0.12521587326132078}, {'dim': 11, 'thresh': 2.0, 'ineq': 'gt', 'alpha': 0.1334764812820767}, {'dim': 9, 'thresh': 4.0, 'ineq': 'lt', 'alpha': 0.1418224325377107}, {'dim': 14, 'thresh': 0.0, 'ineq': 'gt', 'alpha': 0.10264268449708028}, {'dim': 0, 'thresh': 1.0, 'ineq': 'lt', 'alpha': 0.11883732872109484}, {'dim': 4, 'thresh': 19.2, 'ineq': 'gt', 'alpha': 0.09879216527106625}, {'dim': 2, 'thresh': 36.72, 'ineq': 'lt', 'alpha': 0.12029960885056867}, {'dim': 3, 'thresh': 92.0, 'ineq': 'lt', 'alpha': 0.10846927663989175}, {'dim': 15, 'thresh': 0.0, 'ineq': 'lt', 'alpha': 0.09652967982091411}, {'dim': 3, 'thresh': 73.6, 'ineq': 'gt', 'alpha': 0.0895851530927}, {'dim': 18, 'thresh': 8.9, 'ineq': 'lt', 'alpha': 0.09210361961272426}, {'dim': 16, 'thresh': 4.0, 'ineq': 'gt', 'alpha': 0.10464142217079622}, {'dim': 11, 'thresh': 3.2, 'ineq': 'lt', 'alpha': 0.09575457291711606}, {'dim': 20, 'thresh': 0.0, 'ineq': 'gt', 'alpha': 0.09624217440331524}, {'dim': 17, 'thresh': 37.5, 'ineq': 'lt', 'alpha': 0.0785966288518967}, {'dim': 9, 'thresh': 2.0, 'ineq': 'lt', 'alpha': 0.0714286363455072}, {'dim': 5, 'thresh': 2.0, 'ineq': 'gt', 'alpha': 0.07830753154662214}, {'dim': 4, 'thresh': 28.799999999999997, 'ineq': 'lt', 'alpha': 0.07606159074712784}, {'dim': 4, 'thresh': 19.2, 'ineq': 'gt', 'alpha': 0.08306752811081955}, {'dim': 7, 'thresh': 4.2, 'ineq': 'gt', 'alpha': 0.0830416741141175}, {'dim': 3, 'thresh': 92.0, 'ineq': 'lt', 'alpha': 0.08893356802801224}, {'dim': 14, 'thresh': 3.0, 'ineq': 'gt', 'alpha': 0.07000509315417908}, {'dim': 7, 'thresh': 5.3999999999999995, 'ineq': 'lt', 'alpha': 0.07697582358565964}, {'dim': 18, 'thresh': 0.0, 'ineq': 'lt', 'alpha': 0.08507457442866707}, {'dim': 5, 'thresh': 3.2, 'ineq': 'lt', 'alpha': 0.0676590387302069}, {'dim': 7, 'thresh': 3.0, 'ineq': 'gt', 'alpha': 0.08045680822237049}, {'dim': 12, 'thresh': 1.2, 'ineq': 'lt', 'alpha': 0.05616862921969557}, {'dim': 11, 'thresh': 2.0, 'ineq': 'gt', 'alpha': 0.06454264376249863}, {'dim': 7, 'thresh': 5.3999999999999995, 'ineq': 'lt', 'alpha': 0.05308888435382875}, {'dim': 11, 'thresh': 0.0, 'ineq': 'lt', 'alpha': 0.0734605861478849}, {'dim': 13, 'thresh': 0.0, 'ineq': 'gt', 'alpha': 0.07872267320907414}]

testArr, testLabelArr = loadDataSet("horseColicTest.txt")prediction10 = adaClassify(testArr, classifierArray)m = prediction10.shape[0]errArr = np.ones((m, 1))err_rate = errArr[prediction10 != np.expand_dims(testLabelArr, axis=1)].sum() / mprint("error rate is {}%".format(err_rate * 100))

error rate is 19.402985074626866%

如果觉得《机器学习实战 -- 利用AdaBoost 元算法提高分类性能》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。