日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

决策树算法及实现

發(fā)布時間:2023/12/4 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 决策树算法及实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


在計(jì)算機(jī)科學(xué)中,樹是一種很重要的數(shù)據(jù)結(jié)構(gòu),比如我們最為熟悉的二叉查找樹(Binary Search Tree),紅黑樹(Red-Black Tree)等,通過引入樹這種數(shù)據(jù)結(jié)構(gòu),我們可以很快地縮小問題規(guī)模,實(shí)現(xiàn)高效的查找。


在監(jiān)督學(xué)習(xí)中,面對樣本中復(fù)雜多樣的特征,選取什么樣的策略可以實(shí)現(xiàn)較高的學(xué)習(xí)效率和較好的分類效果一直是科學(xué)家們探索的目標(biāo)。那么,樹這種結(jié)構(gòu)到底可以如何用于機(jī)器學(xué)習(xí)中呢?我們先從一個游戲開始。


我們應(yīng)該都玩過或者聽過這么一種游戲:游戲中,出題者寫下一個明星的名字,其他人需要猜出這個人是誰。當(dāng)然,如果游戲規(guī)則僅此而已的話,幾乎是無法猜出來的,因?yàn)閱栴}的規(guī)模太大了。為了降低游戲的難度,答題者可以向出題者問問題,而出題者必須準(zhǔn)確回答是或者否,答題者依據(jù)回答提出下一個問題,如果能夠在指定次數(shù)內(nèi)確定謎底,即為勝出。加入了問答規(guī)則之后,我們是否有可能猜出謎底呢?我們先實(shí)驗(yàn)一下,現(xiàn)在我已經(jīng)寫下了一個影視明星的名字,而你和我的問答記錄如下:


  • 是男的嗎?Y

  • 是亞洲人嗎?Y

  • 是中國人嗎?N

  • 是印度人嗎?Y

  • ?……


雖然只有短短四個問題,但是我們已經(jīng)把答案的范圍大大縮小了,那么接下,第5個問題你應(yīng)該如何問呢?我相信你應(yīng)該基本可以鎖定答案了,因?yàn)槲铱催^的印度電影就那么幾部。我們將上面的信息結(jié)構(gòu)化如下圖所示:



在上面的游戲中,我們針對性的提出問題,每一個問題都可以將我們的答案范圍縮小,在提問中和回答者有相同知識背景的前提下,得出答案的難度比我們想象的要小很多。


回到我們最初的問題中,如何將樹結(jié)構(gòu)用于機(jī)器學(xué)習(xí)中?結(jié)合上面的圖,我們可以看出,在每一個節(jié)點(diǎn),依據(jù)問題答案,可以將答案劃分為左右兩個分支,左分支代表的是Yes,右分支代表的是No,雖然為了簡化,我們只畫出了其中的一條路徑,但是也可以明顯看出這是一個樹形結(jié)構(gòu),這便是決策樹的原型。


1.決策樹算法簡介


我們面對的樣本通常具有很多個特征,正所謂對事物的判斷不能只從一個角度,那如何結(jié)合不同的特征呢?決策樹算法的思想是,先從一個特征入手,就如同我們上面的游戲中一樣,既然無法直接分類,那就先根據(jù)一個特征進(jìn)行分類,雖然分類結(jié)果達(dá)不到理想效果,但是通過這次分類,我們的問題規(guī)模變小了,同時分類后的子集相比原來的樣本集更加易于分類了。然后針對上一次分類后的樣本子集,重復(fù)這個過程。在理想的情況下,經(jīng)過多層的決策分類,我們將得到完全純凈的子集,也就是每一個子集中的樣本都屬于同一個分類。



比如上圖中,平面坐標(biāo)中的六個點(diǎn),我們無法通過其x坐標(biāo)或者y坐標(biāo)直接就將兩類點(diǎn)分開。采用決策樹算法思想:我們先依據(jù)y坐標(biāo)將六個點(diǎn)劃分為兩個子類(如水平線所示),水平線上面的兩個點(diǎn)是同一個分類,但是水平線之下的四個點(diǎn)是不純凈的。但是沒關(guān)系,我們對這四個點(diǎn)進(jìn)行再次分類,這次我們以x左邊分類(見圖中的豎線),通過兩層分類,我們實(shí)現(xiàn)了對樣本點(diǎn)的完全分類。這樣,我們的決策樹的偽代碼實(shí)現(xiàn)如下:


