集成思想是機器學習中重要的思想之一,kaggle中常用的的xgboost就是集成的應用。其基本框架是:假如你有一打分類器(我們稱之為基分類器),假設這些分類器有不同的屬性,將這些基分類器結合起來, 會有意想不到的效果,這篇文章記錄的事集成思想的兩種重要表現:Bagging與Boosting。本文是李宏毅老師ML Lecture22: Ensemble的筆記,建議大家去觀看原視頻。

Bagging

假設現在有N筆數據,每次從這N筆數據中sample出N個樣本,就是通過這樣的方式可以sample出多個database,接下來用一個複雜的模型對每個resample的database做訓練,就得到了幾個不同的function。接下來在做預測的時候,把數據分別丟進這些模型,然後對結果做平均(對回歸問題)或者投票(對分類問題),這就是bagging的思想。

什麼時候做bagging?當你的模型很複雜,bias低而variance高,容易過擬合的時候去做bagging。決策樹這樣的模型就很容易過擬合,所以bagging經常會與決策樹一起用。

隨機森林

隨機森林就是bagging的一個應用。當然僅僅是隨機sample是不夠的,在每一次隨機劃選擇數據的時候,還需要隨機決定使用哪些特徵。最後把這些樹結合起來就是隨機森林。同時注意隨機森林在使用時並不需要劃分訓練集。

Boosting

Boosting是用在弱的基分類器(erro rate小於0.5就可以)上,通過集成弱分類器,可以得到一個效果較好的綜合分類器。首先需要找一個分類器 f_1(x) ,然後找另一個分類器 f_2(x) 去幫助 f_1(x) , 當然 f_2(x) 不能和 f_1(x) 太相似。接下來,再尋找第二個 f_2(x) ,最後再把所有的分類器集合起來...在這裡注意,boosting的分類器選擇是有順序的,而上面說的bagging是沒順序的。

那麼怎麼樣得到不同的基分類器呢?我們可以通過構造的訓練集來訓練不同的分類器。除了resample數據,也可以改變每個數據的權重即re-weight,在實際應用中,一般是通過修改損失函數來完成的,對於不同的樣本,其損失函數前面會乘上不同的洗漱,比如我們對每一筆數據一個weight u,開始所有的u都是1,我們可以重新賦值u,令不同的數據不一樣。現在的一筆數據可以表示為:(x^1, hat{y}, mu^1) ,原來我們的目標函數是: L(f) = sum_nl(f(x^n), hat y^n) ,現在變為 L(f) = sum_n u^nl(f(x^n), hat y^n) 。下面我們看看經典的boosting演算法Adaboost的原理:

Adaboost

Adaboost的意思是,在 f_1(x) 訓練不好的數據上訓練去訓練 f_2(x) , 那麼主要問題是, 怎麼找到這個 f_1(z) 訓練不好的數據集呢?

我們通過計算 f_1(x) 的error rate varepsilon_1 來得到新的數據集

varepsilon_1 = frac{sum_n u_1^nsigma(f_1(x^n)
e hat y^n)}{Z_1} \ Z_1=sum_nmu_1^n

只要基分類器不是隨機的,那麼 varepsilon_1總會小於 0.5。

接下來,我們將這些data的·權重 mu_1 改為 mu_2 ,使得:

varepsilon_2 = frac{sum_n u_2^nsigma(f_1(x^n)
e hat y^n)}{Z_2} = 0.5\

那麼這個操作就好像是說,我們re-weight了數據後, f_1(x) 的表現變差了。

接下來拿這組新的數據去訓練 f_2(x) ,那麼就是我們剛剛說的在 f_1(x) 上訓練不好的數據上訓練 f_2(x) 了。

來看個實例。現在有四筆數據,如下圖,我們的 f_1(x) 最開始認錯了一筆, varepsilon_1 =0.25,之後我們把答錯的data 權重調高,答對的權重調低,然後把這組re-weight的data來訓練 f_2(x)

圖片來自李宏毅老師ensemble課程

