Python機器學習筆記:CART算法實戰 python機器學習筆記:深入學習決策樹算法原理 python機器學習筆記:ID3決策樹算法實戰

完整代碼及其數據,請移步小編的GitHub

  傳送門:請點擊我

  如果點擊有誤:https://github.com/LeBron-Jian/MachineLearningNote

前言

  在python機器學習筆記:深入學習決策樹算法原理 一文中我們提到了決策樹裏的ID3算法,C4.5算法,並且大概的瞭解了CART算法。對於ID3算法的實戰可參考這篇文章(python機器學習筆記:ID3決策樹算法實戰)。雖然我們已經對於C4.5算法也有了粗略的瞭解,並且提到了其不足,比如模型是用較爲複雜的熵度量,使用了相對較爲複雜的多叉樹,只能處理分類不能處理迴歸問題等等。但是對於這些問題CART算法又做了相應的改進。不同於C4.5 ,CART本質是對特徵空間進行二元劃分(即CART生成的決策樹是一顆二叉樹),並能夠對標量屬性(nominal attribute)與連續屬性(continuous attribute)進行分裂。所以本文就學習一下CART算法。

   CART也是決策樹的一種,不過是滿二叉樹,CART可以是強分類器,就跟決策樹一樣,但是我們可以指定CART的深度,使之成爲比較弱的分類器,CART生成過程和決策樹類似,也是採用遞歸劃分的,不過也存在很多的不同之處。

  本文學習CART(Classification And Regression Trees,分類迴歸樹)樹構建算法。該算法是由Leo Breiman,Jerome Friedman,Richard Olshen與Charles Stone於1984年提出,即可以用於分類也可以用於迴歸,其數據的建模方法爲二元切分法,因此非常值得學習。下面我們利用Python來構建並顯示CART樹,代碼會保持足夠的靈活性以便能用於多個問題當中。接着,利用CART算法構建迴歸樹並介紹其中的樹剪枝技術(該技術的主要目的是防止樹的過擬合)。之後引入了一個更高級的模型樹算法。與迴歸樹的做法(在每個葉節點上使用各自的均值做預測)不同,該算法需要在每個葉子節點上都構建出一個線性模型。在這些樹的構建算法中有一些需要調整的參數。

1,複雜數據的局部性建模問題

  前面ID3決策樹算法實戰 博文裏面我們學習了使用決策樹來進行分類。決策樹不斷將數據切分成小數據集,直到所有目標變量完全相同,或者數據不能再切分爲止。但是決策樹也是一種貪心算法啊,它要在給定時間內做出最佳選擇,但並不關心能否達到全局最優。所以ID3 決策樹算法存在以下問題:

  首先,ID3的做法是每次選取當前最佳的特徵來分割數據,並按照該特徵的所有可能取值來切分。也就是說,如果一個特徵有4種取值,那麼數據被切成4份。一旦按某特徵切分後,該特徵在之後的算法執行過程中將不會再起作用,所以有觀點認爲這種切分方式過於迅速。另外一種方法是二元切分法,即每次把數據集切成兩份。如果數據的某特徵值等於切分所要求的值,那麼這些數據就進入了樹的左子樹,反之則進入樹的右子樹。

  除了切分過於迅速外,ID3算法還存在另一個問題,它不能直接處理連續型特徵。只有事先將連續型特徵轉換成離散型,才能在ID3算法中使用。但這種轉換過程會破壞連續型變量的內在性質。而使用二元切分法則易於樹構建過程進行調整以處理連續型特徵。具體的處理方法是:如果特徵值大於給定值就走左子樹,否則走右子樹。另外,二元切分法也節省了樹的構建時間,但這點意義也不是特別大,因爲這些樹構建一般是離線完成,時間並非需要重點關注的因素。

  CART是十分著名且廣泛記載的樹構建算法,它使用二元切分來處理連續型變量。對CART稍作修改就可以處理迴歸問題,前面ID3使用香農熵來度量集合的無組織程序。如果選用其他方法來代替香農熵,就可以使用樹構建算法來完成迴歸。

2,CART算法與C4.5, ID3的對比

  CART算法相比C4.5算法的分類方法,採用了簡化的二叉樹模型,同時特徵選擇採用了近似的基尼係數來簡化計算。當然CART樹的最大的好處是還可以做迴歸模型,下面給出ID3,C4.5, CART算法的一個比較總結(來自:https://www.cnblogs.com/pinard/p/6053344.html)

   下面,我們總結一下決策樹,這裏不再糾結於ID3, C4.5 和 CART的區別什麼的。我們來看看決策樹算法作爲一個大類別的分類迴歸算法的優缺點。

2.1 決策樹的優點

    1)簡單直觀,生成的決策樹很直觀。

    2)基本不需要預處理,不需要提前歸一化,處理缺失值。

    3)使用決策樹預測的代價是 O(log2m)。m爲樣本數

    4)既可以處理離散值也可以處理連續值。很多算法只是專注於離散值或者連續值。

    5)可以處理多維度輸出的分類問題。

    6)相比於神經網絡之類的黑盒分類模型,決策樹在邏輯上可以得到很好的解釋

    7)可以交叉驗證的剪枝來選擇模型,從而提高泛化能力。

    8) 對於異常點的容錯能力好,健壯性高。

2.2 決策樹的缺點

            1)決策樹算法非常容易過擬合,導致泛化能力不強。可以通過設置節點最少樣本數量和限制決策樹深度來改進。

    2)決策樹會因爲樣本發生一點點的改動,就會導致樹結構的劇烈改變。這個可以通過集成學習之類的方法解決。

    3)尋找最優的決策樹是一個NP難的問題,我們一般是通過啓發式方法,容易陷入局部最優。可以通過集成學習之類的方法來改善。

    4)有些比較複雜的關係,決策樹很難學習,比如異或。這個就沒有辦法了,一般這種關係可以換神經網絡分類方法來解決。

    5)如果某些特徵的樣本比例過大,生成決策樹容易偏向於這些特徵。這個可以通過調節樣本權重來改善。

1,CART分類樹算法

1.1 CART分類算法原理

  上面提到過,在ID3算法中我們使用了信息增益來選擇特徵,信息增益大的優先選擇。在C4.5算法中,採用了信息增益比來選擇特徵,以減少信息增益容易選擇特徵多的特徵的問題。但是無論是ID3還是C4.5都是基於信息論的熵模型,這裏面會涉及大量的對數運算。能不能簡化模型的同時也不至於完全丟失熵模型的優點呢?

  這裏要說的CART算法就是,CART分類樹使用基尼係數來代替信息增益比,基尼係數代表了模型的不純度,基尼係數越小,則不純度越低,特徵越好。

  具體的,在分類問題中,假設有K個類別,第K個類別的概率爲Pk,則概率分佈的基尼指數定義爲:

   如果是二類分類問題,計算就更加簡單了,如果屬於第一個樣本輸出的概率是P,則基尼係數的表達式爲:

   對於給定的樣本D,假設有K個類別,第K個類別的數量爲Ck,則樣本D的基尼係數表達式爲:

   特別的,對於樣本D,如果根據特徵A的某個值 a在數據集D上進行分割,把D分爲D1和D2兩部分,則在特徵A的條件下,D的基尼係數表達式爲:

   其中基尼係數Gini(D) 表示集合D的不確定性,基尼係數Gini(D,A)表示 A=a 分割後集合D的不確定性。基尼指數越大,樣本集合的不確定性越大。

  對於屬性A,分別計算任意屬性值將數據集劃分爲兩部分之後的Gain_Gini,選取其中的最小值,作爲屬性A得到的最優二分方案。然後對於訓練集S,計算所有屬性的最優二分方案,選取其中的最小值,作爲樣本集S的最優二分方案

   我們可以比較下基尼係數表達式和熵模型的表達式,二次運算是不是比對數簡單很多?尤其是二分類的計算更加簡單,但是簡單歸簡單,和熵模型的度量方式比,基尼係數對應的誤差有多大呢?對於二類分類,基尼係數和熵之半的曲線如下:

   從上圖可看出,基尼係數和熵之半的曲線非常接近,僅僅在45度角附近誤差稍大。因此,基尼係數可以作爲熵模型的一個近似替代。而CART分類樹算法就是使用的基尼係數來選擇決策樹的特徵。同時,爲了進一步簡化,CART分類樹算法每次僅僅對某個特徵的值進行二分,而不是多分,這樣CART分類樹算法建立起來的是二叉樹,而不是多叉樹。這樣一可以進一步簡化基尼係數的計算,二可以建立一個更加優雅的二叉樹模型。

