• 【AdaBoost算法】强分类器训练过程


    一、强分类器训练过程

    算法原理如下(参考自VIOLA P, JONES M. Robust real time object detection[A] . 8th IEEE International Conference on Computer Vision[C] . Vancouver , 2001.)

    • 给定样本 (x1; y1) , . . . , (xn; yn) ; 其中yi = 0表示负样本,yi =1表示正样本;
    • 初始化权重:负样本权重W0i= 1/2m, 正样本权重W1i = 1/ 2l,其中m为负样本总数,l为正样本总数;
    • 对于t = 1, ... T(T为训练次数):
      1. 权重归一化,简单说就是使本轮所有样本的权重的和为1;
      2. 根据每一个特征训练简单分类器,仅使用一个特征;
      3. 从所有简单分类器中选出一个分错率最低的分类器,为弱分类器;
      4. 更新权重
    • 最后组合T个弱分类器为强分类器

    二、代码实现及说明(python)

    目的:训练得到一个强分类器,该强分类器分错率低于预设值,且该强分类器由若干个弱分类器(对应单个特征)组成,通过若干个分类器及其权重计算得到的值对样本进行分类。

    def adaBoostTrainDS(dataArr,classLabels,numIt=40): 
        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)))#计算alpha值,该值与分错率相关,分错率越小,该值越大,弱分类器权重
                                                                #max(error,1e-16)用于确保错误为0时不会发生除0溢出
            bestStump['alpha'] = alpha  
            weakClassArr.append(bestStump)  #存储该弱分类
            print "classEst: ",classEst.T
            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))) #计算数据点哪个是错误
            print 'aggErrors: ',sign(aggClassEst) != mat(classLabels).T
            print 'aggErrors: ',aggErrors
            errorRate = aggErrors.sum()/m #计算错误率
            print "total error: ",errorRate
            if errorRate == 0.0: break
        return weakClassArr

    三、运行结果

    训练样本:

        datMat = matrix([[ 1. ,  2.1,  0.3],
                                     [ 2. ,  1.1,  0.4],
                                     [ 1.3,  1. ,  1.2],
                                     [ 1. ,  1. ,  1.1],
                                     [ 2. ,  1. ,  1.3],
                                     [ 7. ,  2. ,  0.35]])
        classLabels = [1.0, 1.0, 1.0, -1.0, -1.0, -1.0]

    训练得到的强分类器(强分类器分错率:0%,单个弱分类器最小分错率为33%,在上一篇已经测试过):

    [{'dim': 0, 'ineq': 'gt', 'thresh': 1.6000000000000001, 'alpha': 0.34657359027997275},

    {'dim': 1, 'ineq': 'lt', 'thresh': 1.0, 'alpha': 0.5493061443340549},

    {'dim': 0, 'ineq': 'gt', 'thresh': 2.2000000000000002, 'alpha': 0.5493061443340549},

    {'dim': 2, 'ineq': 'gt', 'thresh': 0.29999999999999999, 'alpha': 0.4777557225137181},

    {'dim': 0, 'ineq': 'lt', 'thresh': 1.0, 'alpha': 0.49926441505556346}]

    手动计算分类:

    针对第一个样本[ 1. ,  2.1,  0.3],利用强分类器计算结果如下:
    - 0.34657359027997275

    - 0.5493061443340549

    - 0.5493061443340549

    + 0.4777557225137181

    + 0.49926441505556346

    = -0.468165741378801--->小于0,正样本

    针对第六个样本[ 7. ,  2. ,  0.35],利用强分类器计算结果如下:
    + 0.34657359027997275

    - 0.5493061443340549

    + 0.5493061443340549

    + 0.4777557225137181

    - 0.49926441505556346

    = +0.3250648977381274--->大于0,负样本

    其它样本的计算类似


    结论:

    强分类器分类,即通过若干个分类器的权重的正负号计算得出,而正负号是通过该若分类器的阈值判断得到;

    强分类器比弱分类器准确率高。

  • 相关阅读:
    了解JVM原理
    封装JS
    “==”和Equals的区别
    SpringMVC请求RequestMapping() 请求乱码
    博客25周
    博客24周
    博客23周
    博客22周
    博客第21周
    博客第21周
  • 原文地址:https://www.cnblogs.com/chenpi/p/5128234.html
Copyright © 2020-2023  润新知