adaboost

来源:互联网 发布:南京地铁网络问政 编辑:程序博客网 时间:2024/06/01 19:43

adaboost

adaboost是一种迭代算法,其核心思想是针对同一个训练集训练不同的分类器,然后把这些弱分类器集合起来,构成一个更强的最终分类器。
adaboost本身是通过改变数据分布来实现的,它根据每次训练集中每个样本的分类是否正确,以及上次的总体分布的准确率,来确定每个样本的权值,将修改过权值的新数据集送给下层分类器进行训练,最后将每次得到的分类器融合起来,作为最后的决策分类器。
adaboost是一种boosting方法,此外还有bagging方法。
- bagging
1、训练分类器-从整体样本集合中,抽样n * < N个样本, 针对抽样的集合训练分类器C i, 抽取方法有很多种。
2、分类器进行投票,最终的结果是分类器投票的优胜结果,每个分类器权重是相等的
- boosting
Boosting是一种与Bagging很类似的技术,两者所使用的多个分类器的类型都是一致的。但是在boosting中,不同的分类器是通过串行训练而获得的,每个新分类器都在已训练出的分类器的性能基础上再进行训练,通过集中关注被已有分类器错分的些数据来获得新的分类器。Boosting分类的结果是基于所有分类器的加权求和结果的,分类器权重并不相等,每个权重代表的是其对应分类器在上一轮迭代中的成功度。Boosting算法有很多种,AdaBoost(Adaptive Boost)就是其中最流行的

算法运行过程

对训练数据中的每个样本,赋予一个权重,这些权重构成向量D。一开始,这些权重都初始化成相等值。首先在训练数据上训练出一个弱分类器并计算该分类器的错误率,然后再同一数据集上再次训练弱分类器。在分类器的第二次训练中,将会重新调整每个样本的权重,其中第一次分对的样本的权重将会降低,分错的样本的权重将会提高。为了从所有弱分类器中得到最终的分类结果,adaboost为每个分类器都分配了一个权重值alpha,这个alpha值是基于每个弱分类器的错误率进行计算的。错误率错误率变量定义为:
这里写图片描述 = 未正确分类的样本数目/所有样本数目。
而alpah计算公式为:
alpah公式
公式可以看出,当ϵ>0.5时,α>0;当0<ϵ<0.5时,α<0
计算出alpha后,可以对权重向量D进行更新,以使得那些正确分类的样本的权重降低,而错分样本的权重升高。D的计算方法:
- 正确分类的样本权重
这里写图片描述
- 错误分类的样本权重
这里写图片描述
综合起来:
这里写图片描述
计算出D后,adaboost又开始进入下一轮迭代。adaboost算法会不断重复训练和调整权重,知道训练错误率为0或者弱分类器的数目达到用户指定值为止。

单层决策树

寻找最佳切分属性及属性值。即得到最佳单层决策树。
伪代码:
将最小错误率minError设为正无穷大
对数据集中的每个feature(第一层循环):
  对每个步长(第二层循环):
    对每个不等号(第二层循环):
      建立一棵单层决策树并利用加权数据集对它进行测试,如果错误率低于minError,则将当前单层决策树设为最佳单层决策树
返回最佳单层决策树
代码:

def buildStump(dataArr, classLabels, D):    """构建一层决策树桩    :param dataArr: m X n维数据矩阵    :param classLabels: dataArr对应的类别    :param D:权重,m维列向量    :return:决策树桩    """    dataMat = mat(dataArr); labelMat = mat(classLabels).T    m,n = shape(dataMat)    numSteps = 10.0; bestStump = {}; bestClassErrorList = mat(zeros((m, 1)))    minError = inf    for i in range(n):        rangeMin = dataMat[:,i].min()        rangeMax = dataMat[:, i].max()        stepSize = (rangeMax - rangeMin)/numSteps        for j in range(-1, int(numSteps)+1):            threshod = rangeMin + float(j) * stepSize            for ineq in ['lt', 'gt']:                predictVal = stumpClassify(dataMat, i, threshod, ineq)                errArr = mat(ones((m,1)))                errArr[predictVal == labelMat] = 0                weightedError = D.T * errArr                #print("split: dim %d, thresh %.2f, thresh ineqal: %s, the weighted error is %.3f" % (i, threshod, ineq, weightedError))                if weightedError < minError:                    minError = weightedError                    bestClassErrorList = predictVal.copy()                    bestStump['dim'] = i                    bestStump['threshod'] = threshod                    bestStump['ineq'] = ineq    return bestStump,minError,bestClassErrorList

