Adaboost算法及其代碼實現


Adaboost算法及其代碼實現

算法概述

AdaBoost(adaptive boosting),即自適應提升算法。

Boosting 是一類算法的總稱,這類算法的特點是通過訓練若干弱分類器,然后將弱分類器組合成強分類器進行分類。

為什么要這樣做呢?因為弱分類器訓練起來很容易,將弱分類器集成起來,往往可以得到很好的效果。

俗話說,"三個臭皮匠,頂個諸葛亮",就是這個道理。

這類 boosting 算法的特點是各個弱分類器之間是串行訓練的,當前弱分類器的訓練依賴於上一輪弱分類器的訓練結果。

各個弱分類器的權重是不同的,效果好的弱分類器的權重大,效果差的弱分類器的權重小。

值得注意的是,AdaBoost 不止適用於分類模型,也可以用來訓練回歸模型。

這需要將弱分類器替換成回歸模型,並改動損失函數。

$幾個概念

強學習算法:正確率很高的學習算法;
弱學習算法:正確率很低的學習算法,僅僅比隨機猜測略好。

弱分類器:通過弱學習算法得到的分類器, 又叫基本分類器;
強分類器:多個弱分類器按照權值組合而成的分類器。

$提升方法專注兩個問題:

1.每一輪如何改變訓練數據的權值或者概率分布:

Adaboost的做法是提高被分類錯誤的訓練數據的權值,而提高被分類錯誤的訓練數據的權值。

這樣,被分類錯誤的訓練數據會得到下一次弱學習算法的重視。

2.弱組合器如何構成一個強分類器

加權多數表決

每一個弱分類器都有一個權值,該分類器的誤差越小,對應的權值越大,因為他越重要。


算法流程

給定二分類訓練數據集:

$T = {(x_1, y_1), (x_2, y_2), ... , (x_n, y_n)}$
和弱學習算法

目標:得到分類器\(G(x)\)

1.初始化權重分布:

一開始所有的訓練數據都賦有同樣的權值,平等對待。

$D_1 = (w_{11}, w_{12}, ... , w_{1n})$, $w_{1i} = \frac{1}{N}$, $i = 1, 2, ... , N$
### 2.權值的更新 設總共有M個弱分類器,m為第m個弱分類器, $m = 1, 2, ... , M$ (1)第m次在具有$D_m$權值分布的訓練數據上進行學習,得到弱分類器$G_m(x)$。 這個時候訓練數據的權值:
$D_m = (w_{m, 1}, w_{m, 2}, ... , w_{m, n})$, $i = 1, 2, ... , N$
(2)計算$Gm(x)$在該訓練數據上的**分類誤差率**: 注:I函數單位誤差函數
**分類誤差率**:$e_m = \sum^{N}_{i = 1} w_i I (G_m(x_i) \neq y_i)$
(3)計算$G_(x)$的系數:
$\alpha_m = \frac 1 2 \ln \frac{1 - e_m}{e_m}$
(4)更新訓練數據的權值:
$D_{m+1} = (w_{m+1, 1}, w_{m+1, 2}, ... , w_{m+1, n})$, $i = 1, 2, ... , N$
$w_{m+1, i} = \frac{w_{m, i}}{Z_m}\exp(-\alpha_m y_i G_m(x_i))$, $i = 1, 2, ... , N$
其中:
$Z_m = \sum^{N}_{i = 1} w_{m, i} \exp(-\alpha_m y_i G_m(x_i))$
正確的分類:$y_i G_m(x_i) = 1$
錯誤的分類:$y_i G_m(x_i) = -1$
### 3.構建基本分類器的線性組合 弱分類器乘以權重
$f(x) = \sum^{M}_{m = 1} \alpha_m G_m(x)$
最終分類器
$G_(x) = sign(f(x))$

一個例子

表 1. 示例數據集

第一輪迭代

1.a 選擇最優弱分類器

第一輪迭代時,樣本權重初始化為(0.167, 0.167, 0.167, 0.167, 0.167, 0.167)。

表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。

1.b 計算最優弱分類器的權重

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

1.c 更新樣本權重

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。

第二輪迭代

2.a 選擇最優弱分類器

若按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。

2.b 計算最優弱分類器的權重

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

2.c 更新樣本權重

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。

第三輪迭代

3.a 選擇最優弱分類器

若按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。

3.b 計算最優弱分類器的權重

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

3.c 更新樣本權重

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)。

代碼實現

import numpy as np

X = np.arange(6)
y = np.array([1, 1, -1, -1, 1, -1])


class my_adabosot(object):
    """docstring for my_adabosot"""

    def __init__(self, max_iter=3):
        super(my_adabosot, self).__init__()
        self.max_iter = max_iter

    def fit(self, X, y):
        self.X = X
        self.y = y
        self.clf_list = []
        self.cut_list = self.cut_list() # 例子中換成[0.5, 1.5, 2.5, 3.5, 4.5]
        self.w = np.ones(len(X)) / len(X)  # 最初的權重

        for i in range(self.max_iter):
            loss_list = []
            for a_index in self.cut_list:
                loss_list.append(sum(self.w[self.G_(self.X, a_index) != self.y]))

            loss_array = np.array(loss_list)
            a_index = np.argmin(loss_array)
            a = self.cut_list[a_index]
            em = np.sum(np.min(loss_array))
            alpha = 1 / 2 * np.log(1 / em - 1)
            alpha = np.round(alpha, 4)
            self.clf_list.append([alpha, a])

            # 更新參數
            temp_array = -alpha * self.y * self.G_(self.X, a_index)
            Zm = np.dot(self.w, np.exp(temp_array))
            #print(self.w)
            self.w = self.w / Zm * np.exp(temp_array)



    def predict(self, X):
        res = []
        for i in range(X):
            temp = 0
            for clf in self.clf_list:
                temp += clf[0] * G_(X, clf[1])
                res.append(-1 if temp > 0 else 1)

        return  np.array(res)


    def G_(self, X, a):
        Z = np.zeros(len(self.X))
        Z[X > a] = -1
        Z[X <= a] = 1
        return Z


    def cut_list(self):
        return  np.arange(self.X.min(), self.X.max(), 0.5)

clf = my_adabosot()
clf.fit(X, y)
#print(clf.cut_list)
for alpha in clf.clf_list:
    print(alpha)
    

Adaboost的另一種解釋

Adaboost算法也可以認為是特殊的加法模型:損失函數為指數函數,學習算法為前向分布算法
加法模型

\[f(x) = \sum^{M}_{m=1} \beta_m b(x; \gamma_m) \]

其中:
\(b(x; \gamma_m)\)是基函數,可以是多項式函數;
\(\gamma_m\)是基函數的參數,即多項式的各項權值;
\(\beta_m\)是基函數的系數,即基函數的加權系數。

在給定的損失函數\(L(y, f(x))\)下,學習加法模型\(f(x)\)成為損失函數最小化問題。

\[\min_{\beta_m, \gamma_m} \sum^{N}_{i=1}L(y_i, \sum^{M}_{m=1}\beta_m b(x; \gamma_m)) \]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM