一、元算法、集成方法概念
1.怎么使弱学习转化为强学习?
核心思想:通过组合使弱学习互补
因为学习是不适定问题,在有限样本上,不同学习方法得到不同“规则”,并在不同的情况下失效,没有一种学习算法总是在任何领域下产生最好的分类效果。
2.元算法:对不同的算法组合的一种方式。我们可以把不同分类器进行组合,这种组合结果被称为集成方法或元算法。
3.使用集成方法的形式:
1)不同算法的集成
2)同一算法在不同设置下的集成
3)数据集不同部分分配给不同分类器的集成
二、bagging和boosting
1.bagging:自举汇聚法(bootstrp aggregating)就是从原始数据集里选出和原始数据集同等大小的数据组合成新的数据集的技术。选取的数据可以重复。生成n个新数据集就将某个分类算法分别作用于每个数据集得到n个分类器。选择分类器投票结果中最多的类别作为最后的分类结果。
2.boosting:不同分类器通过串行训练得到,每个分类器都根据已经训练出的分类器性能来进行训练,boosting在关注前一个弱分类器错分的部分,给与更大权值。
3.主要区别:bagging是并行,分类器权值是相等的,靠“运气”;boosting是串行,分类器权值不等,每个权重代表的是其对应分类器在上一轮迭代中的成功度,有“依据”。
三、AdaBoost算法
AdaBoost就是最流行的元算法,boosting的一个版本,也被很多人认为是最好的监督学习方法。
1.AdaBoost核心思想:“关注”被错分的样本,“器重”性能好的分类器。
2.怎么实现:
1)不同的训练集→调整样本权重
2)“关注”→增加错分样本权重
3)“器重”→好的分类器权重大
4)样本权重间接影响分类器权重
3.优缺点:
优点:泛化错误率低,易编码,可以用在大部分分类器上,无参数调整。
缺点:对离群点敏感。
适用数据类型:数值型和标称型
4.这里的AdBoost其实最主要就是两个过程:一个是找样本权重,错分的权重变大一些;一个是找分类器权重,性能好的权重设置大一些
分类器权重根据每个弱分类器错误率求出:
错误率ε的定义:
alpha计算公式如下:
如果某个样本被正确分类,则样本权重为:
如果某个样本被错误分类,则样本权重为:
三、机器学习实战里的主要代码
from numpy import *
#加载一个简单的数据集
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
#单层决策树分类
#通过阈值比对对数据分类
#dataMatrix为数据,dimen为某一特征,threshVal为阈值,threshIneq为阈值比对方式
#这里的类别用1和-1
def stumpClassify(dataMatrix,dimen,threshVal,threshIneq):#just classify the data
retArray = ones((shape(dataMatrix)[0],1))
if threshIneq == 'lt':
retArray[dataMatrix[:,dimen] <= threshVal] = -1.0
else:
retArray[dataMatrix[:,dimen] > threshVal] = -1.0
return retArray
#创建单层决策树
#dataArr输入数据,classLabels类别,D权重向量
def buildStump(dataArr,classLabels,D):
dataMatrix = mat(dataArr); labelMat = mat(classLabels).T
m,n = shape(dataMatrix)
numSteps = 10.0;#一共分成的步数
bestStump = {};#这个dict用来存储最好的划分方案的一些参数信息
bestClasEst = mat(zeros((m,1)))
minError = inf #初始化为无穷大,方便以后每次减小它
for i in range(n):#遍历每个特征
rangeMin = dataMatrix[:,i].min(); rangeMax = dataMatrix[:,i].max();
stepSize = (rangeMax-rangeMin)/numSteps#根据步数和该特征的范围求出每次步长
for j in range(-1,int(numSteps)+1):#遍历当前特征的每个数据
for inequal in ['lt', 'gt']: #go over less than and greater than,遍历两个对比方式
threshVal = (rangeMin + float(j) * stepSize)
predictedVals = stumpClassify(dataMatrix,i,threshVal,inequal)#call stump classify with i, j, lessThan
errArr = mat(ones((m,1)))
errArr[predictedVals == labelMat] = 0#预测对的错误就是0
print "predictedVals",predictedVals.T,"errArr",errArr.T
weightedError = D.T*errArr #calc total error multiplied by D,根据错误向量求出新的错误率
print "split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshVal, inequal, weightedError)
if weightedError < minError:#若比原来错误率小,更新错误率和bestStump信息
minError = weightedError
bestClasEst = predictedVals.copy()
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal
return bestStump,minError,bestClasEst
#基于单层决策树的Adaboost训练过程
#dataArr数据,classLabels类别,numIt=40迭代次数
def adaBoostTrainDS(dataArr,classLabels,numIt=40):
weakClassArr=[]#每次的分类方式放入weakClassArr
m=shape(dataArr)[0]
D=mat(ones((m,1))/m)#数据的权重
aggClassEst=mat(zeros((m,1)))
for i in range(numIt):
bestStump,error,classEst=buildStump(dataArr,classLabels,D)
print "D:",D.T
alpha=float(0.5*log((1.0-error)/max(error,1e-16)))#根据error求出本次分类方式的权重
bestStump['alpha']=alpha
weakClassArr.append(bestStump)#加入本次分类方案
print "classEst: ",classEst.T
# 计算新的数据权重D
expon=multiply(-1*alpha*mat(classLabels).T,classEst)
D=multiply(D,exp(expon))
D=D/D.sum()
aggClassEst+=alpha*classEst#更新累计类别估计值
print "aggClassEst: ",aggClassEst.T
aggErrors=multiply(sign(aggClassEst)!=mat(classLabels).T,ones((m,1)))
errorRate=aggClassEst.sum()/m
print "total error: ",errorRate,"\n"
if errorRate==0.0:break
return weakClassArr
#AdaBoost分类函数
def adaClassify(datToClass,classifierArr):
dataMatrix=mat(datToClass)
m= shape(dataMatrix)[0]
aggClassEst=mat(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 sign(aggClassEst)