python adaboost的簡單實現

初學adaboost,自己嘗試着寫了下adaboost的實現,這個實現以幾個簡單的數字作爲訓練樣本,當然,這些數字是帶標籤的。然後嘗試着使用adaboost對其分類。對於10個帶標籤的數字,分類他們只需要3個左右的弱分類器級聯,組成一個強分類器就可以完全正確的分類。如果代碼本身沒有bug的話,adaboost的表現的確驚豔。
另外,pathon也是初學,很多的編程思路和c,c++類似,總之,各方面有待提高。但是因爲代碼能很好的分類樣本,其結果還是令人興奮的。
adaboost的教程非常多了,再次就不多做廢話了。
一下是完整的代碼。python是3.5.2版本的,如果版本沒什麼問題,粘貼複製應該就可以運行。

import cv2
import numpy as np
import math
import matplotlib.pyplot as plt

def 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 bestWeakClassfy





def 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:
            break

adaboostTrain(0.98,10)


結果如下:

weight 0.6931471805599453
weakClassfy ['left', 45, 0.20000000000000001]
accuracy 0.7999999999999999
num 0
weight 0.5493061443340549
weakClassfy ['left', 3, 0.25]
accuracy 0.7999999999999999
num 1
weight 0.8047189562170503
weakClassfy ['right', 7, 0.16666666666666666]
accuracy 0.9999999999999999
num 2
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章