1. 程式人生 > >機器學習:AdaBoost演算法及其實現

機器學習:AdaBoost演算法及其實現

文章目錄

楔子

前面提到boosting演算法為一類演算法,這一類演算法框架分為3步:1、訓練一個弱分類;2、根據分類結果調整樣本權重;3、最後決策時,根據弱模型的表現來決定其話語權。
那麼這裡面就有2個關鍵點:
1、如何調整樣本權重;
2、如何根據弱模型的表現來決定其話語權。

演算法描述:

adaboost裡的樣本權重和話語權

事實上,能夠將這兩個問題的解決方案有機地糅合在一起、正是 AdaBoost 的巧妙之處之一。

如何調整樣本權重,一個弱分類器得到一個錯誤分類率e > 0.5, 我們調整樣本權重是分類錯誤率等於0.5,用這個樣本權重用於下一個分類器,這個這兩個分類器就不會強相關,這個就是調整樣本權重的主要思想。

分類錯誤樣本權重乘以d倍,分類正確樣本權重處理d,得到e*d = (1-e)/d =====> d^2 = (1-e)/e

我們定義該分類器的話語權為:alpha = ln(d) = 0.5*ln (1-e)/e,話語權是隨著錯誤率的增大而減小的。

事實上,能夠將這兩個問題的解決方案有機地糅合在一起、正是 AdaBoost 的巧妙之處之一。

實際的樣本權重是歸一化處理過的:
在這裡插入圖片描述

演算法描述

在這裡插入圖片描述

AdaBoost的實現:

實現比較簡單,首先你的分類器需要支援樣本權重,然後按照序列呼叫你的分類器就行了,每次把計算好的樣本權重傳進去。

class AdaBoost:
    # 弱分類器字典,如果想要測試新的弱分類器的話、只需將其加入該字典即可
    _weak_clf = {
        "SKMNB": SKMultinomialNB,
        "SKGNB": SKGaussianNB,
        "SKTree": SKTree,
        "MNB": MultinomialNB,
        "GNB": GaussianNB,
"ID3": ID3Tree, "C45": C45Tree, "Cart": CartTree } """ AdaBoost框架的樸素實現 使用的弱分類器需要有如下兩個方法: 1) 'fit' 方法,它需要支援輸入樣本權重 2) 'predict' 方法, 它用於返回預測的類別向量 """ def __init__(self): # 初始化結構 # self._clf:記錄弱分類器名稱的變數 # self._clfs:記錄弱分類器的列表 # self._clfs_weights:記錄弱分類器“話語權”的列表 self._clf, self._clfs, self._clfs_weights = "", [], [] def fit(self, x, y, sample_weight=None, clf=None, epoch=10, eps=1e-12, **kwargs): # 預設使用10個CART決策樹樁作為弱分類器 if clf is None or AdaBoost._weak_clf[clf] is None: clf = "Cart" kwargs = {"max_depth": 1} # 當前使用的分類器 self._clf = clf # 樣本權重,注意是歸一化後的樣本權重,預設樣本權重為[1/N,1/N,...] if sample_weight is None: sample_weight = np.ones(len(y)) / len(y) else: sample_weight = np.array(sample_weight) # AdaBoost演算法的主迴圈,epoch為迭代次數 for _ in range(epoch): # 根據樣本權重訓練弱分類器 tmp_clf = AdaBoost._weak_clf[clf](**kwargs) tmp_clf.fit(x, y, sample_weight) # 呼叫弱分類器的predict方法進行預測 y_pred = tmp_clf.predict(x) # 計算加權錯誤率;考慮到數值穩定性,在邊值情況加了一個小的常數 # 點乘是行*列 em = min(max((y_pred != y).dot(self._sample_weight[:, None])[0], eps), 1 - eps) # 計算該弱分類器的“話語權”,化簡了一下 am = 0.5 * log(1 / em - 1) # 更新樣本權重並利用deepcopy將該弱分類器記錄在列表中 sample_weight *= np.exp(-am * y * y_pred) sample_weight /= np.sum(sample_weight) # 記錄分類器和話語權 self._clfs.append(deepcopy(tmp_clf)) self._clfs_weights.append(am) def predict(self, x): x = np.atleast_2d(x) # 儲存結果 rs = np.zeros(len(x)) # 根據各個弱分類器的“話語權”進行決策 for clf, am in zip(self._clfs, self._clfs_weights): rs += am * clf.predict(x) # 將預測值大於0的判為類別1,小於0的判為類別-1 return np.sign(rs)

數學基礎(瞭解)

AdaBoost 演算法是前向分步演算法的特例,AdaBoost 模型等價於損失函式為指數函式的加法模型。
在這裡插入圖片描述
所謂的前向分步演算法,就是從前向後、一步一步地學習加法模型中的每一個基函式及其權重而非將f(x)作為一個整體來訓練,這也正是 AdaBoost 的思想。