機器學習演算法系列(十九)-自適應增強演算法(Adaptive Boosting Algorithm)

Saisimon發表於2022-03-15

閱讀本文需要的背景知識點:整合學習、拉格朗日乘數法、一丟丟程式設計知識

一、引言

  前面一節我們學習了隨機森林演算法(Random Forest Algorithm),講到了其中一種整合學習的方法——Bagging 演算法,這一節我們來學習另一種整合學習的方法——提升演算法)1 (Boosting Algorithm),同時介紹其中比較常見的演算法——自適應增強演算法2(Adaptive Boosting Algorithm / AdaBoost Algorithm)

二、模型介紹

Boosting 演算法

  Boosting 演算法也是一種整合學習,與 Bagging 演算法不同的是,每次訓練更關注訓練出的估計器中分類錯誤或者回歸誤差大的樣本,即每次訓練都是根據上次訓練的結果調整不同的樣本權重,直到最後的輸出小於預設的閾值。

0.png
圖2-1

  圖 2-1 展示了提示演算法的具體流程,其與 Bagging 演算法的區別在於:其一,Bagging 演算法的每個估計器相對獨立且權重都相同,而 Boosting 演算法的每個估計器都依賴於上一個估計器同時權重也不同。其二,一般情況下 Bagging 演算法可以減小方差、而 Boosting 演算法則是減小偏差。

  Boosting 演算法中比較有代表性的演算法就是自適應增強演算法(Adaptive Boosting Algorithm / AdaBoost Algorithm)

AdaBoost 演算法

  AdaBoost 演算法是由 Yoav Freund 和 Robert E. Schapire 在 1995 年提出的,同時還提出了 AdaBoost.M1、AdaBoost.M2 演算法用於多分類問題,AdaBoost.R 演算法用於迴歸問題。後面陸續又有人提出了上述演算法的變體 AdaBoost-SAMME、AdaBoost-SAMME.R、AdaBoost.R2 演算法。

  AdaBoost 演算法的基本步驟與 Boosting 演算法一樣,是 Boosting 演算法的具體實現,其定義了每次迴圈如何更新樣本權重以及最後如何將每個估計器結合起來。

  由於筆者能力所限,本文只會介紹基礎的 AdaBoost 演算法和現在 scikit-learn 中所實現的 AdaBoost-SAMME、AdaBoost-SAMME.R、AdaBoost.R2演算法,其他的演算法暫無法一一介紹,感興趣的讀者可以參考文末對應演算法的論文原文。

三、演算法步驟

  下面先給出每個演算法的執行步驟,後面再一一說明這些演算法步驟中公式的來源。

二分類

  假設訓練集 T = { X_i, y_i },i = 1,...,N,y_i 可取-1,+1,h(x) 為估計器,估計器的數量為 K。

AdaBoost 演算法步驟如下:

<hr/>

初始化樣本權重向量 ω_1

$$ \begin{aligned} \omega_{1,i} &= \frac{1}{N} \quad i = 1,...,N \end{aligned} $$

遍歷估計器的數量 K 次:

  在樣本權重 ω_k 下訓練估計器 h(x)

  計算第k次的誤差率 e_k

$$ \begin{aligned} e_k &= \sum_{i = 1}^{N}\omega_{k,i} I(y_i \ne h_k(X_i)) \end{aligned} $$

  如果誤差率 e_k 大於 0.5

    中斷迴圈

  計算第k次的估計器權重 α_k

$$ \begin{aligned} \alpha_k &= \frac{1}{2} \ln \frac{1 - e_k}{e_k}\\ \end{aligned} $$

  計算第 k+1 次的權重向量 ω_{k+1}

$$ \begin{aligned} \omega_{k+1,i} &= \frac{\omega_{k,i} e^{-y_i\alpha_kh_k(X_i)}}{\sum_{j = 0}^N \left(\omega_{k,j} e^{-y_j\alpha_kh_k(X_j)}\right) } \end{aligned} $$

結束迴圈

  最後的結合策略,採用加權後的結果取 sign 函式,得到最終的強估計器:

$$ \begin{aligned} H(x) &= \operatorname{sign} \left(\sum_{i = 1}^{K} \alpha_i h_i(x)\right) \end{aligned} $$

<hr/>

多分類

  假設訓練集 T = { X_i, y_i },i = 1,...,N,y 的取值有 M 種可能,h(x) 為估計器,估計器的數量為 K。

AdaBoost-SUMME 演算法步驟如下:

<hr/>

初始化樣本權重向量 ω_1

$$ \begin{aligned} \omega_{1,i} &= \frac{1}{N} \quad i = 1,...,N \end{aligned} $$

遍歷估計器的數量 K 次:

  在樣本權重 ω_k 下訓練估計器 h(x)

  計算第k次的誤差率 e_k

$$ \begin{aligned} e_k &= \sum_{i = 1}^{N}\omega_{k,i} I(y_i \ne h_k(X_i)) \end{aligned} $$

  計算第 k 次的估計器權重 α_k

$$ \begin{aligned} \alpha_k &= \ln \frac{1 - e_k}{e_k} + \ln (M - 1) \\ \end{aligned} $$

  計算第 k+1 次的權重向量 ω_{k+1}

$$ \begin{aligned} \bar{\omega_{k+1,i}} &= \omega_{k,i}e^{\alpha_kI(y_i \ne h_k(X_i))} \end{aligned} $$

  對權重向量 ω_{k+1} 進行歸一化

$$ \begin{aligned} \omega_{k+1,i} &= \frac{\bar{\omega_{k + 1,i}}}{\sum_{j = 1}^N \bar{\omega_{k + 1,i}} } \end{aligned} $$

結束迴圈

  最後的結合策略,採用正確分類的結果加權後取值最大的分類,得到最終的強估計器:

$$ \begin{aligned} H(x) &= \underset{m}{\operatorname{argmax}} \left( \sum_{i = 1}^{K} \alpha_i I(h_i(x) = m) \right) \end{aligned} $$

<hr/>

AdaBoost-SUMME.R 演算法步驟如下:

<hr/>