1.2  CART分類樹實例詳解

  數據如下:

  上述離散型數據,按照體溫爲恆溫和非恆溫進行劃分,其中恆溫包括哺乳類5個,鳥類2個,非恆溫時包括爬行類3個,魚類3個,兩棲類2個。

   然後計算得到特徵體溫下數據集的 Gini指數,最後我們選擇 Gain_Gini最小的特徵和相應的劃分:

1.3 CART分類樹算法對於連續特徵和離散特徵處理的改進

  對於CART分類樹連續值的處理問題,其思想和C4.5是相同的,都是將連續的特徵離散化。唯一的區別在於在選擇劃分點時的度量方式不同,C4.5使用的是信息增益比,則CART分類樹使用的是基尼係數。

  具體的思路如下:比如有 m個樣本的連續特徵A有m個,從小到大排列爲 a1, a2,  ...  am,則CART算法取相鄰兩樣本值的平均數,一共取得 m-1 個劃分點,其中第 i個劃分點 Ti 表示爲 Ti = (ai+ai+1)/2 。 對於這 m-1個點,分別計算以該店作爲二元分類點時的基尼係數。選擇基尼係數最小的點作爲該連續特徵的二元離散分類點。比如取到的基尼係數最小的點爲 at,則小於at 的值爲類別1,大於at 的值爲類別2,這樣我們就做到了連續特徵的離散化。要注意的是,與ID3或者C4.5 處理離散屬性不同的是,如果當前節點爲連續屬性,則該屬性後面還可以參與子節點的產生選擇過程。

  對於CART分類樹離散值的處理問題,採用的思路是不停的二分離散特徵。

  回憶下ID3或者C4.5,如果某個特徵A被選取建立決策樹節點,如果它有A1,A2,A3三種類別,我們會在決策樹上一下建立一個三叉的節點。這樣導致決策樹是多叉樹。但是CART分類樹使用的方法不同,他採用的是不停的二分,還是這個例子,CART分類樹會考慮把A分成 {A1} 和 {A2, A3},{A2}和{A1, A3}, {A3}和{A1, A2} 三種情況,找到基尼係數最小的組合,比如{A2}和{A1, A3},然後建立二叉樹節點,一個節點是A2對應的樣本,另一個節點是{A1,A3}對應的節點。同時,由於這次沒有把特徵A的取值完全分開,後面我們還有機會在子節點繼續選擇到特徵A來劃分A1和A3。這和ID3或者C4.5不同,在ID3或者C4.5的一棵子樹中,離散特徵只會參與一次節點的建立。

 

2,CART 迴歸樹算法

2.1  CART迴歸樹算法原理

  CART迴歸樹預測迴歸連續型數據,假設X與Y分別是輸入和輸出變量,並且Y是連續變量。在巡邏數據集所在的輸入空間中,遞歸的將每個區間劃分爲兩個子區間並決定每個子區域上的輸出值,構建二叉決策樹。

   選擇最優切分變量 j 與切分點 s:遍歷變量 j,對規定的切分變量 j 掃描切分點 s,選擇使下式得到最小值的(j,  s)對。其中 Rm是被劃分的輸入空間,cm是空間Rm對應的固定輸出值。

   用選定的(j,  s)對,劃分區域並決定相應的輸出值

   繼續對兩個子區域調用上述步驟,將輸入空間劃分爲 M 個區域 R1, R2.....Rm,生成決策樹

  當輸入空間劃分確定時,可以用平方誤差來表示迴歸樹對訓練數據的預測方法,用平方誤差最小的準則求解每個單元上的最優輸出值。