我們整理一下過程,實際上Adaboost是這樣操作的

如果 x^n 被分類錯誤,讓麼令 u_2^n = u_1^nd_1

如果 x^n 被分類正確,讓麼令 u_2^n = frac{u_1^n}{d_1}

那麼 d_1怎麼設定呢?我們之前提到說

varepsilon_1 = frac{sum_n u_1^nsigma(f_1(x^n)
e hat y^n)}{Z_1} \ Z_1=sum_nmu_1^n

同時 varepsilon_2 = frac{sum_n u_2^nsigma(f_1(x^n)
e hat y^n)}{Z_2} = 0.5\

u_2 是由 u_1d_1 乘除得到的。那麼上式的分母可以改寫為:

{sum_n u_1^nsigma(f_1(x^n)
e hat y^n)} = sum_{f_1(x^n)
ehat y^n}u_1^nd_1

分子可以改寫為:

Z_2=sum_nu_2^n = sum_{f_1(x^n)
ehat y^n} u_2^n + sum_{f_1(x^n)hat =y^n} u_2^n \ =  sum_{f_1(x^n)
ehat y^n} u_1^n d_1 + sum_{f_1(x^n)hat =y^n} u_1^n/d_1

根據上面兩式,我們便可以將 varepsilon_2 的公式化為:

frac{sum_{f_1(x^n)
ehat y^n }u_1^nd_1}{sum_{f_1(x^n)
ehat y^n }u_1^nd_1 + sum_{f_1(x^n)=hat y^n}u_1^n/d_1} = 0.5

我們把上式顛倒過來,在消去分子分母中都包含的項,得到

frac{sum_{f_1(x^n)=hat y^n}u_1^n/d_1}{sum_{f_1(x^n)
ehat y ^n}u_1^nd_1} = 1

也就是說

sum_{f_1(x^n)=hat y^n}u_1^n/d_1 = sum_{f_1(x^n)
ehat y^n}u_1^n/d_1

我們知道,

varepsilon_1 = frac{sum_n u_1^nsigma(f_1(x^n)
e hat y^n)}{Z_1} \ Z_1=sum_nmu_1^n

因此 u_1^n 可以用 varepsilon_1,Z_1 表示,於是,我們可以推出

d_1 = sqrt{(1-varepsilon_1)/varepsilon_1}

根據上面的演算法解釋,我們可以列出AdaBoost的流程:

AdaBoost流程

  • 給定訓練數據 {(x^1, hat y^1, mu_1^1),...,(x^n, hat y^n, mu_1^n),...,(x^N, hat y^N, mu_1^N)
    • hat y = pm 1, u_1^n=1
  • 對每次epoch t = 1...T:
    • 訓練一個基分類器 f_t(x) ,權重記為 {u_t^1,...,u_t^N}
    • varepsilon_t 是 基於{u_t^1,...,u_t^N}f_t(x) 的error rate
    • 對於n=1,...,N:
      • 如果分類錯誤,那麼 u_{t+1}^n = u_t^n *d_t , 反之 u_{t+1}^n = u_t^n /d_td_t = sqrt{(1-varepsilon_t)/varepsilon_t} ,這裡我們為了把兩種情況合併為一個式子,我們不再使用 d_t ,而使用 alpha_t 作為參數,令 alpha_t = lnsqrt{(1-varepsilon_t)/varepsilon_t} , 則 u_{t+1}^n = u_t^n * exp(-hat y^nf_t(x^n)alpha_t) ,其中 hat y 是真實的分類標籤。
    • 現在我們得到了一打基分類器 f_1(x),...,f_t(x),...,f_T(x) ,我們計算 H(x) = sign(sum_{t=1}^Talpha_tf_t(x)) ,相當於說每個分類器乘上一個權重(也就是前面幾步中用的 alpha_t ),優秀的基分類器的權重會更大,弱雞的則會更小。最後計算所有分類器雷加起來的正負值,就可以確定類別。

推薦閱讀:

相關文章