1. 程式人生 > >詳解CART樹剪枝原理和過程 --- 機器學習

詳解CART樹剪枝原理和過程 --- 機器學習

       這一節主要講前面多次的提到的決策樹問題,前面的決策樹生成演算法遞迴的產生決策樹,直到不能繼續分支或者達到要求為止,這樣的決策樹往往對訓練資料的分類很準確,因為他就是基於訓練資料的熵或者基尼不存度進行分類的,因此對訓練資料的會產生過擬合現象,而對未知的資料則沒有那麼準確。過擬合的本質原因是決策樹在訓練時追求如何提高訓練資料的準確度,而沒有考慮構件出的決策樹的複雜性,直觀上我們能想象出當決策樹越複雜時,訓練資料的分類效果越好,因為複雜意味著分支多,分支多意味著對資料的分類效果越好。決策樹複雜是對訓練資料過擬合的本質原因,因此為了提高決策樹的泛化能力,需要兼顧決策樹的複雜度問題,這個問題如何考慮才能得到比較好的決策樹呢?

先弄清楚幾個概念,這裡的概念很重要,請大家一定要注意,因為這也是下面搞暈的原因:

決策樹由節點和有向邊組成,其中節點有兩種型別: 內部節點和葉節點,內部節點表示一個特徵或者屬性(如A,B,C都為內部節點),葉節點表示一個類(如D1,D2,,都是葉節點)

       目前比較好的解決這個問題的方法就是決策樹的剪枝演算法,這個演算法是怎麼工作的呢?或者工作的原理是什麼呢?下面我們就一起來看看:

       為了讓大家更容易理解,在這裡先簡單的講解一下李航的《統計學習方法》中的一個例子,這個例子所給的訓練資料是貸款申請的資料,根據特徵決策是否批准貸款申請,特徵有年齡、是否有工作、是否有房子、信貸情況這4個特徵:

這裡通過熵計算,詳情就不說了,直接給出公式和決策樹圖:

好,我們來詳細的看看決策樹的決策過程,他是依據資訊增益進行決策的,增益越大說明這個特徵對最後的分類影響越大,因此從上層到下層資訊增益是逐漸下降的,為了追求訓練資料的準確率,會不停的進行分支下去,直到資訊增益0.此時只有一類了,因此也是最純淨的,所以增益為0 ,但是這也帶來了問題就是決策樹的分支會很複雜,且對訓練資料過擬合,對新資料沒有很好的準確度,因此為了提高決策樹的泛化能力,就需要決策樹不要只追求訓練資料的準確度,還要考慮泛化能力,而這個泛化能力的提高是希望決策樹對訓練資料不要分的那麼“仔細”,想要達到這樣的效果,一個可行的辦法是控制決策樹的樹枝的複雜性,我們知道決策樹的樹枝越多說明分的越細,因此可以通過控制樹枝的多少來提高決策樹的泛化能力,到這裡我們找到了,如何解決這個問題的思路了,但是問題是我還要考慮決策的準確率,不能以大幅度降低準度度來提高決策樹的的泛化能力,這個是不可取的,因此為了兼顧兩者,前輩們提出了剪枝的方法,這個方法是怎麼工作呢?其實很簡單,首先我還是按照之前的決策生成決策樹,此時的決策樹對訓練資料具有很高的準確度但是泛化能力不好,在此基礎上,提出了控制決策樹的複雜度,為了兼顧準確度,把二者結合定義一個目標表達式,這個目標表達式是怎麼定義呢?這個稍後解釋,先引入一個概念,我們知道對分類的資料我們同個資訊增益進行決策的,那麼這個資訊增益充當什麼角色呢?如使用決策樹進行迴歸那麼我們引入的試試損失函式或者誤差函式這個又是充當什麼呢?這兩個有什麼相同之處呢?其實這個兩個就是我們決策樹的決策依據,在分類中我們以最大的資訊增益為決策依據,而在迴歸中,我們以損失函式作為我們的優化目標,使其達到最小就是我們的最終目的。我們從這裡可不可以加入我們的一些限制決策樹複雜度的條件呢?其實我們新的目標表達式就是這樣來的,我們下面詳細看看:

