python adaboost的简单实现

来源:互联网 发布:岳阳网络车招骋公司 编辑:程序博客网 时间:2024/06/06 00:10

初学adaboost,自己尝试着写了下adaboost的实现,这个实现以几个简单的数字作为训练样本,当然,这些数字是带标签的。然后尝试着使用adaboost对其分类。对于10个带标签的数字,分类他们只需要3个左右的弱分类器级联,组成一个强分类器就可以完全正确的分类。如果代码本身没有bug的话,adaboost的表现的确惊艳。
另外,pathon也是初学,很多的编程思路和c,c++类似,总之,各方面有待提高。但是因为代码能很好的分类样本,其结果还是令人兴奋的。
adaboost的教程非常多了,再次就不多做废话了。
一下是完整的代码。python是3.5.2版本的,如果版本没什么问题,粘贴复制应该就可以运行。

import cv2import numpy as npimport mathimport matplotlib.pyplot as pltdef buildDatasAndLables():    data =  [23,12,3,54,89,2,43,7,45,26]    label = [1, 1,-1,-1,-1,1,1,  -1, -1,1,]    return (data,label)def calWeakClassfyOuput(input,weakClassy):    # 在期望范围的数为1,否则为-1    if weakClassy[0] == "left":        # left的时候,如果小于阈值,则输出1,否则,输出0        if input < weakClassy[1] :            return 1        elif input >= weakClassy[1]:            return -1    elif weakClassy[0] == "right":        # right的时候,如果大于阈值,则输出1,否则,输出0        if input > weakClassy[1] :            return 1        elif input <= weakClassy[1]:            return -1#训练弱分类器def trainWeakClassfy(data,label,W):    #训练若分类器的方式:找到一个阈值,把data分成两部分,使得错误率最小    weakClassy = []    #将每个data中的数据作为阈值,判断以该值作为阈值的误差率,这样需要判断len(data)次    for m in data:        for direct in ["left","right"]:            i = 0            error = 0            for mm in data:                #在期望范围的数为1,否则为-1                if direct == "left":                    #left的时候,如果小于阈值,则对应的label应该为1,如果为-1,则错了,需要增加错误率                    if mm < m and label[i]==-1:                        error += W[i]                    elif mm >= m and label[i]==1:                        error += W[i]                elif direct == "right":                    # right的时候,如果大于阈值,则对应的label应该为1,如果为-1,则错了,需要增加错误率                    if mm > m and label[i]==-1:                        error += W[i]                    elif mm <= m and label[i]==1:                        error += W[i]                i += 1            weakClassy.append([direct,m,error[0]])    #从所有的弱分类器中选择出错误率最低的    bestWeakClassfy = []    for classfy in weakClassy:        if not bestWeakClassfy:            bestWeakClassfy = classfy        else:            if classfy[2]<bestWeakClassfy[2]:                bestWeakClassfy = classfy    return bestWeakClassfydef adaboostTrain(desAccuracy,maxWeakClassfyNum):    #首先获取训练数据    data,label = buildDatasAndLables()    #初始化权重为1/n    W = np.ones((len(data),1))/len(data)    weakClassfys = []    accuracy = 0    for num in range(maxWeakClassfyNum):        #首先训练弱分类器        weakClassfy = trainWeakClassfy(data, label, W)        #其次,计算该分类器的话语权        weight = 0.5*math.log(((1-weakClassfy[2])/weakClassfy[2]))        print("weight",weight)        print("weakClassfy",weakClassfy)        weakClassfy.append(weight)        weakClassfys.append(weakClassfy)        #然后更新训练样本的权重        midW = np.zeros(W.shape)        for i in range(len(W)):            midW[i] = W[i]*math.exp(-calWeakClassfyOuput(data[i],weakClassfy)*label[i]*weight)        Zt = np.sum(midW)        for i in range(len(W)):            W[i] = midW[i]/Zt        #左右检验输出是否达标        i = 0        accuracy = 0        for d in data:            result = 0            for classfy in weakClassfys:                result += classfy[3]*calWeakClassfyOuput(d,classfy)            if result > 0 :                result = 1            else:                result = -1            if result == label[i]:                accuracy += 1/len(data)            i += 1        print("accuracy",accuracy)        print("num",num)        if accuracy >= desAccuracy:            breakadaboostTrain(0.98,10)

结果如下:

weight 0.6931471805599453weakClassfy ['left', 45, 0.20000000000000001]accuracy 0.7999999999999999num 0weight 0.5493061443340549weakClassfy ['left', 3, 0.25]accuracy 0.7999999999999999num 1weight 0.8047189562170503weakClassfy ['right', 7, 0.16666666666666666]accuracy 0.9999999999999999num 2