自適應加強(Adaptive Boosting)

  • 簡介

AdaBoost,是英文」Adaptive Boosting「(自適應加強)的縮寫,是一種迭代提高算法,其核心思想是針對同一個訓練集訓練不一樣的分類器(弱分類器),而後把這些弱分類器集合起來,構成一個更強的最終分類器(強分類器)。html

它的自適應在於:其算法自己是經過改變數據分佈來實現的,它根據每次訓練集之中每一個樣本的分類是否正確,以及上次的整體分類的準確率,來肯定每一個樣本的權值。將修改過權值的新數據集送給下層分類器進行訓練,最後將每次訓練獲得的分類器最後融合起來,做爲最後的決策分類器。算法

 

  • 基本思想

AdaBoost 的核心就是不斷迭代訓練弱分類器,並計算弱分類器的權重。須要注意的是,弱分類器的訓練依賴於樣本權重。每一輪迭代的樣本權重都不相同,依賴於弱分類器的權重值和上一輪迭代的樣本權重。具體過程以下:dom

一、訓練當前迭代最優弱分類器

  最優弱分類器是錯誤率最小的那個弱分類器。錯誤率的計算公式是:ide

  

  其中m = 1,2,..,M,表明第m輪迭代。i表明第i個樣本。w 是樣本權重。I指示函數取值爲1或0,當I指示函數括號中的表達式爲真時,I 函數結果爲1;當I函數括號中的表達式爲假時,I 函數結果爲0。取錯誤率最低的弱分類器爲當前迭代的最優弱分類器。函數

  第一輪迭代計算時樣本權重初始化爲總樣本數分之一。spa

二、計算最優弱分類器的權重

  優弱分類器的權重只與該弱分類器的錯誤率有關。弱分類器的權重計算公式以下:code

  

  能夠看出,錯誤率越小,則 alpha 值越大,即該弱分類器的權重越高;反之,錯誤率越大,則 alpha 值越小,則該弱分類器的權重越小。這樣可使分類精度高的弱分類器起到更大的做用,並削弱精度低的弱分類器的做用。orm

三、根據錯誤率更新樣本權重

  樣本權重的更新與當前樣本權重和弱分類器的權重有關。樣本權重更新公式以下:htm

  

  其中m = 1,2,..,M,表明第 m 輪迭代。i表明第i個樣本。w 是樣本權重。alpha 是弱分類器的權重。當樣本被正確分類時,y 和 Gm 取值一致,則新樣本權重變小;當樣本被錯誤分類時,y 和 Gm 取值不一致,則新樣本權重變大。這樣處理,可使被錯誤分類的樣本權重變大,從而在下一輪迭代中獲得重視。blog

四、迭代終止條件

  不斷重複1,2,3步驟,直到達到終止條件爲止。終止條件是強分類器的錯誤率低於最低錯誤率閾值或達到最大迭代次數。

 

  • 舉例說明

數據集如表:

X 0 1 2 3 4 5
Y 1 1 -1 -1 1 -1

 

 

第一輪迭代

 

一、選擇最優弱分類器

第一輪迭代時,樣本權重初始化爲(0.167, 0.167, 0.167, 0.167, 0.167, 0.167)。即1/6

表1數據集的切分點有0.5, 1.5, 2.5, 3.5, 4.5

若按0.5切分數據,得弱分類器x < 0.5,則 y = 1; x > 0.5, 則 y = -1。此時錯誤率爲2 * 0.167 = 0.334

若按1.5切分數據,得弱分類器x < 1.5,則 y = 1; x > 1.5, 則 y = -1。此時錯誤率爲1 * 0.167 = 0.167

若按2.5切分數據,得弱分類器x < 2.5,則 y = 1; x > 2.5, 則 y = -1。此時錯誤率爲2 * 0.167 = 0.334

若按3.5切分數據,得弱分類器x < 3.5,則 y = 1; x > 3.5, 則 y = -1。此時錯誤率爲3 * 0.167 = 0.501

若按4.5切分數據,得弱分類器x < 4.5,則 y = 1; x > 4.5, 則 y = -1。此時錯誤率爲2 * 0.167 = 0.334

因爲按1.5劃分數據時錯誤率最小爲0.167,則最優弱分類器爲x < 1.5,則 y = 1; x > 1.5, 則 y = -1。

 