在這裡我就不碼字了,直接從李航老師的書中解圖過來,大家多包涵,我儘量把剪枝的過程說清楚,我看好多部落格都說的不清不楚,還有的就是錯的,本篇是從問題從發,一步步到表示式,這樣才不會覺得很突兀:

 這裡需要解釋一下此時定義的,此時的定義就把決策依據的損失函式和決策樹的複雜的聯絡起來了,這也是最不好理解的,也是很多部落格說不清的地方,在這裡只代表本人的理解,有什麼問題請留言,我們一起探討。首先定義時是一個完整的樹就是對訓練資料準確度很高但是泛化能力不好的原始樹,假設這顆樹的葉節點個數為|T|,t為樹T的某個葉節點(如上圖的有自己的房子和有工作都是葉節點),這個葉節點有N_t個樣本點,其中K類的樣本點個數為N_{tk},就這些樣本點中有N_{tk}個樣本資料屬於K類的,H_t(T)是指在葉節點的熵,我們知道每個葉節點往下分支的依據是資訊增益,其來源就是熵的變化,而且分支越細,熵就越小,因為確定性越來越大了。因此損失函式的定義為:

                                                          C_\alpha (T)=\sum_{t=1}^{T}N_tH_t(T)+\alpha |T|

我們來看看這個公式的意義,等式的右邊的第一項求和是 對樹T的所有的葉節點的樣本資料的熵進行求和(我們知道在迴歸中損失函式是真實值和預測值的差的平方),而在分類中,以熵為分類依據,理論熵分類完全正確,熵應該為0(因為都是同一類,帶來為1),但是如果樹葉節點的熵不為零說明分類的不完全正確,同時此時的熵就是損失了或者誤差了(這裡好多人沒解釋為什麼這樣,這裡我解釋,有疑問的請留言),而後面的一項\alpha |T|,是說明這顆樹T的葉節點的個數乘以一個係數\alpha,這表明什麼呢?簡單來說就是衡量了樹的複雜度,我們知道一顆樹越複雜表明他的樹葉越多,因此個數就可以衡量樹的複雜度,而\alpha就是用來調整樹的複雜度的,稍後會詳解\alpha的,好,到這裡我們再看看上面的損失函式的合理性,大家應該都可以理解了,如果是迴歸更容易理解因為是誤差函式,這個時候我們求其C_\alpha (T)的最小值,此時一方面是要求正確率儘可能的高,另一方面是希望複雜度儘可能的低,這樣目標公式就建立起來了,我們再看看這個目標公式會發現,此時的損失函式是正對全域性優化的即整棵樹的所有葉節點的損失和,因此求出來的一定是全域性最優的,到這裡大家應該都可以理解,我們繼續深入:

這裡的內容就是我們上面說的,只是作者沒詳細說明為什麼這樣算,然而這裡也是讓人困惑的地方,只有這裡搞懂,下面才能深入理解他的剪枝過程,我們接著看李航的書:

下面就詳細的介紹一下 \alpha是怎樣影響複雜度的,首先大家需要明確,我們的損失函式的第一項和第二項是矛盾的:

                                                      C_\alpha (T) = C(T) + \alpha \left | T \right |

因為我們整體是希望求的最小值,而上式的第一項是損失誤差,希望儘量的小,而要想使損失儘量的小,那麼表現在決策樹上就是決策樹越來越複雜即樹葉節點很多,即|T|很多,但是第二項呢?也是希望儘可能的小,在給定 \alpha時,希望|T|儘可能的小,因此矛盾就出來了,因此需要找到平衡的|T|,而這個平衡值T就和\alpha有關了,大家還記得嶺迴歸的目標式子麼?和那裡的嶺引數一個道理,在這裡我們單獨的解釋一下這個\alpha的作用:

對任意內部節點t,

剪枝前的狀態:有\left | T_t \right |個葉子節點,預測誤差是C_\left | T_t \right |

剪枝後的狀態:只有本身一個葉子節點,預測誤差是C(t)

因此剪枝前的以t節點為根節點的子樹的損失函式是 :

                                                                  C_\alpha (T_t) = C(T_t) + \alpha \left | T_t \right |

剪枝後的損失函式是:

                                                                   C_{\alpha }(t) = C(t) + \alpha

在這裡需要解釋一下,剪枝後為什麼是這樣,剪之後就只有他本身的葉節點了,因此直接計算誤差,因為只有一個葉節點,所以\alpha |T|就是\alpha