2.2  CART迴歸樹算法實例詳解

  數據如下:

   考慮如上所示的連續型變量,根據給定的數據點,考慮 1.5, 2.5, 3.5, 4.5,5.5, 6.5, 7.5, 8.5, 9.5 切分點,對各切分點依次求出R1, R2, c1, c2以及 m(s),例如當切分點 s=1.5 時,得到 R1={1}  R2={2, 3, 4, 5, 6, 7, 8, 9, 10},其中c1, c2, m(s) 如下所示:

   依次改變(j ,  s)對,可以得到 s 以及 m(s) 的計算結果,如下表所示:

   當 x=6.5 時,此時 R1={1, 2, 3, 4, 5, 6} R2={7, 8, 9, 10} c1=6.24  c2=8.9。迴歸樹T1(x)爲:

 

   然後我們利用 f1(x) 擬合訓練數據的殘差,如下表所示

   用 f1(x) 擬合訓練數據得到平方誤差

   第二步求 T2(x)與 求T1(x) 方法相同,只是擬合的數據是上表的殘差。可以得到

   用 f2(x) 擬合訓練數據的平方誤差

   繼續求得 T3(x),  T4(x),  T5(x), T6(x),如下所示:

   用f6(x)擬合訓練數據的平方損失誤差如下所示,假設此時已經滿足誤差要求,那麼f(x)=f6(x)便是所求的迴歸樹。

2.3  CART剪枝

  我們將一顆充分生長的樹稱爲 T0,希望減少樹的大小來防止過擬合。但是同時去掉一些節點後預測的誤差可能會增大,那麼如何達到這兩個變量之間的平衡則是問題的關鍵。因此我們用一個變量 α 來平衡,定義損失函數如下:

  •  T爲任意子樹,|T| 爲子樹 T 的葉子節點個數
  • α 是參數,權衡擬合程度與樹的複雜度
  • C(T) 爲預測誤差,可以是平方誤差也可以是基尼指數,C(T) 衡量訓練數據的擬合程度

  那麼我們如何找到這個合適的 α 來使擬合程度與複雜度之間達到最好的平衡呢?準確的方法就是將 α 從 0 取到正無窮,對於每個固定的 α ,我們都可以找到使得Cα(T) 最小的最優子樹T(α)

  • 當 α 很小的時候,T0是這樣的最優子樹
  • 當α很大的時候,單獨一個根節點就是最優子樹

   儘管 α 的取值無限多,但是T0的子樹是有限個,Tn是最後剩下的根結點,子樹生成是根據前一個子樹Ti,剪掉某個內部節點後,生成Ti+1。然後對摺頁的子樹序列分別用測試集進行交叉驗證,找到最優的那個子樹作爲我們的決策樹。子樹序列如下:

   因此CART剪枝分爲兩部分,分別是生成子樹序列和交叉驗證。

  下面將實現CART算法迴歸樹。迴歸樹與分類樹的思路類似,但是葉子節點的數據類型不是離散型,而是連續型。

2.3.1 樹迴歸的一般方法

  • (1)收集數據:採用任意方法收集數據
  • (2)準備數據:需要數值型的數據,標稱型數據應該映射成二值型數據
  • (3)分析數據:匯出數據的二維可視化顯示結果,以字典方式生成樹
  • (4)訓練算法:大部分時間都花費在葉子節點數模型的構建上
  • (5)測試算法:使用測試數據上的R2值來分析模型的效果
  • (6)使用算法:使用訓練出的樹做預測,預測結果還可以用來做很多事情

 

2.4  CART生成原理

2.4.1 特徵選擇

  CART分類樹預測分類離散型數據,採用基尼指數選擇最優特徵,同時決定該特徵的最優二值切分點。CART對特徵屬性進行二元分裂。特別的,當特徵屬性爲標量或者連續時,可選擇如下方式分裂:

An instance goes left if CONDITION ,and goes right otherwise

  即樣本記錄滿足CONDITION則分裂給左子樹,否則分裂給右子樹。