if?y?>?a:

????output dot

else:

????if?x?<?b:

??????????output cross

????else:

??????????output?dot


由這個分類的過程形成一個樹形的判決模型,樹的每一個非葉子節(jié)點(diǎn)都是一個特征分割點(diǎn),葉子節(jié)點(diǎn)是最終的決策分類。如下圖所示:



將新樣本輸入決策樹進(jìn)行判決時,就是將樣本在決策樹上自頂向下,依據(jù)決策樹的節(jié)點(diǎn)規(guī)則進(jìn)行遍歷,最終落入的葉子節(jié)點(diǎn)就是該樣本所屬的分類。


2.決策樹算法流程


上面我們介紹決策樹算法的思想,可以簡單歸納為如下兩點(diǎn):


  • 每次選擇其中一個特征對樣本集進(jìn)行分類

  • 對分類后的子集遞歸進(jìn)行步驟1


看起來是不是也太簡單了呢?實(shí)際上每一個步驟我們還有很多考慮的。在第一個步驟中,我們需要考慮的一個最重要的策略是,選取什么樣的特征可以實(shí)現(xiàn)最好的分類效果,而所謂的分類效果好壞,必然也需要一個評價的指標(biāo)。在上文中,我們都用純凈來說明分類效果好,那何為純凈呢?直觀來說就是集合中樣本所屬類別比較集中,最理想的是樣本都屬于同一個分類。樣本集的純度可以用熵來進(jìn)行衡量。


在信息論中,熵代表了一個系統(tǒng)的混亂程度,熵越大,說明我們的數(shù)據(jù)集純度越低,當(dāng)我們的數(shù)據(jù)集都是同一個類別的時候,熵為0,熵的計(jì)算公式如下:



其中,P(xi)表示概率,b在此處取2。比如拋硬幣的時候,正面的概率就是1/2,反面的概率也是1/2,那么這個過程的熵為:



可見,由于拋硬幣是一個完全隨機(jī)事件,其結(jié)果正面和反面是等概率的,所以具有很高的熵。假如我們觀察的是硬幣最終飛行的方向,那么硬幣最后往下落的概率是1,往天上飛的概率是0,帶入上面的公式中,可以得到這個過程的熵為0,所以,熵越小,結(jié)果的可預(yù)測性就越強(qiáng)。在決策樹的生成過程中,我們的目標(biāo)就是要劃分后的子集中其熵最小,這樣后續(xù)的的迭代中,就更容易對其進(jìn)行分類。