二、計算最優弱分類器的權重

alpha = 0.5 * ln((1 – 0.167) / 0.167) = 0.8047

 

三、更新樣本權重

x = 0, 1, 2, 3, 5時,y分類正確,則樣本權重爲:

0.167 * exp(-0.8047) = 0.075

x = 4時,y分類錯誤,則樣本權重爲:

0.167 * exp(0.8047) = 0.373

新樣本權重總和爲0.075 * 5 + 0.373 = 0.748

規範化後,

x = 0, 1, 2, 3, 5時,樣本權重更新爲:

0.075 / 0.748 = 0.10

x = 4時, 樣本權重更新爲:

0.373 / 0.748 = 0.50

綜上,新的樣本權重爲(0.1, 0.1, 0.1, 0.1, 0.5, 0.1)。

此時強分類器爲G(x) = 0.8047 * G1(x)。G1(x)爲x < 1.5,則 y = 1; x > 1.5, 則 y = -1。則強分類器的錯誤率爲1 / 6 = 0.167。

 

第二輪迭代

 

一、選擇最優弱分類器

若按0.5切分數據,得弱分類器x > 0.5,則 y = 1; x < 0.5, 則 y = -1。此時錯誤率爲0.1 * 4 = 0.4

若按1.5切分數據,得弱分類器x < 1.5,則 y = 1; x > 1.5, 則 y = -1。此時錯誤率爲1 * 0.5 = 0.5

若按2.5切分數據,得弱分類器x > 2.5,則 y = 1; x < 2.5, 則 y = -1。此時錯誤率爲0.1 * 4 = 0.4

若按3.5切分數據,得弱分類器x > 3.5,則 y = 1; x < 3.5, 則 y = -1。此時錯誤率爲0.1 * 3 = 0.3

若按4.5切分數據,得弱分類器x < 4.5,則 y = 1; x > 4.5, 則 y = -1。此時錯誤率爲2 * 0.1 = 0.2

因爲按4.5劃分數據時錯誤率最小爲0.2,則最優弱分類器爲x < 4.5,則 y = 1; x > 4.5, 則 y = -1。

 

二、計算最優弱分類器的權重

alpha = 0.5 * ln((1 –0.2) / 0.2) = 0.6931

 

三、更新樣本權重

x = 0, 1, 5時,y分類正確,則樣本權重爲:

0.1 * exp(-0.6931) = 0.05

x = 4 時,y分類正確,則樣本權重爲:

0.5 * exp(-0.6931) = 0.25

x = 2,3時,y分類錯誤,則樣本權重爲:

0.1 * exp(0.6931) = 0.20

新樣本權重總和爲 0.05 * 3 + 0.25 + 0.20 * 2 = 0.8

規範化後,

x = 0, 1, 5時,樣本權重更新爲:

0.05 / 0.8 = 0.0625

x = 4時, 樣本權重更新爲:

0.25 / 0.8 = 0.3125

x = 2, 3時, 樣本權重更新爲:

0.20 / 0.8 = 0.250

綜上,新的樣本權重爲(0.0625, 0.0625, 0.250, 0.250, 0.3125, 0.0625)。

此時強分類器爲G(x) = 0.8047 * G1(x) + 0.6931 * G2(x)。G1(x)爲x < 1.5,則 y = 1; x > 1.5, 則 y = -1。G2(x)爲x < 4.5,則 y = 1; x > 4.5, 則 y = -1。

按G(x)分類會使x=4分類錯誤,則強分類器的錯誤率爲1 / 6 = 0.167。

 

第三輪迭代

 

一、選擇最優弱分類器

若按0.5切分數據,得弱分類器x < 0.5,則 y = 1; x > 0.5, 則 y = -1。此時錯誤率爲0.0625 + 0.3125 = 0.375

若按1.5切分數據,得弱分類器x < 1.5,則 y = 1; x > 1.5, 則 y = -1。此時錯誤率爲1 * 0.3125 = 0.3125

若按2.5切分數據,得弱分類器x > 2.5,則 y = 1; x < 2.5, 則 y = -1。此時錯誤率爲0.0625 * 2 + 0.250 + 0.0625 = 0.4375