初始化樣本權重向量 ω_1

$$ \begin{aligned} \omega_{1,i} &= \frac{1}{N} \quad i = 1,...,N \end{aligned} $$

遍歷估計器的數量 K 次:

  在樣本權重 ω_k 下計算加權類概率估計向量 P_k

$$ \begin{aligned} p_k^m(x) = P(y = m \mid x) \end{aligned} $$

   計算第 k+1 次的權重向量 ω_{k+1}

$$ \hat{y} = \left\{ \begin{array}{c} 1 & y =m\\ -\frac{1}{M-1} & y \ne m \end{array}\right. \quad m = 1,\dots,M $$

$$ \begin{aligned} \bar{\omega_{k+1,i}} &= \omega_{k,i}e^{-\frac{M-1}{M} \hat{y_i}^T \ln p_k(x) } \end{aligned} $$

  對權重向量 ω_{k+1} 進行歸一化

$$ \begin{aligned} \omega_{k+1,i} &= \frac{\bar{\omega_{k + 1,i}}}{\sum_{j = 1}^N \bar{\omega_{k + 1,i}} } \end{aligned} $$

結束迴圈

  最後的結合策略,採用概率估計計算結果取值最大的分類,得到最終的強估計器:

$$ \begin{aligned} h_k(x) &= (M - 1) \left( \ln p_k^m(x) - \frac{1}{M} \sum_{i = 1}^{M} \ln p_k^i(x) \right) \\ H(x) &= \underset{m}{\operatorname{argmax}} \left( \sum_{i = 1}^{K} h_i(x)\right) \end{aligned} $$

<hr/>

迴歸

  假設訓練集 T = { X_i, y_i },i = 1,...,N,h(x) 為估計器,估計器的數量為 K

AdaBoost.R2 演算法步驟如下:

<hr/>

初始化樣本權重向量 ω_1

$$ \begin{aligned} \omega_{1,i} &= \frac{1}{N} \quad i = 1,...,N \end{aligned} $$

遍歷估計器的數量 K 次:

  在樣本權重 ω_k 下訓練估計器 h(x)

  計算最大誤差 E_k

$$ \begin{aligned} E_k &= \max \mid y_i - h_k(X_i) \mid \end{aligned} $$

  計算第 k 次的誤差率 e_k

$$ \begin{aligned} e_{k,i} &= \frac{\mid y_i - h_k(X_i) \mid}{E_k} & 線性誤差 \\ e_{k,i} &= \frac{\left( y_i - h_k(X_i) \right)^2}{E_k^2} & 平方誤差 \\ e_{k,i} &= 1 - e^{-\frac{\mid y_i - h_k(X_i) \mid}{E_k} } & 指數誤差 \\ e_k & = \sum_{i = 1}^{N}\omega_{k,i} e_{k,i} \end{aligned} $$

  如果誤差率 e_k 大於 0.5

    中斷迴圈

  計算第 k 次的估計器權重 α_k

$$ \begin{aligned} \alpha_k &= \frac{e_k}{1 - e_k} \end{aligned} $$

  計算第 k+1 次的權重向量 ω_{k+1}

$$ \begin{aligned} \bar{\omega_{k+1,i}} &= \omega_{k,i}\alpha_k^{1 - e_{k,i}} \end{aligned} $$

  對權重向量 ω_{k+1} 進行歸一化

$$ \begin{aligned} \omega_{k+1,i} &= \frac{\bar{\omega_{k + 1,i}}}{\sum_{j = 1}^N \bar{\omega_{k + 1,i}} } \end{aligned} $$

結束迴圈

  最後的結合策略,採用估計器權重的中位數對應的估計器的結果,得到最終的強估計器:

$$ \begin{aligned} H(x) &= \inf \left\{ y \in A: \sum_{h_i(x) \le y } \ln \left(\frac{1}{\alpha_i}\right) \ge \frac{1}{2} \sum_{i = 1}^{K} \ln \left(\frac{1}{\alpha_i}\right) \right\} \end{aligned} $$

<hr/>

四、原理證明

AdaBoost 演算法推導

  同演算法步驟中的前提條件一樣,假設訓練集 T = { X_i, y_i },i = 1,...,N,y_i 可取-1,+1,h(x) 為估計器,估計器的數量為 K。

  AdaBoost 演算法的一種解釋是加法模型,通過多個估計器 h(x) 加權以後得到最後的強估計器 H(x),如下所示:

(1)第 k-1 輪的強估計器表示式

(2)第 k 輪的強估計器表示式

(3)第 k 輪的強估計器可以由第 k-1 輪的強估計器和第 k 輪的加權估計器來表示

$$ \begin{aligned} H_{k-1}(x) &= \sum_{i = 1}^{k-1} \alpha_i h_i(x) & (1) \\ H_k(x) &= \sum_{i = 1}^{k} \alpha_i h_i(x) & (2) \\ H_k(x) &= H_{k-1}(x) + \alpha_k h_k(x) & (3) \\ \end{aligned} $$

式4-1

  接下來我們來定義最後強估計器的代價函式,AdaBoost 演算法選用的是指數函式,相比於0/1 函式具有更好的數學性質。

(1)指數代價函式

(2)帶入式 4-1中的(3)式

(3)我們的目標就是找到最優的估計器權重 α 和估計器 h(x)

(4)定義一個新的變數 ω,包含前一輪的強估計器等與 α 、h(x)無關的值

(5)替換 ω

$$ \begin{aligned} Cost(H(x)) &= \sum_{i = 1}^{N} e^{-y_iH(X_i)} & (1) \\ Cost(\alpha, h(x)) &= \sum_{i = 1}^{N} e^{-y_i(H_{k-1}(X_i) + \alpha h(X_i))} & (2) \\ \alpha_k, h_k(x) &= \underset{\alpha, h(x)}{\operatorname{argmin} } \sum_{i = 1}^{N} e^{-y_i(H_{k-1}(X_i) + \alpha h(X_i))} & (3) \\ \bar{\omega_{k,i}} &= e^{-y_iH_{k-1}(X_i)} & (4) \\ \alpha_k, h_k(x) &= \underset{\alpha, h(x)}{\operatorname{argmin} } \sum_{i = 1}^{N} \bar{\omega_{k,i}} e^{-y_i\alpha h(X_i)} & (5) \\ \end{aligned} $$

式4-2

  我們先來看下估計器 h(x),在每次訓練估計器後,估計器已經確定下來了,所以我們現在只需要關心每個估計器的權重 α 即可。

(1)找到最優的估計器權重 α 使得代價函式的取值最小

(2)代價函式 Cost(α)

(3)由於標籤值可取正負 1,根據預測值與標籤值是否相同拆為兩項

(4)增加第二、三兩項,不影響最後的結果

(5)將(4)式中前兩項和後兩項分別合併得到

$$ \begin{aligned} \alpha_k &= \underset{\alpha}{\operatorname{argmin} } \sum_{i = 1}^{N} \bar{\omega_{k,i}} e^{-y_i\alpha h_k(X_i)} & (1) \\ Cost(\alpha) &= \sum_{i = 1}^{N} \bar{\omega_{k,i}} e^{-y_i\alpha h_k(X_i)} & (2) \\ &= \sum_{y_i = h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{-\alpha} + \sum_{y_i \ne h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{\alpha} & (3) \\ &= \sum_{y_i = h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{-\alpha} + \sum_{y_i \ne h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{-\alpha} - \sum_{y_i \ne h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{-\alpha} + \sum_{y_i \ne h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{\alpha} & (4) \\ &= e^{-\alpha} \sum_{i = 1}^{N} \bar{\omega_{k,i}} + (e^{\alpha} - e^{-\alpha}) \sum_{i = 1}^{N} \bar{\omega_{k,i}} I(y_i \ne h_k(X_i)) & (5) \\ \end{aligned} $$

式4-3

(1)對代價函式求導數並令其為零

(2)定義錯誤率 e_k 的表示式

(3)將錯誤率 e_k 帶入(2)式

(4)兩邊同時乘以 exp(α)

(5)移項後整理得

(6)求得最後的估計器權重 α 的表示式

$$ \begin{aligned} \frac{\partial Cost(\alpha )}{\partial \alpha } &= -e^{-\alpha} \sum_{i = 1}^{N} \bar{\omega_{k,i}} + (e^{\alpha} + e^{-\alpha}) \sum_{i = 1}^{N} \bar{\omega_{k,i}} I(y_i \ne h_k(X_i)) = 0& (1) \\ e_k &= \frac{\sum_{i = 1}^{N}\bar{\omega_{k,i}} I(y_i \ne h_k(X_i))}{\sum_{i = 1}^{N}\bar{\omega_{k,i}}} & (2) \\ 0 &= -e^{-\alpha} + (e^\alpha + e^{-\alpha}) e_k & (3) \\ 0 &= -1 + (e^{2\alpha } + 1)e_k & (4) \\ e^{2\alpha } &= \frac{1 - e_k}{e_k} & (5) \\ \alpha &= \frac{1}{2} \ln \frac{1 - e_k}{e_k} & (6) \\ \end{aligned} $$

式4-4

(1)錯誤率 e_k 的定義

(2)定義 ω_k

(3)得到錯誤率 e_k 的表示式

$$ \begin{aligned} e_k &= \frac{\sum_{i = 1}^{N}\bar{\omega_{k,i}} I(y_i \ne h_k(X_i))}{\sum_{i = 1}^{N}\bar{\omega_{k,i}}} & (1) \\ \omega_{k,i} &= \frac{\bar{\omega_{k,i}}}{\sum_{i = 1}^{N}\bar{\omega_{k,i}}} & (2) \\ e_k &= \sum_{i = 1}^{N}\omega_{k,i} I(y_i \ne h_k(X_i)) & (3) \\ \end{aligned} $$

式4-5

  接下來是 ω 的更新方法:

(1) ω_{k+1} 的定義

(2)帶入式 4-1中的(3)式

(3)替換為 ω_k

$$ \begin{aligned} \bar{\omega_{k+1,i}} &= e^{-y_iH_{k}(X_i)} & (1) \\ &= e^{-y_i(H_{k-1}(X_i) + \alpha_kh_k(X_i))} & (2) \\ &= \bar{\omega_{k,i}}e^{-y_i\alpha_kh_k(X_i)} & (3) \end{aligned} $$

式4-6

(1)式 4-6中的(3)

(2)兩邊同時除以歸一化引數

(3)分子按照式 4-5中(2)式的定義替換,分母用式 4-7中(1)式替換

(4)分母再按照式 4-5中(2)式的定義替換

(5)由於 ω 的和為一個常數 C

(6)分子分母的常數 C 可以消除,得到 ω 的更新方表示式

$$ \begin{aligned} \bar{\omega_{k+1,i}} &= \bar{\omega_{k,i}}e^{-y_i\alpha_kh_k(X_i)} & (1) \\ \omega_{k+1,i} &= \frac{ \bar{\omega_{k,i}}e^{-y_i\alpha_kh_k(X_i)} }{\sum_{j = 0}^N \bar{\omega_{k+1,j}}} & (2) \\ &= \frac{\omega_{k,i} \sum_{j = 0}^N \left(\bar{\omega_{k,j}}\right) e^{-y_i\alpha_kh_k(X_i)} }{\sum_{j = 0}^N \left(\bar{\omega_{k,j}} e^{-y_j\alpha_kh_k(X_j)} \right) } & (3) \\ &= \frac{\omega_{k,i} \sum_{j = 0}^N \left(\bar{\omega_{k,j}}\right) e^{-y_i\alpha_kh_k(X_i)}}{\sum_{j = 0}^N \left(\omega_{k,j} \left(\sum_{l = 0}^N \bar{\omega_{k,l}}\right) e^{-y_j\alpha_kh_k(X_j)}\right) } & (4) \\ &= \frac{\omega_{k,i} C e^{-y_i\alpha_kh_k(X_i)}}{\sum_{j = 0}^N \left(\omega_{k,j} C e^{-y_j\alpha_kh_k(X_j)}\right) } & (5) \\ &= \frac{\omega_{k,i} e^{-y_i\alpha_kh_k(X_i)}}{\sum_{j = 0}^N \left(\omega_{k,j} e^{-y_j\alpha_kh_k(X_j)}\right) } & (6) \\ \end{aligned} $$

式4-7

  綜合式 4-1~式 4-7 可以得到 AdaBoost 演算法的表示式:

$$ \begin{aligned} e_k &= \sum_{i = 1}^{N}\omega_{k,i} I(y_i \ne h_k(X_i)) & (1) \\ \alpha_k &= \frac{1}{2} \ln \frac{1 - e_k}{e_k} & (2) \\ \omega_{k+1,i} &= \frac{\omega_{k,i} e^{-y_i\alpha_kh_k(X_i)}}{\sum_{j = 0}^N \left(\omega_{k,j} e^{-y_j\alpha_kh_k(X_j)}\right) } & (3) \\ H(x) &= \operatorname{sign} \left(\sum_{i = 1}^{K} \alpha_i h_i(x)\right) & (4) \\ \end{aligned} $$

式4-8

AdaBoost-SAMME 演算法推導

  同演算法步驟中的前提條件一樣,假設訓練集 T = { X_i, y_i },i = 1,...,N,y 的取值有 M 種可能,h(x) 為估計器,估計器的數量為 K。

  為了適應多分類問題,AdaBoost-SAMME 演算法將原本為數值的標籤 y 轉化成一個向量的形式,如式 4-9 所示:

$$ \hat{y} = \left\{ \begin{array}{c} 1 & y =m\\ -\frac{1}{M-1} & y \ne m \end{array}\right. \quad m = 1,\dots,M $$

式4-9

  下面用一個例子來說明式 4-9 的含義,假設標籤 y 可取 1,2,3,標籤集 y = { 2,1,2,3 },這時根據式 4-9 可以得到對應的轉換後的標籤集如式 4-10 所示:

$$ \begin{array}{c} y \in \{1,2,3\} \\ y = \{2,1,2,3\} \\ \hat{y}_i = \left\{ \begin{array}{c} 1 & y_i =m\\ -\frac{1}{2} & y_i \ne m \end{array}\right. \quad m = 1,2,3 \\ \hat{y} = \begin{bmatrix} -\frac{1}{2} & 1 & -\frac{1}{2} \\ 1 & -\frac{1}{2} & -\frac{1}{2} \\ -\frac{1}{2} & 1 & -\frac{1}{2} \\ -\frac{1}{2} & -\frac{1}{2} & 1 \end{bmatrix} \end{array} $$

式4-10

  同樣將演算法解釋為加法模型,通過多個估計器 h(x) 加權以後得到最後的強估計器 H(x),代價函式使用指數函式

(1)代價函式,這裡比原始演算法多了一個 1 / M,是為了後面計算方便,同時 H(X_i) 也是一個向量

(2)帶入式 4-1 中的(3)式

(3)同樣定義一個 ω,包含前一輪的強估計器等與 α 無關的值

(4)帶入 ω 得到代價函式的表示式

(5)目標為找到最優的估計器權重 α 使得代價函式的取值最小

$$ \begin{aligned} Cost(H(x)) &= \sum_{i = 1}^{N} e^{-\frac{1}{M} \hat{y}_iH(X_i)} & (1) \\ Cost(\alpha) &= \sum_{i = 1}^{N} e^{-\frac{1}{M}\hat{y}_i(H_{k-1}(X_i) + \alpha h_k(X_i))} & (2) \\ \bar{\omega_{k,i}} &= e^{-\frac{1}{M}\hat{y}_iH_{k-1}(X_i)} & (3) \\ Cost(\alpha) &= \sum_{i = 1}^{N} \bar{\omega_{k,i}} e^{-\frac{1}{M}\hat{y}_i\alpha h_k(X_i)} & (4) \\ \alpha_k &= \underset{\alpha}{\operatorname{argmin} } \sum_{i = 1}^{N} \bar{\omega_{k,i}} e^{-\frac{1}{M}\hat{y}_i\alpha h_k(X_i)} & (5) \\ \end{aligned} $$

式4-11

  我們先來看下代價函式中指數的部分,即預測值與標籤值的點積,下面分兩種情況討論:

  當預測值與標籤值相同的時候,向量中 1 的位置一致,-1 / (M - 1) 一共有 M - 1 個,得到如下的點積結果:

$$ \begin{aligned} 1 + \left(M - 1\right)\left(-\frac{1}{M-1}\right)\left(-\frac{1}{M-1}\right) = \frac{M}{M-1}\\ \end{aligned} $$

式4-12

  當預測值與標籤值不相同的時候,向量中 1 的位置不一致,-1 / (M - 1) 一共有 M - 2 個,得到如下的點積結果:

$$ \begin{aligned} \left(-\frac{1}{M-1}\right) + \left(-\frac{1}{M-1}\right) + \left(M - 2\right) \left(-\frac{1}{M-1}\right)\left(-\frac{1}{M-1}\right) = -\frac{M}{(M-1)^2} \end{aligned} $$

式4-13

  綜合上面兩種情況,得到如下的結果:

$$ \hat{y}_ih_k(X_i) = \left\{ \begin{aligned} &\frac{M}{M-1} & \hat{y}_i = h_k(X_i) \\ &-\frac{M}{(M-1)^2} & \hat{y}_i \ne h_k(X_i) \end{aligned} \right. $$

式4-14

(1)代價函式 Cost(α)

(2)分兩種情況帶入式 4-14

(3)增加第二、三兩項,不影響最後的結果

(4)將(3)式中前兩項和後兩項分別合併得到

$$ \begin{aligned} Cost(\alpha) &= \sum_{i = 1}^{N} \bar{\omega_{k,i}} e^{-\frac{1}{M}\hat{y}_i\alpha h_k(X_i)} & (1) \\ &= \sum_{\hat{y}_i = h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{-\frac{\alpha}{M-1} } + \sum_{\hat{y}_i \ne h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{\frac{\alpha}{(M-1)^2}} & (2) \\ &= \sum_{\hat{y}_i = h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{-\frac{\alpha}{M-1} } + \sum_{\hat{y}_i \ne h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{-\frac{\alpha}{M-1}} - \sum_{\hat{y}_i \ne h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{-\frac{\alpha}{M-1}} + \sum_{\hat{y}_i \ne h_k(X_i)}^{N} \bar{\omega_{k,i}} e^{\frac{\alpha}{(M-1)^2}} & (3) \\ &= e^{-\frac{\alpha}{M-1} } \sum_{i = 1}^{N} \bar{\omega_{k,i}} + (e^{\frac{\alpha}{(M-1)^2}} - e^{-\frac{\alpha}{M-1}}) \sum_{i = 1}^{N} \bar{\omega_{k,i}} I(\hat{y}_i \ne h_k(X_i)) & (4) \\ \end{aligned} $$

式4-15

(1)對代價函式求導數並令其為零

(2)定義錯誤率 e_k 的表示式

(3)將錯誤率 e_k 帶入(2)式

(4)兩邊同時乘以 exp(α / (M - 1))

(5)移項後整理得

(6)求得最後的估計器權重 α 的表示式

$$ \begin{aligned} \frac{\partial Cost(\alpha )}{\partial \alpha } &= \left(-\frac{1}{M-1}\right)e^{-\frac{\alpha}{M-1}} \sum_{i = 1}^{N} \bar{\omega_{k,i}} + \left(\left(\frac{1}{(M-1)^2}\right)e^{\frac{\alpha}{(M-1)^2}} + \left(\frac{1}{(M-1)}\right)e^{-\frac{\alpha}{M-1}}\right) \sum_{i = 1}^{N} \bar{\omega_{k,i}} I(y_i \ne h_k(X_i)) = 0& (1) \\ e_k &= \frac{\sum_{i = 1}^{N}\bar{\omega_{k,i}} I(y_i \ne h_k(X_i))}{\sum_{i = 1}^{N}\bar{\omega_{k,i}}} & (2) \\ e^{-\frac{\alpha}{M-1}} &= \left(\left(\frac{1}{M-1}\right)e^{\frac{\alpha}{(M-1)^2}} + e^{-\frac{\alpha}{M-1}}\right) e_k & (3) \\ 1 &= \left(\left(\frac{1}{M-1}\right)e^{\frac{\alpha}{(M-1)^2} + \frac{\alpha}{M-1}} + 1\right) e_k & (4) \\ \frac{1 - e_k}{e_k} &= \left(\frac{1}{M-1}\right)e^{\frac{M\alpha}{(M-1)^2}} & (5) \\ \alpha &= \frac{(M-1)^2}{M}\left( \ln \left(\frac{1 - e_k}{e_k}\right) + \ln (M - 1) \right) & (6) \end{aligned} $$

式4-16

  式 4-16 中估計器權重 α 的表示式前面的常數在進過歸一化後對結果沒有影響,後面的樣本權重更新的公式一樣也是簡化後的結果。更多詳細的演算法說明請參考原始論文——Multi-class AdaBoost7

AdaBoost-SAMME.R 演算法推導

  AdaBoost-SAMME.R 演算法是 AdaBoost-SAMME 演算法的變體,該演算法是使用加權概率估計來更新加法模型,如式 4-17 所示:

$$ \begin{aligned} H_k(x) = H_{k - 1}(x) + h_k(x) \end{aligned} $$

式4-17

  代價函式使用的依然是指數函式,不同的是已經沒有了估計器權重或者說每一個估計器的權重都為 1,且改成了期望的形式,其中 h(x) 返回的是 M 維的向量,同時為保證求出的 h(x) 唯一,加上了向量的各個元素之和為 0 的限制條件。

$$ \begin{array}{c} h_k(x) = \underset{h(x)}{\operatorname{argmax}} E(e^{-\frac{1}{M} \hat{y}_i (H_{k-1}(x) + h(x)) } \mid x) \\ s.t. \quad h_k^1(x) + h_k^2(x) + \cdots + h_k^M(x) = 0 \end{array} $$

式4-18

  代價函式可以拆分成對每一類分別求期望後再相加:

$$ \begin{aligned} Cost(h(x)) &= E(e^{-\frac{1}{M} \hat{y}_i (H_{k-1}(x) + h(x)) } \mid x) & (1) \\ &= E(e^{-\frac{1}{M} \hat{y}_i H_{k-1}(x)}e^{-\frac{1}{M}\hat{y}_ih(x) } \mid x) & (2) \\ &= E(e^{-\frac{1}{M} \hat{y}_i H_{k-1}(x)}e^{-\frac{1}{M}\hat{y}_ih(x) } I(y = 1) \mid x) + \cdots + E(e^{-\frac{1}{M} \hat{y}_i H_{k-1}(x)}e^{-\frac{1}{M}\hat{y}_ih(x) } I(y = M) \mid x) & (3) \\ \end{aligned} $$

式4-19

  先來看看當 y = 1 時,y * h(x) 的結果:

(1)當 y = 1 時,轉換後 y 的向量形式

(2)計算點積的結果

(3)合併最後的項

(4)根據限制條件替換

(5)得到化簡後的結果

$$ \begin{aligned} \hat{y} &= [1, -\frac{1}{M - 1}, \cdots, -\frac{1}{M - 1} ] & (1) \\ \hat{y}_ih(x) &= h^1(x) + (-\frac{1}{M - 1})h^2(x) + \cdots + (-\frac{1}{M - 1})h^M(x) & (2) \\ &= h^1(x) - \frac{h^2(x) + \cdots + h^M(x)}{M - 1} & (3) \\ &= h^1(x) - \frac{-h^1(x)}{M - 1} & (4) \\ &= \frac{Mh^1(x)}{M - 1} & (5) \\ \end{aligned} $$

式4-20

(1)帶入式 4-20

(2)提出與期望無關的項

(3)另後面的期望為 P(y = 1 | x)

(4)同理可以得每一類的期望結果

$$ \begin{aligned} E(e^{-\frac{1}{M} \hat{y}_i H_{k-1}(x)}e^{-\frac{1}{M}\hat{y}_ih(x) } I(y = 1) \mid x) &= E(e^{-\frac{1}{M} \hat{y}_i H_{k-1}(x)}e^{-\frac{h^1(x)}{M-1} } I(y = 1) \mid x) & (1) \\ &= e^{-\frac{h^1(x)}{M-1}} E(e^{-\frac{1}{M} \hat{y}_i H_{k-1}(x)} I(y = 1) \mid x) & (2) \\ P(y = 1 | x) &= E(e^{-\frac{1}{M} \hat{y}_i H_{k-1}(x)} I(y = 1) \mid x) & (3) \\ E(e^{-\frac{1}{M} \hat{y}_i H_{k-1}(x)}e^{-\frac{1}{M}\hat{y}_ih(x) } I(y = m) \mid x) &= e^{-\frac{h^m(x)}{M-1}} P(y = m | x) & (4) \\ \end{aligned} $$

式4-21

  將上面的結果帶入代價函式得:

$$ \begin{aligned} Cost(h(x)) &= e^{-\frac{h^1(x)}{M-1}} P(y = 1 | x) + \cdots + e^{-\frac{h^M(x)}{M-1}} P(y = M | x) & (1) \\ &= \sum_{m = 1}^{M} e^{-\frac{h^m(x)}{M-1}} P(y = m | x) & (2) \\ \end{aligned} $$

式4-22

  這時可以使用拉格朗日乘數法來求解上述問題,其拉格朗日函式 L 如下:

$$ \begin{aligned} L(h(x), \lambda ) &= \sum_{m = 1}^{M} e^{-\frac{h^m(x)}{M-1}} P(y = m | x) - \lambda \sum_{m = 1}^{M} h^m(x)\\ \end{aligned} $$

式4-23

  拉格朗日函式分別對 h(x) 的各個分量求導數:

$$ \begin{aligned} \frac{\partial L(h(x), \lambda)}{\partial h^1(x)} &= -\frac{1}{M-1} e^{-\frac{h^1(x)}{M-1}} P(y = 1 | x) - \lambda = 0 \\ \frac{\partial L(h(x), \lambda)}{\partial h^2(x)} &= -\frac{1}{M-1} e^{-\frac{h^2(x)}{M-1}} P(y = 2 | x) - \lambda = 0 \\ & \cdots \\ \frac{\partial L(h(x), \lambda)}{\partial h^M(x)} &= -\frac{1}{M-1} e^{-\frac{h^M(x)}{M-1}} P(y = M | x) - \lambda = 0 \\ \end{aligned} $$

式4-24

  兩兩聯立式 4-24 ,分別求出各個分量的結果,下面以第一個為例:

(1)聯立導數中的第 1,2 式子

(2)消掉相同的常數項再兩邊同時取對數

(3)移項化簡後得

$$ \begin{aligned} -\frac{1}{M-1} e^{-\frac{h^1(x)}{M-1}} P(y = 1 | x) &= -\frac{1}{M-1} e^{-\frac{h^2(x)}{M-1}} P(y = 2 | x) & (1)\\ -\frac{h^1(x)}{M-1} + \ln P(y = 1 | x) &= -\frac{h^2(x)}{M-1} + \ln P(y = 2 | x) & (2) \\ h^1(x) - h^2(x) &= (M - 1) (\ln P(y = 1 | x) - \ln P(y = 2 | x)) & (3) \\ \end{aligned} $$

式4-25

(1)~(3)同理可得

(4)將(1)~(3)式累加起來根據限制條件化簡

(5)將最後一項補充完整

(6)得到第一個分量的結果

$$ \begin{aligned} h^1(x) - h^2(x) &= (M - 1) (\ln P(y = 1 | x) - \ln P(y = 2 | x)) & (1) \\ h^1(x) - h^3(x) &= (M - 1) (\ln P(y = 1 | x) - \ln P(y = 3 | x)) & (2) \\ & \cdots \\ h^1(x) - h^M(x) &= (M - 1) (\ln P(y = 1 | x) - \ln P(y = M | x)) & (3) \\ (M - 1) h^1(x) - (-h^1(x)) &= (M - 1)((M - 1)\ln P(y = 1 | x) - \sum_{m \ne 1} \ln P(y = m | x))) & (4) \\ Mh^1(x) &= (M - 1)(M\ln P(y = 1 | x) - \sum_{m = 1}^{M} \ln P(y = m | x)) & (5) \\ h^1(x) &= (M - 1)(\ln P(y = 1 | x) - \frac{1}{M} \sum_{m = 1}^{M} \ln P(y = m | x)) & (6) \\ \end{aligned} $$

式4-26

  同理可得 h(x) 各個分量的結果

$$ \begin{aligned} h^m(x) &= (M - 1)(\ln P(y = m | x) - \frac{1}{M} \sum_{m^{'} = 1}^{M} \ln P(y = m^{'} | x)) \\ \end{aligned} $$

式4-27

  樣本權重的更新如下,將 h(x) 帶入更新方法中,可以看到更新方法只保留了前面一項,因為後面一項為每一類的 p(x) 求和,可以認為是一個常數,歸一化以後不影響最後的結果。

$$ \begin{aligned} \bar{\omega_{k,i}} &= e^{-\frac{1}{M}\hat{y}_iH_{k-1}(X_i)} & (1) \\ \bar{\omega_{k+1,i}} &= \bar{\omega_{k,i}} e^{-\frac{1}{M}\hat{y}_ih_{k}(X_i)} & (2) \\ &= \bar{\omega_{k,i}} e^{-\frac{M - 1}{M}\hat{y}_i\ln p_k(X_i)} & (3) \\ \end{aligned} $$

式4-28

  這樣就得到了演算法步驟中的樣本權重的更新公式,更多詳細的演算法說明也請參考原始論文——Multi-class AdaBoost7

五、程式碼實現

使用 Python 實現 AdaBoost 演算法

import numpy as np
from sklearn.tree import DecisionTreeClassifier

class adaboostc():
    """
    AdaBoost 分類演算法
    """

    def __init__(self, n_estimators = 100):
        # AdaBoost弱學習器數量
        self.n_estimators = n_estimators

    def fit(self, X, y):
        """
        AdaBoost 分類演算法擬合
        """
        # 初始化樣本權重向量
        sample_weights = np.ones(X.shape[0]) / X.shape[0]
        # 估計器陣列
        estimators = []
        # 估計器權重陣列
        weights = []
        # 遍歷估計器
        for i in range(self.n_estimators):
            # 初始化最大深度為1的決策樹估計器
            estimator = DecisionTreeClassifier(max_depth = 1)
            # 按照樣本權重擬合訓練集
            estimator.fit(X, y, sample_weight=sample_weights)
            # 預測訓練集
            y_predict = estimator.predict(X)
            # 計算誤差率
            e = np.sum(sample_weights[y_predict != y])
            # 當誤差率大於等於0.5時跳出迴圈
            if e >= 0.5:
                self.n_estimators = i
                break
            # 計算估計器權重
            weight = 0.5 * np.log((1 - e) / e)
            # 計算樣本權重
            temp_weights = np.multiply(sample_weights, np.exp(- weight * np.multiply(y, y_predict)))
            # 歸一化樣本權重
            sample_weights = temp_weights / np.sum(temp_weights)
            weights.append(weight)
            estimators.append(estimator)
        self.weights = weights
        self.estimators = estimators

    def predict(self, X):
        """
        AdaBoost 分類演算法預測
        """
        y = np.zeros(X.shape[0])
        # 遍歷估計器
        for i in range(self.n_estimators):
            estimator = self.estimators[i]
            weight = self.weights[i]
            # 預測結果
            predicts = estimator.predict(X)
            # 按照估計器的權重累加
            y += weight * predicts
        # 根據權重的正負號返回結果
        return np.sign(y)

使用 Python 實現 AdaBoost-SAMME 演算法

import numpy as np
from sklearn.tree import DecisionTreeClassifier

class adaboostmc():
    """
    AdaBoost 多分類SAMME演算法
    """

    def __init__(self, n_estimators = 100):
        # AdaBoost弱學習器數量
        self.n_estimators = n_estimators

    def fit(self, X, y):
        """
        AdaBoost 多分類SAMME演算法擬合
        """
        # 標籤分類
        self.classes = np.unique(y)
        # 標籤分類數
        self.n_classes = len(self.classes)
        # 初始化樣本權重向量
        sample_weights = np.ones(X.shape[0]) / X.shape[0]
        # 估計器陣列
        estimators = []
        # 估計器權重陣列
        weights = []
        # 遍歷估計器
        for i in range(self.n_estimators):
            # 初始化最大深度為1的決策樹估計器
            estimator = DecisionTreeClassifier(max_depth = 1)
            # 按照樣本權重擬合訓練集
            estimator.fit(X, y, sample_weight=sample_weights)
            # 訓練集預測結果
            y_predict = estimator.predict(X)
            incorrect = y_predict != y
            # 計算誤差率
            e = np.sum(sample_weights[incorrect])
            # 計算估計器權重
            weight = np.log((1 - e) / e) + np.log(self.n_classes - 1)
            # 計算樣本權重
            temp_weights = np.multiply(sample_weights, np.exp(weight * incorrect))
            # 歸一化樣本權重
            sample_weights = temp_weights / np.sum(temp_weights)
            weights.append(weight)
            estimators.append(estimator)
        self.weights = weights
        self.estimators = estimators

    def predict(self, X):
        """
        AdaBoost 多分類SAMME演算法預測
        """
        # 加權結果集合
        results = np.zeros((X.shape[0], self.n_classes))
        # 遍歷估計器
        for i in range(self.n_estimators):
            estimator = self.estimators[i]
            weight = self.weights[i]
            # 預測結果
            predicts = estimator.predict(X)
            # 遍歷標籤分類
            for j in range(self.n_classes):
                # 對應標籤分類的權重累加
                results[predicts == self.classes[j], j] += weight
        # 取加權最大對應的分類作為最後的結果
        return self.classes.take(np.argmax(results, axis=1), axis=0)

使用 Python 實現 AdaBoost-SAMME.R 演算法

import numpy as np
from sklearn.tree import DecisionTreeClassifier

class adaboostmcr():
    """
    AdaBoost 多分類SAMME.R演算法
    """

    def __init__(self, n_estimators = 100):
        # AdaBoost弱學習器數量
        self.n_estimators = n_estimators

    def fit(self, X, y):
        """
        AdaBoost 多分類SAMME.R演算法擬合
        """
        # 標籤分類
        self.classes = np.unique(y)
        # 標籤分類數
        self.n_classes = len(self.classes)
        # 初始化樣本權重
        sample_weights = np.ones(X.shape[0]) / X.shape[0]
        # 估計器陣列
        estimators = []
        # 論文中對 y 的定義
        y_codes = np.array([-1. / (self.n_classes - 1), 1.])
        # 將訓練集中的標籤值轉換成論文中的矩陣形式
        y_coding = y_codes.take(self.classes == y[:, np.newaxis])
        # 遍歷估計器
        for i in range(self.n_estimators):
            # 初始化最大深度為1的決策樹估計器
            estimator = DecisionTreeClassifier(max_depth = 1)
            # 根據樣本權重擬合訓練集
            estimator.fit(X, y, sample_weight=sample_weights)
            # 預測訓練集標籤值的概率
            y_predict_proba = estimator.predict_proba(X)
            # 處理概率為0的結果,避免取對數是結果為負無窮大的問題
            np.clip(y_predict_proba, np.finfo(y_predict_proba.dtype).eps, None, out=y_predict_proba)
            # 計算樣本權重
            temp_weights = sample_weights * np.exp(- ((self.n_classes - 1) / self.n_classes) * np.sum(np.multiply(y_coding, np.log(y_predict_proba)), axis=1))
            # 歸一化樣本權重
            sample_weights = temp_weights / np.sum(temp_weights)
            estimators.append(estimator)
        self.estimators = estimators

    def predict(self, X):
        """
        AdaBoost 多分類SAMME.R演算法預測
        """
        # 結果集合
        results = np.zeros((X.shape[0], self.n_classes))
        # 遍歷估計器
        for i in range(self.n_estimators):
            estimator = self.estimators[i]
            # 預測標籤值的概率
            y_predict_proba = estimator.predict_proba(X)
            # 同樣需要處理零概率的問題
            np.clip(y_predict_proba, np.finfo(y_predict_proba.dtype).eps, None, out=y_predict_proba)
            # 對概率取對數
            y_predict_proba_log = np.log(y_predict_proba)
            # 計算 h(x)
            h = (self.n_classes - 1) * (y_predict_proba_log - (1 / self.n_classes) * np.sum(y_predict_proba_log, axis=1)[:, np.newaxis])
            # 累加
            results += h
        # 取累加最大對應的分類作為最後的結果
        return self.classes.take(np.argmax(results, axis=1), axis=0)

使用 Python 實現 AdaBoost.R2 演算法

import numpy as np
from sklearn.tree import DecisionTreeRegressor

class adaboostr():
    """
    AdaBoost 迴歸演算法
    """

    def __init__(self, n_estimators = 100):
        # AdaBoost弱學習器數量
        self.n_estimators = n_estimators

    def fit(self, X, y):
        """
        AdaBoost 迴歸演算法擬合
        """
        # 初始化樣本權重向量
        sample_weights = np.ones(X.shape[0]) / X.shape[0]
        # 估計器陣列
        estimators = []
        # 估計器權重陣列
        weights = []
        # 遍歷估計器
        for i in range(self.n_estimators):
            # 初始化最大深度為3的決策樹估計器
            estimator = DecisionTreeRegressor(max_depth = 3)
            # 根據樣本權重擬合訓練集
            estimator.fit(X, y, sample_weight=sample_weights)
            # 預測結果
            y_predict = estimator.predict(X)
            # 計算誤差向量(線性誤差)
            errors = np.abs(y_predict - y)
            errors = errors / np.max(errors)
            # 計算誤差率
            e = np.sum(np.multiply(errors, sample_weights))
            # 當誤差率大於等於0.5時跳出迴圈
            if e >= 0.5:
                self.n_estimators = i
                break
            # 計算估計器權重
            weight = e / (1 - e)
            # 計算樣本權重
            temp_weights = np.multiply(sample_weights, np.power(weight, 1 - errors))
            # 歸一化樣本權重
            sample_weights = temp_weights / np.sum(temp_weights)
            weights.append(weight)
            estimators.append(estimator)
        self.weights = np.array(weights)
        self.estimators = np.array(estimators)

    def predict(self, X):
        """
        AdaBoost 迴歸演算法預測
        """
        # 論文中權重的定義
        weights = np.log(1 / self.weights)
        # 預測結果矩陣
        predictions = np.array([self.estimators[i].predict(X) for i in range(self.n_estimators)]).T
        # 根據預測結果排序後的下標
        sorted_idx = np.argsort(predictions, axis=1)
        # 根據排序結果依次累加估計器權重,得到新的累積權重矩陣,類似累積分佈函式的定義
        weight_cdf = np.cumsum(weights[sorted_idx], axis=1, dtype=np.float64)
        # 累積權重矩陣中大於其中中位數的結果
        median_or_above = weight_cdf >= 0.5 * weight_cdf[:, -1][:, np.newaxis]
        # 中位數結果對應的下標
        median_idx = median_or_above.argmax(axis=1)
        # 對應的估計器
        median_estimators = sorted_idx[np.arange(X.shape[0]), median_idx]
        # 取對應的估計器的預測結果作為最後的結果
        return predictions[np.arange(X.shape[0]), median_estimators]

六、第三方庫實現

scikit-learn3 實現自適應增強分類

from sklearn.ensemble import AdaBoostClassifier

# 自適應增強分類器 SAMME 演算法
clf = AdaBoostClassifier(n_estimators = 50, random_state = 0, algorithm = "SAMME")
# 自適應增強分類器 SAMME.R 演算法
clf = AdaBoostClassifier(n_estimators = 50, random_state = 0, algorithm = "SAMME.R")
# 擬合資料集
clf = clf.fit(X, y)

scikit-learn4 實現自適應增強迴歸

from sklearn.ensemble import AdaBoostRegressor

# 自適應增強迴歸器
clf = AdaBoostRegressor(n_estimators = 50, random_state = 0)
# 擬合資料集
clf = clf.fit(X, y)

七、示例演示

  圖 7-1 展示了使用自適應增強演算法進行二分類的結果,紅色表示標籤值為 -1 的樣本點,藍色代表標籤值為 1 的樣本點。淺紅色的區域為預測值為 -1 的部分,淺藍色的區域則為預測值為 1 的部分

1.png
<center>圖7-1</center>

  圖 7-2 、圖 7-3 分別展示了使用 SAMME 和 SAMME.R 演算法進行多分類的結果,紅色表示標籤值為 0 的樣本點,藍色代表標籤值為 1 的樣本點,綠色代表標籤值為 2 的樣本點。淺紅色的區域為預測值為 0 的部分,淺藍色的區域則為預測值為 1 的部分,淺綠色的區域則為預測值為 1 的部分

2.png
<center>圖7-2</center>

3.png
<center>圖7-3</center>

  圖 7-4 展示了使用自適應增強演算法進行迴歸的結果

4.png
圖7-4

八、思維導圖

5.jpeg
圖8-1

九、參考文獻

  1. https://en.wikipedia.org/wiki...(machine_learning)
  2. https://en.wikipedia.org/wiki...
  3. https://scikit-learn.org/stab...
  4. https://scikit-learn.org/stab...
  5. https://www.face-rec.org/algo...
  6. https://citeseer.ist.psu.edu/...
  7. https://hastie.su.domains/Pap...

完整演示請點選這裡

注:本文力求準確並通俗易懂,但由於筆者也是初學者,水平有限,如文中存在錯誤或遺漏之處,懇請讀者通過留言的方式批評指正

本文首發於——AI導圖,歡迎關注

相關文章