8.李航機械学習-AdaBoost勾配向上アルゴリズムpython実現

5389 ワード

AdaBoost勾配リフトアルゴリズム
プロジェクトリンク:https://github.com/Wchenguang/gglearn/blob/master/AdaBoost/李航機械学習説明/adaBoost.ipynb
アルゴリズムステップと原理
  • 訓練m m m個弱学習分類器、分類器は同じインタフェースG m(x):X→{x 1,x 2... G_{m}(x) :\mathcal{X}\rightarrow\{x_{1},x_{2}\dots\} Gm​(x):X→{x1​,x2​…}
  • は、各サンプルが分類器において同じ役割を果たし、$n$個のインスタンスの重みがD 1=(w 11,⋯ ,w 1 i,⋯ ,w 1 N),w 1 i=1 N,i=1,2,⋯ ,N D_{1}=\left(w_{11},\cdots, w_{1 i},\cdots, w_{1 N}\right),\quad w_{1 i}=frac{1}{N},quad i=1,2,cdots,N D 1=(w 11,⋯,w 1 i,⋯,w 1 N),w 1 i=N 1,i=1,2,⋯,Nはm m個の分類器に対して$mtimes n$個の重み
  • を有する
  • は反復サイクルに入り、各サイクルにおいて、重み付けデータセット上のm m個の分類器の分類誤り率e m=P(G m(x i)≠y i)=ΣC n(x i)≠y i e_を計算する3.1の動作を行う.{m}=P\left(G_{m}\left(x_{i}\right) eq y_{i}\right)=\sum_{C_{n}\left(x_{i}\right) eq y_{i}} w_{m i} em​=P(Gm​(xi​)̸​=yi​)=Cn​(xi​)̸=yiΣwmi 3.2各分類器の重みa l p h a m alpha_を計算する最終分類器における各個別分類器の重要度を示す{m}alphamα m = 1 2 log ⁡ 1 − e m e m\alpha_{m}=\frac{1}{2}\log\frac{1-e_{m}}{e_{m}} αm​=21​logem​1−em​​
  • 上式から分かるように、分類器の誤差率が減少するにつれて、その重み値が大きくなる
  • .
    3.3データセットの重み分布D m+1=(w m+1,1,⋯ ,w m+1,i,⋯ ,w m+1,N)w m+1,i=w m i Z m exp⁡(−α m ( y i = = G m ( x i ) ) ) , i = 1 , 2 , ⋯   , N\begin{array}{c}{D_{m+1}=\left(w_{m+1,1},\cdots, w_{m+1, i},\cdots, w_{m+1, N}\right)}\\{w_{m+1, i}=\frac{w_{m i}}{Z_{m}}\exp\left(-\alpha_{m} (y_{i}== G_{m}\left(x_{i})\right)\right),\quad i=1,2,\cdots, N}\end{array} Dm+1​=(wm+1,1​,⋯,wm+1,i​,⋯,wm+1,N​)wm+1,i​=Zm​wmi​​exp(−αm​(yi​==Gm​(xi​))),i=1,2,⋯,N​ Z m = ∑ i = 1 N w m i exp ⁡ ( − α m y i G m ( x i ) ) Z_{m}=\sum_{i=1}^{N} w_{m i}\exp\left(-\alpha_{m} y_{i} G_{m}\left(x_{i}\right)\right) Zm​=i=1∑N​wmi​exp(−αm​yi​Gm​(xi​))
  • 上式から分かるようにw m+1,i={w m i Z m e−α m , G m ( x i ) = y i w m i Z m e α m , G m ( x i ) ≠ y i w_{m+1, i}=\left\{\begin{array}{ll}{\frac{w_{m i}}{Z_{m}}\mathrm{e}^{-\alpha_{m}},} & {G_{m}\left(x_{i}\right)=y_{i}}\\{\frac{w_{m i}}{Z_{m}}\mathrm{e}^{\alpha_{m}},} & {G_{m}\left(x_{i}\right) eq y_{i}}\end{array}\right. wm+1,i​={Zm​wmi​​e−αm​,Zm​wmi​​eαm​,​Gm​(xi​)=yi​Gm​(xi​)̸=yi予測エラーのインスタンス、ウェイトアップ.正しいインスタンスを予測し、重みが下がります.

  • import numpy as np
    
    class testClf:
        def __init__(self, thresold):
            self.thresold = thresold
            self.x = None
            self.y = None
        def fit(self, x, y):
            self.x = x
            self.y = y
            return self
        def predict(self, x):
            y = x.copy()
            less_index = np.where(y[:, 0] < self.thresold)
            greater_index = np.where(y[:, 0] > self.thresold)
            y[less_index] = 1
            y[greater_index] = -1
            return y
        def fit_predict(self, x, y):
            return self.fit(x, y).predict(x)
            
    '''
    test_x = np.arange(10).reshape(-1, 1)
    test_y = np.array([1,1,1,-1,-1,-1,1,1,1,-1]).reshape(-1, 1)
    tc = testClf(2.5)
    print(tc.fit_predict(test_x, test_y))
    '''
    import numpy as np
    import matplotlib.pyplot as plt
    
    class AdaBoost:
        def __init__(self, clf_list, iteration_times):
            '''
                     fit,predict         
            '''
            self.clf_list = clf_list
            self.iteration_times = iteration_times
            self.x_weight_matrix = None
            self.clf_weight = None
        def _em(self, y_predict, y, x_weight):
            y_predict_flag = (y_predict != y).astype(int)
            return np.multiply(y_predict_flag, x_weight).sum()
        def _am(self, em):
            return np.log((1- em) / em) * 0.5
        def _update_x_weight(self, y_predict, y, am, x_weight):
            y_predict_flag = (y_predict == y).astype(int)
            y_predict_flag[np.where(y_predict_flag[:, 0] == 0)] = -1
            zm_array = np.multiply(np.exp(y_predict_flag * am * -1),
                                        x_weight)
            zm_array = zm_array / zm_array.sum()
            return zm_array
        def _fit_once(self, x, y, x_weight, clf_weight):
            for index in range(len(self.clf_list)):
                clf = self.clf_list[index]
                y_predict = clf.fit_predict(x, y)
                em = self._em(y_predict, y, x_weight)
                am = self._am(em)
                x_weight = self._update_x_weight(y_predict, y, am, x_weight)
                clf_weight[index] = am
                print('em', em, 'am', am)
                print('     ')
                print(x_weight)
        def fit(self, x, y):
            m = len(self.clf_list)
            n = x.shape[0]
            if(0 == n or 0 == m):
                return
            self.x_weight = np.full((n, 1), 1/n)
            self.clf_weight = np.full((m, 1), 1/m)
            for i in range(self.iteration_times):
                self._fit_once(x, y, self.x_weight, self.clf_weight)
        def transform(self, x):
            if(self.clf_list == None or 0 == len(self.clf_list)):
                return None
            res = self.clf_weight[0] * self.clf_list[0].predict(x)
            for index in range(1, len(self.clf_list)):
                res += (self.clf_weight[index] * 
                                self.clf_list[index].predict(x))
            return res
    test_x = np.arange(10).reshape(-1, 1)
    test_y = np.array([1,1,1,-1,-1,-1,1,1,1,-1]).reshape(-1, 1)
    adaboost = AdaBoost([testClf(2.5), testClf(8.5), testClf(5.5), ], 1)
    adaboost.fit(test_x, test_y)
    predict = adaboost.transform(test_x)
    predict[np.where(predict[:, 0] < 0)] = -1
    predict[np.where(predict[:, 0] >= 0)] = 1
    print('predict')
    print(predict)
    print('truth')
    print(test_y)
    
  • 本のP 140-P 41の結果と一致する
  • 本の分類器G 3の計算は間違い
  • であるべきである.