若按3.5切分數據,得弱分類器x > 3.5,則 y = 1; x < 3.5, 則 y = -1。此時錯誤率爲0.0625 * 3 = 0.1875

若按4.5切分數據,得弱分類器x < 4.5,則 y = 1; x > 4.5, 則 y = -1。此時錯誤率爲2 * 0.25 = 0.5

因爲按3.5劃分數據時錯誤率最小爲0.1875,則最優弱分類器爲x > 3.5,則 y = 1; x < 3.5, 則 y = -1。

 

二、計算最優弱分類器的權重

alpha = 0.5 * ln((1 –0.1875) / 0.1875) = 0.7332

 

三、更新樣本權重

x = 2, 3時,y分類正確,則樣本權重爲:

0.25 * exp(-0.7332) = 0.1201

x = 4 時,y分類正確,則樣本權重爲:

0.3125 * exp(-0.7332) = 0.1501

x = 0, 1, 5時,y分類錯誤,則樣本權重爲:

0.0625 * exp(0.7332) = 0.1301

新樣本權重總和爲 0.1201 * 2 + 0.1501 + 0.1301 * 3 = 0.7806

規範化後,

x = 2, 3時,樣本權重更新爲:

0.1201 / 0.7806 = 0.1539

x = 4時, 樣本權重更新爲:

0.1501 / 0.7806 = 0.1923

x = 0, 1, 5時, 樣本權重更新爲:

0.1301 / 0.7806 = 0.1667

綜上,新的樣本權重爲(0.1667, 0.1667, 0.1539, 0.1539, 0.1923, 0.1667)。

 

此時強分類器爲G(x) = 0.8047 * G1(x) + 0.6931 * G2(x) + 0.7332 * G3(x)。

G1(x)爲x < 1.5,則 y = 1; x > 1.5, 則 y = -1。

G2(x)爲x < 4.5,則 y = 1; x > 4.5, 則 y = -1。

G3(x)爲x > 3.5,則 y = 1; x < 3.5, 則 y = -1。

按G(x)分類全部樣本均分類正確,則強分類器的錯誤率爲0 / 6 = 0,則中止迭代。

最終強分類器爲G(x) = 0.8047 * G1(x) + 0.6931 * G2(x) + 0.7332 * G3(x)。

 

  • 代碼實現

環境:MacOS mojave  10.14.3

Python  3.7.0

使用庫:scikit-learn    0.19.2

sklearn.ensemble.AdaBoostClassifier官方庫:https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.AdaBoostClassifier.html

 

AdaBoost.py  主程序和算法

import matplotlib.pyplot as plt
from prep_terrain_data import makeTerrainData
from class_vis import prettyPicture

features_train, labels_train, features_test, labels_test = makeTerrainData()


### the training data (features_train, labels_train) have both "fast" and "slow"
### points mixed together--separate them so we can give them different colors
### in the scatterplot and identify them visually
grade_fast = [features_train[ii][0] for ii in range(0, len(features_train)) if labels_train[ii]==0]
bumpy_fast = [features_train[ii][1] for ii in range(0, len(features_train)) if labels_train[ii]==0]
grade_slow = [features_train[ii][0] for ii in range(0, len(features_train)) if labels_train[ii]==1]
bumpy_slow = [features_train[ii][1] for ii in range(0, len(features_train)) if labels_train[ii]==1]


#### initial visualization
plt.xlim(0.0, 1.0)
plt.ylim(0.0, 1.0)
plt.scatter(bumpy_fast, grade_fast, color = "b", label="fast")
plt.scatter(grade_slow, bumpy_slow, color = "r", label="slow")
plt.legend()
plt.xlabel("bumpiness")
plt.ylabel("grade")

################################################################################


### your code here!  name your classifier object clf if you want the 
### visualization code (prettyPicture) to show you the decision boundary
from sklearn.ensemble import AdaBoostClassifier

clf = AdaBoostClassifier(n_estimators=100)
clf.fit(features_train,labels_train)

prettyPicture(clf, features_test, labels_test)
accuracy = clf.score(features_test, labels_test)
print (accuracy)

plt.show()

 

class_vis.py  繪圖與保存圖像

import numpy as np
import matplotlib.pyplot as plt
import pylab as pl

