<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從0開始實現(xiàn)一個Adaboost分類器(完整代碼)

          共 1165字,需瀏覽 3分鐘

           ·

          2020-11-16 11:22


          導讀

          日前,通俗易懂的推導了三種集成學習的原理及主要公式,今天本文基于Python從0開始手動實現(xiàn)一個Adaboost分類器,文中提供完整代碼。


          2352c3fa973f7ebd05ac3f395545dec2.webp



          01 Adaboost基本原理回顧Adaboost作為一種提升集成算法,核心思想是不斷訓練弱學習器,來針對性的提升前一輪中預測錯誤樣本的權(quán)重,最終通過加權(quán)所有弱學習器的訓練結(jié)果得到最終分類標簽。Adaboost是一種加權(quán)提升的集成算法,關(guān)鍵在于兩個權(quán)重系數(shù):
          • 弱學習器權(quán)重,影響每個弱學習器的結(jié)果對最終集成學習結(jié)果的影響程度,與該學習器的錯誤率有關(guān)

          • 樣本權(quán)重,這也是Adaboost算法的精髓所在,即每輪訓練弱學習器時不斷優(yōu)化調(diào)整樣本間的權(quán)重,保證前一輪中學習錯誤的樣本在下一輪訓練中受到重點照顧


          弱學習器的權(quán)重為:

          為學習器錯誤率
          樣本權(quán)重更新迭代公式為:


          具體含義及推導過程詳見:三種集成學習算法原理及核心公式推導


          值得指出,在sklearn庫內(nèi)置的Adaboost算法中,當解決分類問題時弱學習器選擇最大深度為1的決策樹(俗稱決策樹樁),解決回歸問題時則選擇最大深度為3的決策樹(CART)。



          02 決策樹樁

          本文以分類問題為例實現(xiàn)Adaboost算法,所以首先探索實現(xiàn)一個最大深度只有一層的決策樹樁。


          簡單起見,假設(shè)樣本為連續(xù)數(shù)值型特征,要實現(xiàn)一個最大深度只有一層決策樹樁,那么實際上無論有多少個特征,也僅會用到其中一個特征作為分類。則問題等價于確定以下三個參數(shù):

          • 確定選擇哪一列特征作為分類依據(jù)

          • 選擇的特征列中,以什么數(shù)值作為二分類的閾值

          • 特征與閾值的判別符號問題,即大于閾值還是小于閾值判斷為正類


          由于是分類問題,那么選擇最優(yōu)參數(shù)的依據(jù)不妨可以選擇為Accuracy。當然,由于該決策樹樁需要支持樣本權(quán)重參數(shù),所以這里的Accuracy嚴謹?shù)恼f是指所有分類正確的樣本權(quán)重之和占所有樣本權(quán)重之和的比例,當執(zhí)行樣本權(quán)重歸一化時所有樣本權(quán)重之和為1。


          基于此,一個簡單的決策樹樁實現(xiàn)思路就比較清晰了,實現(xiàn)3重循環(huán)依次遍歷尋找最有參數(shù)組合即可。另外,沿襲sklearn標準庫中的做法,這里僅實現(xiàn)fit()、predict()和score()三個核心接口。


          詳細代碼如下,配合注解應該比較簡單易懂:

          class?DecisionTreeClassifierWithWeight:
          ????def?__init__(self):
          ????????self.best_err?=?1??#?最小的加權(quán)錯誤率
          ????????self.best_fea_id?=?0??#?最優(yōu)特征id
          ????????self.best_thres?=?0??#?選定特征的最優(yōu)閾值
          ????????self.best_op?=?1??#?閾值符號,其中?1:?>,?0:?<

          ????def?fit(self,?X,?y,?sample_weight=None):
          ????????if?sample_weight?is?None:
          ????????????sample_weight?=?np.ones(len(X))?/?len(X)
          ????????n?=?X.shape[1]
          ????????for?i?in?range(n):
          ????????????feature?=?X[:,?i]??#?選定特征列
          ????????????fea_unique?=?np.sort(np.unique(feature))??#?將所有特征值從小到大排序
          ????????????for?j?in?range(len(fea_unique)-1):
          ????????????????thres?=?(fea_unique[j]?+?fea_unique[j+1])?/?2??#?逐一設(shè)定可能閾值
          ????????????????for?op?in?(0,?1):
          ????????????????????y_?=?2*(feature?>=?thres)-1?if?op==1?else?2*(feature?-1??#?判斷何種符號為最優(yōu)
          ????????????????????err?=?np.sum((y_?!=?y)*sample_weight)
          ????????????????????if?err?#?當前參數(shù)組合可以獲得更低錯誤率,更新最優(yōu)參數(shù)
          ????????????????????????self.best_err?=?err
          ????????????????????????self.best_op?=?op
          ????????????????????????self.best_fea_id?=?i
          ????????????????????????self.best_thres?=?thres
          ????????return?self
          ????
          ????def?predict(self,?X):
          ????????feature?=?X[:,?self.best_fea_id]
          ????????return?2*(feature?>=?self.best_thres)-1?if?self.best_op==1?else?2*(feature?-1
          ????
          ????def?score(self,?X,?y,?sample_weight=None):
          ????????y_pre?=?self.predict(X)
          ????????if?sample_weight?is?not?None:
          ????????????return?np.sum((y_pre?==?y)*sample_weight)
          ????????return?np.mean(y_pre?==?y)


          這里以sklearn庫中自帶的乳腺癌二分類數(shù)據(jù)集為例,以上述實現(xiàn)的決策樹樁進行訓練和評分,得到最終得分0.867,這對于一個僅有單層決策樹的分類器來說效果還是比較好的。

          from sklearn.datasets import load_breast_cancer
          from sklearn.model_selection import train_test_split

          X, y = load_breast_cancer(return_X_y=True)
          y = 2*y-1 # 將0/1取值映射為-1/1取值
          X_train, X_test, y_train, y_test = train_test_split(X, y)

          DecisionTreeClassifierWithWeight().fit(X_train, y_train).score(X_test, y_test)
          # 0.8671328671328671


          注:按照Adaboost中的算法約定,二分類模型中標簽分別用-1和1代表負類和正類。



          03 Adaboost集成分類器

          在實現(xiàn)決策樹樁作為弱分類器的基礎(chǔ)上,實現(xiàn)Adaboost算法就僅需按照算法流程逐層訓練即可。簡單起見,這里僅設(shè)置超參數(shù)n_estimators用于選擇弱分類器的個數(shù)。為區(qū)分于sklearn中的Adaboost標準內(nèi)置庫,本文將自定義實現(xiàn)的Adaboost分類算法命名為AdaBoostClassifier_,并設(shè)置相同的默認弱學習器數(shù)量超參數(shù)n_estimators=50,其余不做限制。


          實質(zhì)上,在逐漸調(diào)整樣本權(quán)重的基礎(chǔ)上,僅需逐層訓練一個最優(yōu)的決策樹樁作為每輪的弱學習器,并保存在一個弱學習器列表中,同步記錄每個弱學習器的權(quán)重系數(shù)。最后,在實現(xiàn)predict接口時,用每個弱學習器逐一完成訓練,而后按其權(quán)重系數(shù)加權(quán)即可得到最終結(jié)果。完整代碼如下:

          class AdaBoostClassifier_:
          def __init__(self, n_estimators=50):
          self.n_estimators = n_estimators
          self.estimators = []
          self.alphas = []

          def fit(self, X, y):
          sample_weight = np.ones(len(X)) / len(X) # 初始化樣本權(quán)重為 1/N
          for _ in range(self.n_estimators):
          dtc = DecisionTreeClassifierWithWeight().fit(X, y, sample_weight) # 訓練弱學習器
          alpha = 1/2 * np.log((1-dtc.best_err)/dtc.best_err) # 權(quán)重系數(shù)
          y_pred = dtc.predict(X)
          sample_weight *= np.exp(-alpha*y_pred*y) # 更新迭代樣本權(quán)重
          sample_weight /= np.sum(sample_weight) # 樣本權(quán)重歸一化
          self.estimators.append(dtc)
          self.alphas.append(alpha)
          return self

          def predict(self, X):
          y_pred = np.empty((len(X), self.n_estimators)) # 預測結(jié)果二維數(shù)組,其中每一列代表一個弱學習器的預測結(jié)果
          for i in range(self.n_estimators):
          y_pred[:, i] = self.estimators[i].predict(X)
          y_pred = y_pred * np.array(self.alphas) # 將預測結(jié)果與訓練權(quán)重乘積作為集成預測結(jié)果
          return 2*(np.sum(y_pred, axis=1)>0)-1 # 以0為閾值,判斷并映射為-1和1

          def score(self, X, y):
          y_pred = self.predict(X)
          return np.mean(y_pred==y)


          最后,繼續(xù)以乳腺癌二分類數(shù)據(jù)集為例,對比測試自定義實現(xiàn)的AdaBoostClassifier_算法與sklearn標準庫中的AdaBoostClassifer算法性能,得到如下結(jié)果:

          from sklearn.ensemble import AdaBoostClassifier
          AdaBoostClassifier_().fit(X_train, y_train).score(X_test, y_test)
          # 0.986013986013986
          AdaBoostClassifier().fit(X_train, y_train).score(X_test, y_test)
          # 0.965034965034965


          除了訓練效率略低,自定義實現(xiàn)Adaboost算法效果簡直好的不得了。



          本文按部就班的實現(xiàn)了一個Adaboost分類算法的baseline,實現(xiàn)了較好的分類效果,但仍有很多需要優(yōu)化的點,例如對回歸算法的支持、更多集成學習參數(shù)的設(shè)置以及特殊訓練情況下的處理等。To be continued……


          60ef626aad2b89a984330eb170a2e979.webp


          相關(guān)閱讀:


          瀏覽 23
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  2021国产免费自拍视频 | 午夜爽爽视频 | 最近日韩中文字幕 | 青草娱乐视频在线观看 | 天堂在线V |