2.4.2  標量屬性

  進行分裂的CONDITION可置爲不等於屬性的某值;比如,標量屬性Car Type取值空間爲{Sports, Fanily, Luxury},二元分裂與多路分裂如下:

  連續屬性:CONDITION可以設置爲不大於ε ;比如,連續屬性Annual Income,ε 取屬性相鄰值的平均值,其二元分裂結果如下:

  接下來,需要解決的問題:應該選擇哪種特徵屬性及定義CONDITION,才能分類效果比較好,CART採用Gini指數來度量分裂時的不純度,之所以採用Gini指數,是因爲較於熵而言計算速度更快一些。對於決策樹的節點t,Gini指數計算公式如下:

  Gini指數即爲1與類別Ck的概率平方之和的差值,反映了樣本集合的不確定性程序。Gini指數越大,樣本集合的不確定性程度越高。分類學習過程的本質是樣本不確定性程序的減少(即熵減過程),故應選擇最小Gini指數的特徵分裂。父節點對應的樣本集合爲D,CART選擇特徵A分裂爲兩個子節點,對應集合爲DL與DR;分裂後的Gini指數定義如下:

  其中|.| 表示樣本集合的記錄數量,如上圖的表格所示,當Annual Income 的分裂值取87時,則Gini指數計算如下:

 

 

3,sklearn CART算法

  scikit-learn決策樹算法庫內部實現的時使用了調優過的 CART樹算法,既可以做分類,又可以做迴歸。分類決策樹的類對應的是DecisionTreeClassifier,而回歸決策樹的類對應的是DecisionTreeRegressor。兩者的參數定義幾乎完全相同,但是意義不全相同。下面就對DecisionTreeClassifier和DecisionTreeRegressor的重要參數做一個總結,重點比較兩者參數使用的不同點和調參的注意點。

3.1  DecisionTree Classifier重要參數

  首先我們看看其庫裏的決策樹都有哪些參數:

 

  爲了便於比較,這裏我們使用表格對其重要的參數進行展示,並學習其意義

  • 1.criterion   gini or entropy  前者代表基尼係數,後者代表信息增益。一般說使用默認的基尼係數 gini就可以了,即CART算法,除非你更喜歡類似於ID3, C4.5 的最優特徵選擇方法

  • 2.splitter best or random 前者是在所有特徵中找最好的切分點 後者是在部分特徵中(數據量大的時候),默認的"best"適合樣本量不大的時候,而如果樣本數據量非常大,此時決策樹構建推薦"random"

  • 3.max_features None(所有),log2,sqrt,N 特徵小於50的時候一般使用所有的

  • 4.max_depth 數據少或者特徵少的時候可以不管這個值,如果模型樣本量多,特徵也多的情況下,可以嘗試限制下

  • 5.min_samples_split 如果某節點的樣本數少於min_samples_split,則不會繼續再嘗試選擇最優特徵來進行劃分如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。

  • 6.min_samples_leaf 這個值限制了葉子節點最少的樣本數,如果某葉子節點數目小於樣本數,則會和兄弟節點一起被剪枝,如果樣本量不大,不需要管這個值,大些如10W可是嘗試下5

  • 7.min_weight_fraction_leaf 這個值限制了葉子節點所有樣本權重和的最小值,如果小於這個值,則會和兄弟節點一起被剪枝默認是0,就是不考慮權重問題。一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分佈類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。

  • 8.max_leaf_nodes 通過限制最大葉子節點數,可以防止過擬合,默認是"None”,即不限制最大的葉子節點數。如果加了限制,算法會建立在最大葉子節點數內最優的決策樹。如果特徵不多,可以不考慮這個值,但是如果特徵分成多的話,可以加以限制具體的值可以通過交叉驗證得到。

  • 9.class_weight 指定樣本各類別的的權重,主要是爲了防止訓練集某些類別的樣本過多導致訓練的決策樹過於偏向這些類別。這裏可以自己指定各個樣本的權重如果使用“balanced”,則算法會自己計算權重,樣本量少的類別所對應的樣本權重會高。

  • 10.min_impurity_split 這個值限制了決策樹的增長,如果某節點的不純度(基尼係數,信息增益,均方差,絕對差)小於這個閾值則該節點不再生成子節點。即爲葉子節點 。

  • n_estimators:要建立樹的個數