def prettyPicture(clf, X_test, y_test):
    x_min = 0.0; x_max = 1.0
    y_min = 0.0; y_max = 1.0
    
    # Plot the decision boundary. For that, we will assign a color to each
    # point in the mesh [x_min, m_max]x[y_min, y_max].
    h = .01  # step size in the mesh
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])

    # Put the result into a color plot
    Z = Z.reshape(xx.shape)
    plt.xlim(xx.min(), xx.max())
    plt.ylim(yy.min(), yy.max())

    plt.pcolormesh(xx, yy, Z, cmap=pl.cm.seismic)

    # Plot also the test points
    grade_sig = [X_test[ii][0] for ii in range(0, len(X_test)) if y_test[ii]==0]
    bumpy_sig = [X_test[ii][1] for ii in range(0, len(X_test)) if y_test[ii]==0]
    grade_bkg = [X_test[ii][0] for ii in range(0, len(X_test)) if y_test[ii]==1]
    bumpy_bkg = [X_test[ii][1] for ii in range(0, len(X_test)) if y_test[ii]==1]

    plt.scatter(grade_sig, bumpy_sig, color = "b", )
    plt.scatter(grade_bkg, bumpy_bkg, color = "r",)
    plt.legend()
    plt.xlabel("bumpiness")
    plt.ylabel("grade")

    plt.savefig("test.png")
                                    

 

perp_terrain_data.py  生成訓練點

import random


def makeTerrainData(n_points=1000):
###############################################################################
### make the toy dataset
    random.seed(42)
    grade = [random.random() for ii in range(0,n_points)]
    bumpy = [random.random() for ii in range(0,n_points)]
    error = [random.random() for ii in range(0,n_points)]
    y = [round(grade[ii]*bumpy[ii]+0.3+0.1*error[ii]) for ii in range(0,n_points)]
    for ii in range(0, len(y)):
        if grade[ii]>0.8 or bumpy[ii]>0.8:
            y[ii] = 1.0

### split into train/test sets
    X = [[gg, ss] for gg, ss in zip(grade, bumpy)]
    split = int(0.75*n_points)
    X_train = X[0:split]
    X_test  = X[split:]
    y_train = y[0:split]
    y_test  = y[split:]

    grade_sig = [X_train[ii][0] for ii in range(0, len(X_train)) if y_train[ii]==0]
    bumpy_sig = [X_train[ii][1] for ii in range(0, len(X_train)) if y_train[ii]==0]
    grade_bkg = [X_train[ii][0] for ii in range(0, len(X_train)) if y_train[ii]==1]
    bumpy_bkg = [X_train[ii][1] for ii in range(0, len(X_train)) if y_train[ii]==1]

    training_data = {"fast":{"grade":grade_sig, "bumpiness":bumpy_sig}
            , "slow":{"grade":grade_bkg, "bumpiness":bumpy_bkg}}


    grade_sig = [X_test[ii][0] for ii in range(0, len(X_test)) if y_test[ii]==0]
    bumpy_sig = [X_test[ii][1] for ii in range(0, len(X_test)) if y_test[ii]==0]
    grade_bkg = [X_test[ii][0] for ii in range(0, len(X_test)) if y_test[ii]==1]
    bumpy_bkg = [X_test[ii][1] for ii in range(0, len(X_test)) if y_test[ii]==1]

    test_data = {"fast":{"grade":grade_sig, "bumpiness":bumpy_sig}
            , "slow":{"grade":grade_bkg, "bumpiness":bumpy_bkg}}

    return X_train, y_train, X_test, y_test

 

獲得結果,正確率爲92.4%

 

Adaboost的參數

n_estimators表示迭代的次數

n_estimators分別爲100、1000、10000時:

 

正確率分別爲:92.4%  91.6%  92%

 能夠看出迭代次數越大,過擬合現象越嚴重,但正確率並沒有明顯變化,編譯時間略微增長。

 

  • AdaBoost優缺點

 優勢:

一、能夠將不一樣的分類算法做爲弱分類器。

二、AdaBoost充分考慮的每一個分類器的權重。

 

缺點:

一、AdaBoost迭代次數也就是弱分類器數目不太好設定。

二、數據不平衡致使分類精度降低。

三、訓練比較耗時,

相關文章
相關標籤/搜索