Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。
Adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器(弱分类器),然后把这
些弱分类器集合起来,构成一个更强的最终分类器(强分类器)。其 算法本身是通过改变数据分布来实现的,它根据每次训练集之中每个样本的分类是否正确,以及上次的总体分类的准确率,来确定每个样本的权值。将修改过权值的新数据集送给下层 分类器进行训练,最后将每次训练得到的分类器最后融合起来,作为最后的决策分类器。使用adaboost 分类器可以排除一些不必要的训练数据特征,并放在关键的训练数据上面。
对adaBoost算法的研究以及应用大多集中于分类问题,同时也出现了一些在回归问题上的应用。就其应用adaBoost系列主要解决了: 两类问题、多类单标签问题、多类多标签问题、大类单标签问题、回归问题。它用全部的训练样本进行学习。
过程分析
1. 先通过对N个训练样本的学习得到第一个弱
分类器;
2. 将分错的样本和其他的新数据一起构成一个新的N个的训练样本,通过对这个样本的学习得到第二个弱
分类器 ;
3. 将1和2都分错了的样本加上其他的新样本构成另一个新的N个的训练样本,通过对这个样本的学习得到第三个弱
分类器;
4. 最终经过提升的强
分类器 。即某个数据被分为哪一类要通过 , ……的多数表决。
存在的问题及改进方法
对于boosting
算法,存在两个问题:
1. 如何调整训练集,使得在训练集上训练的弱
分类器得以进行;
2. 如何将训练得到的各个弱
分类器联合起来形成强分类器。
针对以上两个问题,adaBoost
算法进行了调整:
1. 使用
加权后选取的训练数据代替随机选取的训练样本,这样将训练的焦点集中在比较难分的训练数
据样本上;
AdaBoost
算法是Freund和Schapire根据在线分配算法提出的,他们详细分析了AdaBoost算法错误率的
上界,以及为了使强
分类器达到错误率,算法所需要的最多迭代次数等相关问题。与
Boosting算法不同的是,adaBoost算法不需要预先知道弱学习算法学习正确率的下限即弱
分类器的误差,并且最后得到的强分类器的分类精度依赖于所有弱分类器的分类精度,这样可以深入挖掘弱分类器算法的能力。 AdaBoost算法中不同的训练集是通过调整每个样本对应的权重来实现的。开始时,每个样本对应的权重是相同的,即其中 n 为样本个数,在此
样本分布下训练出一弱
分类器。对于分类错误的样本,加大其对应的权重;而对于分类正确的样本,降低其权重,这样分错的样本就被突显出来,从而得到一个新的
样本分布。在新的
样本分布下,再次对样本进行训练,得到弱
分类器。依次类推,经过 T 次循环,得到 T 个弱
分类器,把这 T 个弱分类器按一定的权重叠加(boost)起来,得到最终想要的强分类器。 AdaBoost算法的具体步骤如下:
1. 给定训练样本集S,其中X和Y分别对应
于正例样本和负例样本; T为训练的最大循环次数;
2. 初始化样本权重为1/n ,即为训练样本的初始
概率分布;
3. 第一次迭代:
(2) 计算弱
分类器的错误率;
(3) 选取合适
阈值,使得误差最小;
(4) 更新样本权重;
经T次循环后,得到T个弱
分类器,按更新的权重叠加,最终得到的强分类器。
Adaboost
算法是经过调整的
Boosting算法,其能够对弱学习得到的弱
分类器的错误进行适应性调整。上述算法中迭代了T次的主循环,每一次循环根据当前的权重分布对样本x定一个分布P,然后对这个分布下的样本使用弱学习算法得到一个弱
分类器,对于这个算法定义的弱学习算法,对所有的,都有,而这个错误率的上限并不需要事先知道,实际上。每一次迭代,都要对权重进行更新。更新的规则是:减小弱
分类器分类效果较好的数据的
概率,增大弱分类器分类效果较差的数据的概率。最终的
分类器是个弱分类器的
加权平
误差计算:
更新D:
实现:
建立stump伪代码:
adaBoostTrainDS伪代码:
误差计算:
更新D:
实现:
建立stump伪代码:
def stumpClassify(dataMatrix , dimen , threshVal , threshIneq):
retArray = np.ones((np.shape(dataMatrix)[0],1))
if threshIneq =='lt':
retArray[dataMatrix[:, dimen] <=threshVal] = -1.
else:
retArray[dataMatrix[: ,dimen] > threshVal] = -1.
return retArray
def buildStump(dataArr , classLabels ,D):
###find a better bestStump,make the weights error little
dataMatrix =np.mat(dataArr) ; labelMax = np.mat(classLabels).T
# Unlike `matrix`, `asmatrix` does not make a copy if the input is already
#a matrix or an ndarray. Equivalent to ``matrix(data, copy=False)``.
m , n = np.shape(dataMatrix)
# m * n
numSteps = 10.0; bestStump = {};
# bestClasEst = np.mat(np.zeros( m ,1),dtype = int)
bestclasEst = np.mat(np.zeros((m,1)), dtype = np.int)
minError = inf
for i in range(n):
#standerd
rangeMin = dataMatrix[: , i] .min() ; rangeMax = dataMatrix[: ,i] .max();
stepSize = (rangeMax - rangeMin) / numSteps
#average step
for j in range(-1 , np.int(numSteps) +1):
for inequal in ['lt' , 'gt']:
threshVal = (rangeMin + float(j)* stepSize)
predictedVals = stumpClassify(dataMatrix, i, threshVal, inequal)
#这里对数据集里每一步(threshVal)将数据集扔入简单分类器进行测试
errArr = np.mat(np.ones((m, 1)))
errArr[predictedVals == labelMax] = 0
weightedError =D.T * errArr
#print 'split: dim %d ,thresh %.2f , thresh inequal:\%s \
#the weghted error is %.3f % (i , threshVal , inequa , weigtedError)\'
if weightedError < minError:
#得到的简单分类器如果能使权重误差最小,则选择该分类器,并记录
minError = weightedError
bestClasEst = predictedVals.copy
bestStump['dim'] = i
bestStump['thresh'] = threshVal
bestStump['ineq'] = inequal
return bestStump , minError , bestClasEst
adaBoostTrainDS伪代码:
def adaBoostTrainDS(dataArr ,classLabels , numIt = 40):
weakClassArr = []
m= np.shape(dataArr)[0] #rows of classLabels
D = np.mat(np.ones((m ,1))/m)
#give a matrix and every element is a average (1/m))
aggClassEst = np.mat(np.zeros((m ,1)))
for i in range(numIt):
bestStump ,error , classEst = buildStump(dataArr, classLabels, D)
#find the best Stump and its values
print 'D:' ,D.T
alpha = np.float(0.5*np.log((1. - error)/np.max(error , 1e-16)))
#calculate alpha,
bestStump['alpha'] = alpha
weakClassArr.append(bestStump)
#build a list weakClassArr for store stump tree
print 'classEst: ' , np.transpose(classEst)
expon = np.multiply(-1*alpha*np.transpose(np.mat(classLabels)), classEst)
#predictions compared with classLabels
D = np.multiply(D , np.exp(expon))
D = D/D.sum()
#update D
aggClassEst += alpha*classEst
print 'aggClassEst:' , aggClassEst.T
aggErrors = np.multiply(np.sign(aggClassEst) != np.mat(classLabels).T \
, np.ones((m ,1)))
#after update alpha and aggClassEst,save similar value between classLabels and aggClassEst
errorRate = np.sum(aggErrors)/m;
print ('total error : ' , errorRate ,'\n' )
if errorRate ==0.0: break
return weakClassArr