Python · 決策樹(三)· 節點
02-04
(這裡是本章用到的 GitHub 地址)
(這裡是本章用到的 Python 相關知識)
上一章我們把 node 的結構搭好了,這一章要做的就是塞東西進去。為此,我們不妨先看看我們需要實現什麼:
- 一個 fit 函數,它能夠根據輸入的數據遞歸生成一顆決策樹
- 一個 handle_terminate 函數,它在 node 成為 leaf 時調用,用於更新它爸爸和它爸爸的爸爸和……等等的信息
- 一個 prune 函數,用於剪枝
- 一個 view 函數,用於可視化
大提上來說就是這兩點,剩下的就是一些細節。我們分開來說說怎麼去實現它們
- fit 函數
- 先說一下大概的流程:
- 接受數據和相應的標籤
- 判斷該 node 是否應該被當做 leaf;若是,則 return,否則繼續往下走算出各維度的條件熵,記錄下最好的條件熵、信息增益和此時關注的數據維度比如說,如果輸入的數據和標籤為:那麼通過計算各個維度的條件熵和信息增益可知,此時該 node 關注的數據維度應該是第一維、也就是 A 對應的那一維。直觀來說,這意味著 A 提供的信息量最大(事實上在這個栗子中,A 和 Label 是一樣的)
- 根據信息增益判斷是否終止(比如在 ID3 中,如果信息增益小於閾值的話就直接終止。這種判斷方法會有比較嚴重的缺陷,觀眾老爺們可以想一想為什麼 ( σω)σ 【提示:異或數據集】)
- 根據所選的數據維度的各個特徵把數據集切分成幾份,分別餵給新的 node、遞歸,同時把這些 node 記錄在自己的 children 裡面
- 由於利用了遞歸,感覺還是一個比較乾淨利落的實現。下面就貼一些核心的代碼,完整的實現可以參見這裡
- 計算各個維度的條件熵和信息增益,這裡就要用到準則章節的東西了
- 遞歸
- handle_terminate 函數
- 如果童鞋們還記得我們 node 的結構的話,大概就會知道當一個 node 成為 leaf 後、需要做的事情有兩個:
- 計算該 leaf 屬於哪一類
- 更新它列祖列宗的 leafs 變數
只要分別實現它們就好了:
其中 - prune 函數
- 需要指出的是,node 的 prune 函數不是決策樹的剪枝演算法、而是會在決策樹的剪枝演算法中被調用。它僅僅是為了該 node 的所有子孫都切了而已(喂
- 先說說流程,核心思想其實就是把該 node 變成一個 leaf:
- 判斷該 node 應該屬於哪一類
- 把該 node 的 leafs 中的 leaf 從該 node 的列祖列宗中的 leafs 中刪除
- 把該 node 存進列祖列宗的 leafs 中
- 把該 node 自身及其所有子孫打上「已被剪枝」的標籤
- 接下來是實現:其中打標籤用的 self.mark_pruned 函數的定義如下:
- view 函數
- 基本思路很簡單:如果自己是 leaf、就直接輸出相關信息,否則在輸出自己相關信息的同時、還要調用自己所有 children 的 view 函數。以下是實現:
這一章有點長,稍微總結一下:
- 決策樹的生長關鍵是靠遞歸。當 node 接收一個數據和標籤時,它會選出數據的某個維度、記錄下來,然後會根據該維度的各個特徵將數據、標籤進行劃分,分別餵給新的 node、從而能夠遞歸下去
- 在 node 被判定應該是 leaf 時,要判斷它屬於哪一類並更新它列祖列宗的 leafs 變數
- node 的 prune 函數是用來把 node 變成 leaf 並更新結構的,它本身不是決策樹的剪枝演算法、但它會在決策樹的剪枝演算法中被調用
下一章我們就要說說怎麼建立一個框架以利用這些 node 來搭建一顆真正的決策樹了。可能有童鞋已經敏銳地發現:不就只剩一個剪枝演算法沒有實現了嗎?
事實上正是如此。下一章的框架確實只額外地實現了剪枝演算法,剩下的都是封裝的活兒
希望觀眾老爺們能夠喜歡~
(猛戳我進入下一章!( σω)σ)
推薦閱讀:
※有哪些比較好的機器學習,深度學習的網路資源可利用?
※SVM在線性不可分的情況下,利用核函數升維後就一定線性可分嗎?
※CVAE-GAN論文翻譯(3.4. CVAEGAN的目標)
※大話機器學習之隨機森林