既然是遞歸過程,那么就需要制定遞歸的停止規(guī)則。在兩種情況下我們停止進(jìn)一步對子集進(jìn)行劃分,其一是劃分已經(jīng)達(dá)到可以理想效果了,另外一種就是進(jìn)一步劃分收效甚微,不值得再繼續(xù)了。用專業(yè)術(shù)語總結(jié)終止條件有以下幾個:


  • 子集的熵達(dá)到閾值

  • 子集規(guī)模夠小

  • 進(jìn)一步劃分的增益小于閾值


  • 其中,條件3中的增益代表的是一次劃分對數(shù)據(jù)純度的提升效果,也就是劃分以后,熵減少越多,說明增益越大,那么這次劃分也就越有價值,增益的計(jì)算公式如下:



    Gain


    上述公式可以理解為:計(jì)算這次劃分之后兩個子集的熵之和相對劃分之前的熵減少了多少,需要注意的是,計(jì)算子集的熵之和需要乘上各個子集的權(quán)重,權(quán)重的計(jì)算方法是子集的規(guī)模占分割前父集的比重,比如劃分前熵為e,劃分為子集A和B,大小分別為m和n,熵分別為e1和e2,那么增益就是e - m/(m + n) * e1 - n/(m + n) * e2


    3. 決策樹算法實(shí)現(xiàn)


    有了上述概念,我們就可以開始開始決策樹的訓(xùn)練了,訓(xùn)練過程分為:


  • 選取特征,分割樣本集

  • 計(jì)算增益,如果增益夠大,將分割后的樣本集作為決策樹的子節(jié)點(diǎn),否則停止分割

  • 遞歸執(zhí)行上兩步


  • 上述步驟是依照ID3的算法思想(依據(jù)信息增益進(jìn)行特征選取和分裂),除此之外還有C4.5以及CART等決策樹算法。


    算法框架如下:


    class?DecisionTree(object):

    ????def fit(self,?X,?y):

    ????????# 依據(jù)輸入樣本生成決策樹

    ????????self.root?=?self._build_tree(X,?y)

    ?

    ????def _build_tree(self,?X,?y,?current_depth=0):

    ????????#1. 選取最佳分割特征,生成左右節(jié)點(diǎn)

    ????????#2. 針對左右節(jié)點(diǎn)遞歸生成子樹

    ??????

    ????def predict_value(self,?x,?tree=None):

    ????????# 將輸入樣本傳入決策樹中,自頂向下進(jìn)行判定

    ????????# 到達(dá)葉子節(jié)點(diǎn)即為預(yù)測值


    在上述代碼中,實(shí)現(xiàn)決策樹的關(guān)鍵是遞歸構(gòu)造子樹的過程,為了實(shí)現(xiàn)這個過程,我們需要做好三件事:分別是節(jié)點(diǎn)的定義,最佳分割特征的選擇,遞歸生成子樹。


    3.1 節(jié)點(diǎn)定義


    決策樹的目的是用于分類預(yù)測,即各個節(jié)點(diǎn)需要選取輸入樣本的特征,進(jìn)行規(guī)則判定,最終決定樣本歸屬到哪一棵子樹,基于這個目的,決策樹的每一個節(jié)點(diǎn)需要包含以下幾個關(guān)鍵信息:


  • 判決特征:當(dāng)前節(jié)點(diǎn)針對哪一個特征進(jìn)行判決

  • 判決規(guī)則:對于二類問題,這個規(guī)則一般是一個布爾表達(dá)式

  • 左子樹:判決為TRUE的樣本

  • 右子樹:判決為FALSE的樣本


  • 決策樹節(jié)點(diǎn)的定義代碼如下所示:


    class?DecisionNode():

    ????

    ????def __init__(self,?feature_i=None,?threshold=None,

    ?????????????????value=None,?true_branch=None,?false_branch=None):

    ????????self.feature_i?=?feature_i??# 用于測試的特征對應(yīng)的索引

    ????????self.threshold?=?threshold??# 判斷規(guī)則:>=threshold為true

    ????????self.value?=?value??# 如果是葉子節(jié)點(diǎn),用于保存預(yù)測結(jié)果

    ????????self.true_branch?=?true_branch??# 左子樹

    ????????self.false_branch?=?false_branch??# 右子樹


    3.2 特征選取


    特征選取是構(gòu)造決策樹最關(guān)鍵的步驟,其目的是選出能夠?qū)崿F(xiàn)分割結(jié)果最純凈的那個特征,其操作流程的代碼如下:


    # 遍歷樣本集中的所有特征,針對每一個特征計(jì)算最佳分割點(diǎn)

    # 再選取最佳的分割特征

    for?feature_i?in?range(n_features):

    ????# 遍歷集合中某個特征的所有取值

    ????for?threshold?in?unique_values:

    ????????# 以當(dāng)前特征值作為閾值進(jìn)行分割

    ????????Xy1,?Xy2?=?divide_on_feature(X_y,?feature_i,?threshold)

    ????????# 計(jì)算分割后的增益

    ????????gain?=?gain(y,?y1,?y2)

    ????????# 記錄最佳分割特征,最佳分割閾值

    ????????if?gain?>?largest_gain:

    ????????largest_gain?=?gain

    ????????????best_criteria?=?{

    ????????????????"feature_i":?feature_i,

    ????????????????"threshold":?threshold

    ????????????????}


    3.3 節(jié)點(diǎn)分裂


    節(jié)點(diǎn)分裂的時候有兩條處理分支,如果增益夠大,就分裂為左右子樹,如果增益很小,就停止分裂,將這個節(jié)點(diǎn)直接作為葉子節(jié)點(diǎn)。節(jié)點(diǎn)分裂和Gain(分割后增益)的計(jì)算可以做一個優(yōu)化,在上一個步驟中,我們尋找最優(yōu)分割點(diǎn)的時候其實(shí)就可以將最佳分裂子集和Gain計(jì)算并保存下來,將上一步中的for循環(huán)改寫為:


    # 以當(dāng)前特征值作為閾值進(jìn)行分割

    Xy1,?Xy2?=?divide_on_feature(X_y,?feature_i,?threshold)

    # 計(jì)算分割后的熵

    gain?=?gain(y,?y1,?y2)

    # 記錄最佳分割特征,最佳分割閾值

    if?gain?>?largest_gain:

    ????largest_gain?=?gain

    ????????best_criteria?=?{

    ????????"feature_i":?feature_i,

    ????????"threshold":?threshold?,

    ????????}

    ????best_sets?=?{

    ????????"left":?Xy1,

    ????????"right":?Xy2,

    ????????"gain":?gain

    ????????}


    為了防止過擬合,需要設(shè)置合適的停止條件,比如設(shè)置Gain的閾值,如果Gain比較小,就沒有必要繼續(xù)進(jìn)行分割,所以接下來,我們就可以依據(jù)gain來決定分割策略:


    if?best_sets["gain"]?>?MIN_GAIN:

    ????# 對best_sets["left"]進(jìn)一步構(gòu)造子樹,并作為父節(jié)點(diǎn)的左子樹

    ????# 對best_sets["right"]進(jìn)一步構(gòu)造子樹,并作為父節(jié)點(diǎn)的右子樹

    ????...

    else:

    ????# 直接將父節(jié)點(diǎn)作為葉子節(jié)點(diǎn)

    ????...


    下面,我們結(jié)合一組實(shí)驗(yàn)數(shù)據(jù)來學(xué)習(xí)決策樹的訓(xùn)練方法。實(shí)驗(yàn)數(shù)據(jù)來源于這里,下表中的數(shù)據(jù)是一組消費(fèi)調(diào)查結(jié)果,我們訓(xùn)練決策樹的目的,就是構(gòu)造一個分類算法,使得有新的用戶數(shù)據(jù)時,我們依據(jù)訓(xùn)練結(jié)果去推斷一個用戶是否購買這個商品:


    AGEEDUCATIONINCOMEMARITAL STATUSPURCHASE?
    36-55master’shighsingleyes
    18-35high schoollowsingleno
    36-55master’slowsingleyes
    18-35bachelor’shighsingleno
    ?< 18high schoollowsingleyes
    18-35bachelor’shighmarriedno
    36-55bachelor’slowmarriedno
    > 55bachelor’shighsingleyes
    36-55master’slowmarriedno
    > 55master’slowmarriedyes
    36-55master’shighsingleyes
    > 55master’shighsingleyes
    18high schoolhighsingleno
    36-55master’slowsingleyes
    36-55high schoollowsingleyes
    ?< 18high schoollowmarriedyes
    18-35bachelor’shighmarriedno
    > 55high schoolhighmarriedyes
    > 55bachelor’slowsingleyes
    36-55high schoolhighmarriedno


    從表中可以看出,我們一共有20組調(diào)查樣本,每一組樣本包含四個特征,分別是年齡段,學(xué)歷,收入,婚姻狀況,而最后一列是所屬分類,在這個問題中就代表是否購買了該產(chǎn)品。


    監(jiān)督學(xué)習(xí)就是在每一個樣本都有正確答案的前提下,用算法預(yù)測結(jié)果,然后根據(jù)預(yù)測情況的好壞,調(diào)整算法參數(shù)。在決策樹中,預(yù)測的過程就是依據(jù)各個特征劃分樣本集,評價預(yù)測結(jié)果的好壞標(biāo)準(zhǔn)是劃分結(jié)果的純度。


    為了方便處理,我們對樣本數(shù)據(jù)進(jìn)行了簡化,將年齡特征按照樣本的特點(diǎn),轉(zhuǎn)化為離散的數(shù)據(jù),比如小于18對應(yīng)0,18對應(yīng)1,18-35對應(yīng)2,36-55對應(yīng)3,大于55對應(yīng)4,以此類推,同樣其他的特征也一樣最數(shù)字化處理,教育水平分別映射為0(hight school),1(bachelor’s),2(master’s),收入映射為0(low)和1(hight), 婚姻狀況同樣映射為0(single), 1(married),最終處理后的樣本,放到一個numpy矩陣中,如下所示:


    X_y?=?np.array(

    ????????[[3,?2,?1,?0,?1],

    ?????????[2,?0,?0,?0,?0],

    ?????????[3,?2,?0,?0,?1],

    ?????????[2,?1,?1,?0,?0],

    ?????????[0,?0,?0,?0,?1],

    ?????????[2,?1,?1,?1,?0],

    ?????????[3,?1,?0,?1,?0],

    ?????????[4,?1,?1,?0,?1],

    ?????????[3,?2,?0,?1,?0],

    ?????????[4,?2,?0,?1,?1],

    ?????????[3,?2,?1,?0,?1],

    ?????????[4,?2,?1,?0,?1],

    ?????????[1,?0,?1,?0,?0],

    ?????????[3,?2,?0,?0,?1],

    ?????????[3,?0,?0,?0,?1],

    ?????????[0,?0,?0,?1,?1],

    ?????????[2,?1,?1,?1,?0],

    ?????????[4,?0,?1,?1,?1],

    ?????????[4,?1,?0,?0,?1],

    ?????????[3,?0,?1,?1,?0]]

    ????)


    4. 新樣本預(yù)測


    依照上面的算法構(gòu)造決策樹,我們將決策樹打印出來,如下所示:


    --?Classification?Tree?--

    0?:?4?

    ???T?->?1

    ???F?->?3?:?1?

    ??????T?->?0?:?2?

    ????????????T?->?0

    ????????????F?->?1

    ??????F?->?0?:?3?

    ????????????T?->?1

    ????????????F?->?0?:?1?

    ????????????????????????T?->?0

    ????????????????????????F?->?1


    其中,冒號前代表選擇的分割特征,冒號后面代表判別規(guī)則,二者組合起來就是一個決策樹的非葉子節(jié)點(diǎn),每個非葉子節(jié)點(diǎn)進(jìn)一步分割為分為True和False分支,對于葉子節(jié)點(diǎn)箭頭后面表示最終分類,0表示不購買,1表示購買。由于我們的數(shù)據(jù)做過簡化,所以上述結(jié)果不太直觀,我們將對應(yīng)的特征以及判斷規(guī)則翻譯一下:


    年齡?:?大于55?

    ????->?購買

    ????->?收入?:??

    ???????->?年齡?:?大于18?

    ?????????????->?不購買

    ?????????????->?購買

    ???????->?年齡?:?大于36?

    ?????????????->?購買

    ?????????????->?年齡?:?大于等于18?

    ?????????????????????????->?不購買

    ?????????????????????????->?購買


    決策樹構(gòu)造完之后,我們就可以用來進(jìn)行新樣本的分類了。決策樹的預(yù)測過程十分容易理解,只需要將從根節(jié)點(diǎn)開始,按照節(jié)點(diǎn)定義的規(guī)則進(jìn)行判決,選擇對應(yīng)的子樹,并重復(fù)這個過程,直到葉子節(jié)點(diǎn)即可。決策樹的預(yù)測功能實(shí)現(xiàn)代碼如下:


    def predict_value(self,?x,?tree=None):

    ????????# 如果當(dāng)前節(jié)點(diǎn)是葉子節(jié)點(diǎn),直接輸出其值

    ????????if?tree.value?is?not?None:

    ????????????return?tree.value

    ????????# 否則將x按照當(dāng)前節(jié)點(diǎn)的規(guī)則進(jìn)行判決

    ????????# 如果判決為true選擇左子樹,否則選擇右子樹,

    ????????feature_value?=?x[tree.feature_i]

    ????????if?feature_value?>=?tree.threshold:

    ????????????branch?=?tree.true_branch

    ????????else:

    ????????????branch?=?tree.false_branch

    ????????# 在選中的子樹上遞歸進(jìn)行判斷

    ????????return?self.predict_value(x,?branch)


    5. 總結(jié)


    決策樹是一種簡單常用的分類器,通過訓(xùn)練好的決策樹可以實(shí)現(xiàn)對未知的數(shù)據(jù)進(jìn)行高效分類。從我們的例子中也可以看出,決策樹模型具有較好的可讀性和描述性,有助于輔助人工分析;此外,決策樹的分類效率高,一次構(gòu)建后可以反復(fù)使用,而且每一次預(yù)測的計(jì)算次數(shù)不超過決策樹的深度。


    當(dāng)然,決策樹也有其缺點(diǎn)。對于連續(xù)的特征,比較難以處理,對于多分類問題,計(jì)算量和準(zhǔn)確率都不理想。此外,在實(shí)際應(yīng)用中,由于其最底層葉子節(jié)點(diǎn)是通過父節(jié)點(diǎn)中的單一規(guī)則生成的,所以通過手動修改樣本特征比較容易欺騙分類器,比如在攔擊郵件識別系統(tǒng)中,用戶可能通過修改某一個關(guān)鍵特征,就可以騙過垃圾郵件識別系統(tǒng)。從實(shí)現(xiàn)上來講,由于樹的生成采用的是遞歸,隨著樣本規(guī)模的增大,計(jì)算量以及內(nèi)存消耗會變得越來越大。


    此外,過擬合也是決策樹面臨的一個問題,完全訓(xùn)練的決策樹(未進(jìn)行剪紙,未限制Gain的閾值)能夠100%準(zhǔn)確地預(yù)測訓(xùn)練樣本,因?yàn)槠涫菍τ?xùn)練樣本的完全擬合,但是,對與訓(xùn)練樣本以外的樣本,其預(yù)測效果可能會不理想,這就是過擬合。解決決策樹的過擬合,除了上文說到的通過設(shè)置Gain的閾值作為停止條件之外,通常還需要對決策樹進(jìn)行剪枝,常用的剪枝策略有:


  • Pessimistic Error Pruning:悲觀錯誤剪枝

  • Minimum Error Pruning:最小誤差剪枝

  • Cost-Complexity Pruning:代價復(fù)雜剪枝

  • ?Error-Based Pruning:基于錯誤的剪枝,即對每一個節(jié)點(diǎn),都用一組測試數(shù)據(jù)集進(jìn)行測試,如果分裂之后,能夠降低錯誤率,再繼續(xù)分裂為兩棵子樹,否則直接作為葉子節(jié)點(diǎn)。

  • Critical Value Pruning:關(guān)鍵值剪枝,這就是上文中提到的設(shè)置Gain的閾值作為停止條件。


  • 我們以最簡單的方式展示了ID3決策樹的實(shí)現(xiàn)方式,如果想要了解不同類型的決策樹的差別,可以參考(https://www.quora.com/What-are-the-differences-between-ID3-C4-5-and-CART)。


    另外,關(guān)于各種機(jī)器學(xué)習(xí)算法的實(shí)現(xiàn),強(qiáng)烈推薦參考Github倉庫ML-From-Scratch,下載代碼之后,通過pip install -r requirements.txt安裝依賴庫即可運(yùn)行代碼。


    來源:?ZPPenny

    www.jianshu.com/p/c4d0837e9439


    總結(jié)

    以上是生活随笔為你收集整理的决策树算法及实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。