stumpClassify函数如下:

def stumpClassify(dataMatrix, dimen, threshold, inequation):    """单层决策树(决策树桩)分类函数,在所有可能得树桩值上进行迭代来得到具有最小加权错误率的单层决策树    :param dataMatrix: m X n维数据矩阵    :param dimen: 要检验的维度,1,2...n    :param threshold: 阈值    :param inequation: 比较操作 ”lt“ or ”gt“    :return: 列向量,dataMatrix中第dimen维度的数据,满足a inequation threshold的预测为-1,不满足的为1    """    retArray = ones([shape(dataMatrix)[0], 1])    if inequation == 'lt':        retArray[dataMatrix[:, dimen] <= threshold] = -1.0    else:        retArray[dataMatrix[:, dimen] > threshold] = -1.0    return retArray     #列向量

adaboost构建

adaBoostTrainDS伪代码:
对每次迭代:
  利用buildStump函数找到最佳单层决策树
  将最佳单层决策树加入到单层决策树数组
  计算alpha
  计算新的权重D
  更新累计类别估计值
  如果错误率等于0.0,退出循环
代码:

def adaBoostTrainDS(dataArr, classLabels, numIt = 40):    """adaboosting训练决策树桩    :param dataArr: m X n维数据矩阵    :param classLabels: dataArr对应的类别    :param numIt: 最多迭代次数    :return: weakClassArr-决策树桩弱分类器数组;aggClassEst是累计的类别估计值    """    labelMat = mat(classLabels).T    weakClassArr = []    m,n = shape(dataArr)    D = mat(ones((m,1))/m)    aggClassEst = mat(zeros((m, 1)))    for i in range(numIt):        bestStump, minError, bestClassEst = buildStump(dataArr, classLabels, D)        #print("D:", D.T)        #print("classEst: ", bestClassEst.T)        alpha = float(0.5*log((1-minError)/max(minError,1e-16)))        bestStump['alpha'] = alpha        weakClassArr.append(bestStump)        expon = multiply(-1 * alpha * labelMat, bestClassEst)        D = multiply(D, exp(expon))        D = D/sum(D)        aggClassEst += alpha * bestClassEst        #print("aggClassEst: ",aggClassEst.T)        aggErrors = multiply(sign(aggClassEst) != labelMat, ones((m,1)))        #print("aggErrors error: ", aggErrors)        errorRate = aggErrors.sum() / m        #print("total error: ", errorRate)        if errorRate == 0.0:            break    return weakClassArr

使用adaboost来预测:
所有弱分类器的结果的加权求和,即可得到结果。
代码:

def adaClassfy(dataToClassfy, classifierArr):    dataMat = mat(dataToClassfy)    m = shape(dataMat)[0]    aggClassEst = mat(zeros((m, 1)))    for i in range(len(classifierArr)):        classEst = stumpClassify(dataMat,classifierArr[i]['dim'],classifierArr[i]['threshod'],classifierArr[i]['ineq'])        # 加权求和        aggClassEst += classifierArr[i]['alpha']*classEst        print(aggClassEst)    return sign(aggClassEst)

参考:
http://blog.csdn.net/lvsolo/article/details/51031117
完整代码参考github:
https://github.com/zhanggw/algorithm/blob/master/machine-learning/adaboost/adaboost.py

0 0
原创粉丝点击