好,到這裡我們需要好好探討一下了,我們知道,決策樹隨著樹葉的增加是損失值是減小的,那麼如果我剪掉這個葉節點,是不是就意味著的損失值在增大呢,是的,但是此時的\left | T_t \right |減小為1了,一個增大,一個減小,最後求和的結果是增大還是減小呢?答案是不一定的,這裡理解很關鍵,我們看看剪枝前的公式,發現誤差是最小的,但是決策樹此時複雜度是最大的,因此對應一個值,那麼剪枝後呢?剪之後就是我們知道損失是增大的,但是複雜度即葉節點從\left | T_t \right |直接變為1了,,因此他們的求和後的結果就有三種情況,要麼相等,要麼是增大或者減小,這個大家應該可以理解。對於剪枝後的求和如果小於剪枝前的求和,說明覆雜度在其中起到關鍵的作用,而損失函式起的作用很小,簡單來說就是剪枝前的葉節點並沒有很好的提高準確度但是卻帶來更復雜的樹,因此可以考慮剪去這個葉節點,,這就是剪枝的過程和原理了,這也是李航書中提到的:

 到這裡,相信大家還是能理解的,不理解的請留言,我們繼續討論,我們知道,剪枝前和剪枝後的大小還取決於\alpha,因為\alpha不同,得到的結果可能不同,那麼\alpha取何止更好呢?這個值怎麼取才能是全域性最優剪枝呢?我們繼續深入探討:

此時我們令剪枝前和剪枝後的兩式相等:

                                                                C_\alpha (T_t) = C_\alpha (t)

即得到:

                                                                C(T_t) + \alpha \left | T_t \right | = C(t) + \alpha

求出\alpha

                                                                 \alpha = \frac{C(t) - C(T_t)}{\left | T_t \right | - 1 }           

也就是說當\alpha等於這個值時剪枝前和剪枝後的損失結果是一樣的,這個就是靈界條件了,好,我們知道臨界條件了,下面是到底如何取\alpha才能取到全域性最優的剪枝後的決策樹呢?

這時我們需要再看看這個表示式:

                                                                  C_\alpha (T_t) = C(T_t) + \alpha \left | T_t \right |

我們發現\alpha在中間起著制約的作用,但是它到底代表什麼物理意義呢?我們來分析一下,我們知道,我們求C_\alpha (T_t)的最小值,如果\alpha很大時加入為無窮大,則此時要想最小,就需要\left | T_t \right |最小,如果\alpha很小假如為0時,此時\left | T_t \right |可以取到很大,同時也說明了,當\alpha=0時,樹很複雜,訓練資料準確率很高即過擬合,因此可以看出\alpha是衡量損失函式剪枝後的損失程度的量。

這裡\alpha如何選擇引數呢?哪個引數對應的損失最小同時複雜度最小呢?我們知道,一旦給定一個\alpha值,則就會對應一個最優的剪枝樹,只是哪個是最優的,則需要遍歷了,如何遍歷呢?

此時大家應該可以看懂了吧,人們是找到所有可能剪枝的剪枝後樹,然後通過資料交叉驗證,看看哪個的錯誤率和泛化能力最好就選擇哪個。

好,剪枝過程基本講完了,下面我們以CART數的建立和剪枝為例進行系統的講解:

CART樹的生成是以二叉樹為分支的,分為分類和迴歸,這裡就不詳細講了,請看李航的《統計學習方法》第68頁,下面直接給出生成演算法了:

 生成還是和以前的決策樹一樣,我們看看剪枝演算法:

CART剪枝:

先說明一下,該演算法是採用動態規劃進行設計的,因此他先計算樹T的所有節點的損失值,剪枝是從下到上進行剪枝的:

上面的第6步有錯誤,應該返回到底三步,要不然最小值永遠不變了 ,之所以返回到第三步就是計算全域性的\alpha,在此更新。李航網上已經勘誤了,大家需要注意

剛開始設定\alpha為無窮大,,然後計算所有內部節點的 \alpha,然後取一個最小的值賦值給\alpha,我們知道,所有的節點的\alpha肯定是不一樣的,\alpha最小說明|T|很大,那麼就可以剪枝了,此時記錄對應的剪枝後的樹,儲存起來,減掉以後,全域性的節點的\alpha都會變化,此時在次計算所有的\alpha,然後繼續剪枝,這裡需要強調的是這是遞迴實現動態規劃,因此它是在第一個剪枝的基礎上進行再次剪枝的,因為重新計算了\alpha,那麼那個最小的\alpha一定比之前的要大,直到根節點結束。下面能解釋我的理解:

就是說因為是遞迴,所以只要滿足條件才會全部返回,我也不知道這樣理解對不對,感覺有問題的請留言我們一起交流,機器學習演算法寫完後我會開一篇演算法專欄,把常用的演算法總結一下。 

好,本篇到此結束,有疑問請留言,這是本人的理解難免會有錯誤,請多包涵,可以一起討論,微訊號:zsffuture