<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開始實(shí)現(xiàn)一個(gè)Adaboost分類器(完整代碼)

          共 1270字,需瀏覽 3分鐘

           ·

          2020-11-16 18:07


          導(dǎo)讀

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




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

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


          弱學(xué)習(xí)器的權(quán)重為:


          樣本權(quán)重更新迭代公式為:


          具體含義及推導(dǎo)過(guò)程詳見:三種集成學(xué)習(xí)算法原理及核心公式推導(dǎo)


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



          02 決策樹樁

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


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

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

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

          • 特征與閾值的判別符號(hào)問(wèn)題,即大于閾值還是小于閾值判斷為正類


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


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


          詳細(xì)代碼如下,配合注解應(yīng)該比較簡(jiǎn)單易懂:

          class?DecisionTreeClassifierWithWeight:
          ????def?__init__(self):
          ????????self.best_err?=?1??#?最小的加權(quán)錯(cuò)誤率
          ????????self.best_fea_id?=?0??#?最優(yōu)特征id
          ????????self.best_thres?=?0??#?選定特征的最優(yōu)閾值
          ????????self.best_op?=?1??#?閾值符號(hào),其中?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??#?判斷何種符號(hào)為最優(yōu)
          ????????????????????err?=?np.sum((y_?!=?y)*sample_weight)
          ????????????????????if?err?#?當(dāng)前參數(shù)組合可以獲得更低錯(cuò)誤率,更新最優(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庫(kù)中自帶的乳腺癌二分類數(shù)據(jù)集為例,以上述實(shí)現(xiàn)的決策樹樁進(jìn)行訓(xùn)練和評(píng)分,得到最終得分0.867,這對(duì)于一個(gè)僅有單層決策樹的分類器來(lái)說(shuō)效果還是比較好的。

          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中的算法約定,二分類模型中標(biāo)簽分別用-1和1代表負(fù)類和正類。



          03 Adaboost集成分類器

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


          實(shí)質(zhì)上,在逐漸調(diào)整樣本權(quán)重的基礎(chǔ)上,僅需逐層訓(xùn)練一個(gè)最優(yōu)的決策樹樁作為每輪的弱學(xué)習(xí)器,并保存在一個(gè)弱學(xué)習(xí)器列表中,同步記錄每個(gè)弱學(xué)習(xí)器的權(quán)重系數(shù)。最后,在實(shí)現(xiàn)predict接口時(shí),用每個(gè)弱學(xué)習(xí)器逐一完成訓(xùn)練,而后按其權(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) # 訓(xùn)練弱學(xué)習(xí)器
          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)) # 預(yù)測(cè)結(jié)果二維數(shù)組,其中每一列代表一個(gè)弱學(xué)習(xí)器的預(yù)測(cè)結(jié)果
          for i in range(self.n_estimators):
          y_pred[:, i] = self.estimators[i].predict(X)
          y_pred = y_pred * np.array(self.alphas) # 將預(yù)測(cè)結(jié)果與訓(xùn)練權(quán)重乘積作為集成預(yù)測(cè)結(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ù)集為例,對(duì)比測(cè)試自定義實(shí)現(xiàn)的AdaBoostClassifier_算法與sklearn標(biāo)準(zhǔn)庫(kù)中的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


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



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



          相關(guān)閱讀:


          瀏覽 72
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  伊人国产综合视频在线 | aaa天堂在线观看 | 日本精品一区二区三区视频 | 撸一撸干一干 | 一级内射视频 |