集成方法: ensemble method(元算法: meta algorithm) 概述
- 概念:是对其他算法进行组合的一种形式
- 通俗解释:做重要决定,综合多个专家的意见。机器学习处理问题时又何尝不是如此? 这就是集成方法背后的思想。
- 集成方法
投票选举(bagging: 自举汇聚法 bootstrap aggregating): 是基于数据随机重抽样分类器构造的方法。新数据集和原数据集的大小相等。每个数据集都是通过在原始 数据集中随机选择一个样本来进行替换而得到的。
再学习(boosting): 是基于所有分类器的加权求和的方法。boosting中的分类器权重并不相等,每个权重代表的是 其对应分类器在上一轮迭代中的成功度。
AdaBoost (adaptive boosting: 自适应 boosting) 概述
AdaBoost 优缺点
优点:泛化错误率低,易编码,可以应用在大部分分类器上,无参数调整。
缺点:对离群点敏感。 适用数据类型:数值型和标称型数据。
AdaBoost的一般流程
(1) 收集数据:可以使用任意方法。
(2) 准备数据:依赖于所使用的弱分类器类型,本章使用的是单层决策树,这种分类器可 以处理任何数据类型。当然也可以使用任意分类器作为弱分类器,第2章到第6章中的 任一分类器都可以充当弱分类器。作为弱分类器,简单分类器的效果更好。
(3) 分析数据:可以使用任意方法。
(4) 训练算法:AdaBoost的大部分时间都用在训练上,分类器将多次在同一数据集上训练 弱分类器。
(5) 测试算法:计算分类的错误率。
(6) 使用算法:同SVM一样,AdaBoost预测两个类别中的一个。如果想把它应用到多个类 别的场合,那么就要像多类SVM中的做法一样对AdaBoost进行修改。
训练算法:基于错误提升分类器的性能
能否使用弱分类器和多个实例来构建一个强分类器?这里的弱是指的着分类器的性能比随机猜测要略好但不会好太多。这就是说,在二分类情况下 弱分类器的错误率会高于50%,而“强”分类器的错误率将会低很多。AdaBoost算法即脱胎于上 述理论问题
AdaBoost是adaptive boosting(自适应boosting)的缩写。其运行过程如下:训练数据中的每 个样本,并赋予其一个权重,这些权重构成了向量D。一开始,这些权重都初始化成相等值。首 先在训练数据上训练出一个弱分类器并计算该分类器的错误率,然后在同一数据集上再次训练弱分类器。 在分类器的第二次训练当中,将会重新调整每个样本的权重,其中第一次分对的样本的 权重将会降低,而第一次分错的样本的权重将会提高。 为了从所有弱分类器中得到终的分类结 果,AdaBoost为每个分类器都分配了一个权重值alpha,这些alpha值是基于每个弱分类器的错误 率进行计算的。其中,错误率ε的定义为:
而alpha的计算公式如下:
AdaBoost 工作原理流程图
计算出alpha值之后,可以对权重向量D进行更新,以使得那些正确分类的样本的权重降低而 错分样本的权重升高。D的计算方法如下
如果某个样本被正确分类,那么该样本的权重更改为:
而如果某个样本被错分,那么该样本的权重更改为:
在计算出D之后,AdaBoost又开始进入下一轮迭代。AdaBoost算法会不断地重复训练和调整 权重的过程,直到训练错误率为0或者弱分类器的数目达到用户的指定值为止。
项目案例: 马疝病的预测
项目流程图
基于单层决策树构建弱分类器
- 单层决策树(decision stump, 也称决策树桩)是一种简单的决策树
项目概述
预测患有疝气病的马的存活问题,这里的数据包括368个样本和28个特征,疝气病是描述马胃肠痛的术语,然而,这种病并不一定源自马的胃肠问题,其他问题也可能引发疝气病,该数据集中包含了医院检测马疝气病的一些指标,有的指标比较主观,有的指标难以测量,例如马的疼痛级别。另外,除了部分指标主观和难以测量之外,该数据还存在一个问题,数据集中有30%的值是缺失的。
开发流程
收集数据:提供的文本文件
准备数据:确保类别标签是+1和-1,而非1和0
分析数据:统计分析
训练算法:在数据上,利用adaBoostTrainDS() 函数训练出一系列的分类器
测试算法:我们拥有两个数据集。在不采用随机抽样的方法下,我们就会对AdaBoost 和 Logistic 回归的结果进行完全对等的比较
使用算法:观察该例子上的错误率。不过,也可以构建一个 Web网站,让驯马师输入马的症状然后预测马是否会死去
收集数据:提供的文本文件
训练数据:horseColicTraining.txt
测试数据:horseColicTest.txt
2.000000 1.000000 38.500000 66.000000 28.000000 3.000000 3.000000 0.000000 2.000000 5.000000 4.000000 4.000000 0.000000 0.000000 0.000000 3.000000 5.000000 45.000000 8.400000 0.000000 0.000000 -1.000000
1.000000 1.000000 39.200000 88.000000 20.000000 0.000000 0.000000 4.000000 1.000000 3.000000 4.000000 2.000000 0.000000 0.000000 0.000000 4.000000 2.000000 50.000000 85.000000 2.000000 2.000000 -1.000000
2.000000 1.000000 38.300000 40.000000 24.000000 1.000000 1.000000 3.000000 1.000000 3.000000 3.000000 1.000000 0.000000 0.000000 0.000000 1.000000 1.000000 33.000000 6.700000 0.000000 0.000000 1.000000
准备数据:确保类别标签是+1和-1,而非1和0
def loadDataSet(fileName):
# 获取 feature 的数量, 便于获取
numFeat = len(open(fileName).readline().split('\t'))
dataArr = []
labelArr = []
fr = open(fileName)
for line in fr.readlines():
lineArr = []
curLine = line.strip().split('\t')
for i in range(numFeat-1):
lineArr.append(float(curLine[i]))
dataArr.append(lineArr)
labelArr.append(float(curLine[-1]))
return dataArr, labelArr
分析数据:统计分析
过拟合(overfitting, 也称为过学习)
发现测试错误率在达到一个最小值之后有开始上升,这种现象称为过拟合。
- 通俗来说:就是把一些噪音数据也拟合进去的,如下图。
训练算法:在数据上,利用 adaBoostTrainDS() 函数训练出一系列的分类器
def adaBoostTrainDS(dataArr, labelArr, numIt=40):
"""adaBoostTrainDS(adaBoost训练过程放大)
Args:
dataArr 特征标签集合
labelArr 分类标签集合
numIt 实例数
Returns:
weakClassArr 弱分类器的集合
aggClassEst 预测的分类结果值
"""
weakClassArr = []
m = shape(dataArr)[0]
# 初始化 D,设置每个样本的权重值,平均分为m份
D = mat(ones((m, 1))/m)
aggClassEst = mat(zeros((m, 1)))
for i in range(numIt):
# 得到决策树的模型
bestStump, error, classEst = buildStump(dataArr, labelArr, D)
# alpha目的主要是计算每一个分类器实例的权重(组合就是分类结果)
# 计算每个分类器的alpha权重值
alpha = float(0.5*log((1.0-error)/max(error, 1e-16)))
bestStump['alpha'] = alpha
# store Stump Params in Array
weakClassArr.append(bestStump)
print "alpha=%s, classEst=%s, bestStump=%s, error=%s " % (alpha, classEst.T, bestStump, error)
# 分类正确:乘积为1,不会影响结果,-1主要是下面求e的-alpha次方
# 分类错误:乘积为 -1,结果会受影响,所以也乘以 -1
expon = multiply(-1*alpha*mat(labelArr).T, classEst)
print '(-1取反)预测值expon=', expon.T
# 计算e的expon次方,然后计算得到一个综合的概率的值
# 结果发现: 判断错误的样本,D中相对应的样本权重值会变大。
D = multiply(D, exp(expon))
D = D/D.sum()
# 预测的分类结果值,在上一轮结果的基础上,进行加和操作
print '当前的分类结果:', alpha*classEst.T
aggClassEst += alpha*classEst
print "叠加后的分类结果aggClassEst: ", aggClassEst.T
# sign 判断正为1, 0为0, 负为-1,通过最终加和的权重值,判断符号。
# 结果为:错误的样本标签集合,因为是 !=,那么结果就是0 正, 1 负
aggErrors = multiply(sign(aggClassEst) != mat(labelArr).T, ones((m, 1)))
errorRate = aggErrors.sum()/m
# print "total error=%s " % (errorRate)
if errorRate == 0.0:
break
return weakClassArr, aggClassEst
发现:
alpha (模型权重)目的主要是计算每一个分类器实例的权重(加和就是分类结果)
分类的权重值:最大的值= alpha 的加和,最小值=-最大值
D (样本权重)的目的是为了计算错误概率: weightedError = D.T*errArr,求最佳分类器
样本的权重值:如果一个值误判的几率越小,那么 D 的样本权重越小
测试算法:我们拥有两个数据集。在不采用随机抽样的方法下,我们就会对 AdaBoost 和 Logistic 回归的结果进行完全对等的比较
def adaClassify(datToClass, classifierArr):
"""adaClassify(ada分类测试)
Args:
datToClass 多个待分类的样例
classifierArr 弱分类器的集合
Returns:
sign(aggClassEst) 分类结果
"""
# do stuff similar to last aggClassEst in adaBoostTrainDS
dataMat = mat(datToClass)
m = shape(dataMat)[0]
aggClassEst = mat(zeros((m, 1)))
# 循环 多个分类器
for i in range(len(classifierArr)):
# 前提: 我们已经知道了最佳的分类器的实例
# 通过分类器来核算每一次的分类结果,然后通过alpha*每一次的结果 得到最后的权重加和的值。
classEst = stumpClassify(dataMat, classifierArr[i]['dim'], classifierArr[i]['thresh'], classifierArr[i]['ineq'])
aggClassEst += classifierArr[i]['alpha']*classEst
return sign(aggClassEst)
使用算法:观察该例子上的错误率。不过,也可以构建一个 Web 网站,让驯马师输入马的症状然后预测马是否会死去。
# 马疝病数据集
# 训练集合
dataArr, labelArr = loadDataSet("data/7.AdaBoost/horseColicTraining2.txt")
weakClassArr, aggClassEst = adaBoostTrainDS(dataArr, labelArr, 40)
print weakClassArr, '\n-----\n', aggClassEst.T
# 计算ROC下面的AUC的面积大小
plotROC(aggClassEst.T, labelArr)
# 测试集合
dataArrTest, labelArrTest = loadDataSet("data/7.AdaBoost/horseColicTest2.txt")
m = shape(dataArrTest)[0]
predicting10 = adaClassify(dataArrTest, weakClassArr)
errArr = mat(ones((m, 1)))
# 测试:计算总样本数,错误样本数,错误率
print m, errArr[predicting10 != mat(labelArrTest).T].sum(), errArr[predicting10 != mat(labelArrTest).T].sum()/m
来源:CSDN
作者:Pang_ling
链接:https://blog.csdn.net/Pang_ling/article/details/103599156