初學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