3.2  DecisionTree Classifier調參注意點

         1)當樣本少數量但是樣本特徵非常多的時候,決策樹很容易過擬合,一般來說,樣本數比特徵數多一些會比較容易建立健壯的模型

    2)如果樣本數量少但是樣本特徵非常多,在擬合決策樹模型前,推薦先做維度規約,比如主成分分析(PCA),特徵選擇(Losso)或者獨立成分分析(ICA)。這樣特徵的維度會大大減小。再來擬合決策樹模型效果會好。

    3)推薦多用決策樹的可視化(下節會講),同時先限制決策樹的深度(比如最多3層),這樣可以先觀察下生成的決策樹裏數據的初步擬合情況,然後再決定是否要增加深度。

    4)在訓練模型先,注意觀察樣本的類別情況(主要指分類樹),如果類別分佈非常不均勻,就要考慮用class_weight來限制模型過於偏向樣本多的類別。

    5)決策樹的數組使用的是numpy的float32類型,如果訓練數據不是這樣的格式,算法會先做copy再運行。

    6)如果輸入的樣本矩陣是稀疏的,推薦在擬合前調用csc_matrix稀疏化,在預測前調用csr_matrix稀疏化。

3.3  決策樹可視化環境搭建

        scikit-learn中決策樹的可視化一般需要安裝graphviz。主要包括graphviz的安裝和python的graphviz插件的安裝。

    第一步是安裝graphviz。下載地址在:http://www.graphviz.org/。如果你是linux,可以用apt-get或者yum的方法安裝。如果是windows,就在官網下載msi文件安裝。無論是linux還是windows,裝完後都要設置環境變量,將graphviz的bin目錄加到PATH,比如我是windows,將C:/Program Files (x86)/Graphviz2.38/bin/加入了PATH

        (注意:這裏一定要在window上加上自己的路徑,不然找不到)

    第二步是安裝python插件graphviz: pip install graphviz

    第三步是安裝python插件pydotplus: pip install pydotplus

    這樣環境就搭好了,有時候python會很笨,仍然找不到graphviz,這時,可以在代碼裏面加入這一行:

    os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'

    注意後面的路徑是你自己的graphviz的bin目錄。

3.4  決策樹可視化——iris案例

  我們以sklearn中 iris 數據作爲訓練集,iris屬性特徵包括花萼長度、花萼寬度、花瓣長度、花瓣寬度,類別共三類,分別爲Setosa、Versicolour、Virginca。

  代碼如下:

from sklearn.datasets import load_iris
from sklearn import tree
import graphviz

# load data
iris = load_iris()
X = iris.data
y = iris.target
clf = tree.DecisionTreeClassifier()
clf.fit(X, y)
# export_graphviz support a variety of aesthetic options
dot_data = tree.export_graphviz(clf, out_file=None,
                                feature_names=iris.feature_names,
                                class_names=iris.target_names,
                                filled=True, rounded=True,
                                special_characters=True)

graph = graphviz.Source(dot_data)
graph.view()

   生成的效果圖如下:

   還可以使用劉建平老師的限制決策樹層數爲4的決策樹例子:

import numpy as np
import matplotlib.pyplot as plt

from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier


# 仍然使用自帶的iris數據
iris = datasets.load_iris()
X = iris.data[:, [0, 2]]
y = iris.target

# 訓練模型,限制樹的最大深度4
clf = DecisionTreeClassifier(max_depth=4)
#擬合模型
clf.fit(X, y)


# 畫圖
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
                     np.arange(y_min, y_max, 0.1))

Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.contourf(xx, yy, Z, alpha=0.4)
plt.scatter(X[:, 0], X[:, 1], c=y, alpha=0.8)
plt.show()

 得到的圖如下:

 

 

參考文獻:https://www.cnblogs.com/en-heng/p/5035945.html

https://www.cnblogs.com/pinard/p/6056319.html

https://www.zhihu.com/search?type=content&q=CART%E5%88%86%E7%B1%BB%E6%A0%91

https://www.cnblogs.com/pinard/p/6053344.html

《機器學習實戰》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章