1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 1270字,需瀏覽 3分鐘

         ·

        2020-11-16 18:07


        導(dǎo)讀

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




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

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


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


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


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


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



        02 決策樹樁

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


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

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

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

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


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


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


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

        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?#?當(dāng)前參數(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)的決策樹樁進(jìn)行訓(xù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中的算法約定,二分類模型中標(biāo)簽分別用-1和1代表負(fù)類和正類。



        03 Adaboost集成分類器

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


        實質(zhì)上,在逐漸調(diào)整樣本權(quán)重的基礎(chǔ)上,僅需逐層訓(xùn)練一個最優(yōu)的決策樹樁作為每輪的弱學(xué)習(xí)器,并保存在一個弱學(xué)習(xí)器列表中,同步記錄每個弱學(xué)習(xí)器的權(quán)重系數(shù)。最后,在實現(xiàn)predict接口時,用每個弱學(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ù)測結(jié)果二維數(shù)組,其中每一列代表一個弱學(xué)習(xí)器的預(yù)測結(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ù)測結(jié)果與訓(xùn)練權(quán)重乘積作為集成預(yù)測結(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標(biāo)準(zhǔn)庫中的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)練效率略低,自定義實現(xiàn)Adaboost算法效果簡直好的不得了。



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



        相關(guān)閱讀:


        瀏覽 72
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            在线激情小视频 | AV片网址 | 浪货跪趴开荤肉欲H文视频 | 少妇熟女性爱视频 | 我用双乳夹住他的巨大 | 久久久久久久久久电影 | 农村寡妇偷人高潮完整版 | 粉嫩被两根大粗黑进出视频 | 老外做爰全过高潮视频 | 日韩婬乱a一级毛片无码 |