
開學(xué)那會兒翻開這本書的目錄第四章“決策樹”三個字平平無奇我甚至一度覺得它是最沒技術(shù)含量的一章——不就是if-else嵌套嗎直到用Python里的庫跑完幾個模型的對比又回頭啃了兩遍這章內(nèi)容才發(fā)現(xiàn)自己錯得離譜。純啃公式的讀書筆記太多了這一篇我盡量換個講法不按原書章節(jié)順序走而是先把“一棵樹到底是怎么長出來的”講明白再回到那些容易被跳過的難點上比如剪枝、連續(xù)值、缺失值、多變量樹。如果你也是正在啃這本書的初學(xué)者或者用了一段時間樹模型想看下底層邏輯這篇筆記應(yīng)該能幫你省不少力氣。1. 決策樹的核心邏輯一套“先問哪個問題”的分層篩選機制這一節(jié)在原書里屬于基礎(chǔ)鋪墊但很多人恰恰是在這里就開始吃夾生飯。決策樹的推理邏輯說白了就是一句大白話遇到一個新樣本我不知道它屬于哪一類就反復(fù)問它“你的某個特征是什么”每問一次縮小一圈候選范圍最后剩下來的類別就是預(yù)測結(jié)果。這個過程放到數(shù)據(jù)結(jié)構(gòu)里就是一棵樹。頂部叫根節(jié)點中間每個判斷點叫內(nèi)部節(jié)點最底部不再繼續(xù)分叉的叫葉節(jié)點每個葉節(jié)點對應(yīng)一個決策結(jié)果。整棵樹的生成過程是從根節(jié)點開始遞歸地“選屬性、分數(shù)據(jù)、建子樹”直到數(shù)據(jù)被分隔得足夠純或者可用特征用完為止。書中給的基本流程里有兩個細節(jié)值得圈出來每一個非葉節(jié)點只挑一個最優(yōu)屬性劃分這個“最優(yōu)”是局部意義上的最優(yōu)決策樹整體并不保證全局最優(yōu)。遞歸終止有三個條件當(dāng)前節(jié)點樣本全屬于同一類別當(dāng)前屬性集為空或所有樣本在剩余屬性上取值相同樣本集合為空。第三個條件容易被漏掉它對應(yīng)一種特殊處理——把父節(jié)點中樣本最多的類別作為葉節(jié)點的標(biāo)記。這種“分而治之”的策略之所以幾十年不過時在于它和人類的分類認知高度吻合。我拿生活中最常見的場景舉例你媽給你介紹對象對方資料擺在桌上你第一眼看的既不是學(xué)歷也不是收入而是“在不在一個城市”。見了面看“聊不聊得來”再往下看“有沒有存款”。每問一個問題都砍掉一批選項這就是一棵活脫脫的決策樹。樹模型的強項不是像線性回歸那樣給出一個光滑的連續(xù)打分而是把規(guī)則攤開每一步都講得出理由——所以它在風(fēng)控、醫(yī)療診斷這類需要解釋性的場景里依然是主力。這里的原書內(nèi)容我建議反復(fù)讀三遍核心不是背流程而是理解“遞歸”“劃分”“純度”這幾個詞背后到底對應(yīng)了什么操作。2. 屬性選擇到底在優(yōu)化什么信息熵、信息增益、增益率、基尼系數(shù)的來龍去脈如果決策樹生成過程是一臺機器那“選哪個屬性作為當(dāng)前節(jié)點”就是這臺機器的發(fā)動機。書里真正難啃的第一塊硬骨頭就在這里——明明叫決策樹為什么非要扯上信息論里的“熵”。信息熵這個概念當(dāng)初也繞了我一陣。你把它理解成不確定性程度就對了。一箱球如果全是紅的閉著眼睛猜都能猜對熵為0如果五種顏色各占五分之一猜錯概率高熵就大。公式是Ent(D) -Σ p(k) × log2(p(k))其中k是類別下標(biāo)p(k)是第k類樣本占比。這個公式不要求你會推導(dǎo)但要求你能說出一個直覺含義熵越小數(shù)據(jù)越純。信息增益說白了就是“劃分之前的不確定性”減去“劃分之后的不確定性”。Gain(D, a) Ent(D) - Σ(|Dv| / |D| × Ent(Dv))其中v是屬性a的各個取值。這個差值越大說明用了這個屬性之后類別變得更確定了那它就應(yīng)該被優(yōu)先拿來劃分。ID3決策樹就是按信息增益選屬性的。信息增益有個明顯毛病——它天然偏好取值數(shù)目多的屬性。比如你拿樣本編號當(dāng)屬性每個編號一個值信息增益直接拉滿但這顯然毫無泛化能力。為了掰回這種傾向C4.5改成用增益率公式是Gain_ratio(D, a) Gain(D, a) / IV(a)其中IV(a)是屬性a的固有值等于 -Σ(|Dv| / |D| × log2(|Dv| / |D|))。取值多的屬性IV值通常更大等于給信息增益做了個除法懲罰。但懲罰也不能太狠否則又會偏向取值少的屬性所以C4.5的做法是先挑信息增益高于平均水平的屬性再從里面選增益率最高的?;嵯禂?shù)又是另一套思路它不用熵的log運算公式是Gini(D) 1 - Σ p(k)2。直觀含義是從數(shù)據(jù)集里隨便抽兩個樣本它們類別不一致的概率。概率越小數(shù)據(jù)集越純。CART決策樹就是基于基尼指數(shù)來選劃分屬性的。我曾經(jīng)在項目里只盯著準確率看對Node上的impurity不純度指標(biāo)毫不在意。后來遇到一棵深度夸張的樹打印出的結(jié)構(gòu)完全不符合業(yè)務(wù)直覺回頭排查才發(fā)現(xiàn)是不同節(jié)點用了不同的分裂標(biāo)準模型庫默認的配置和書上寫的算法根本對不上。所以我建議你把這些數(shù)學(xué)指標(biāo)動手算一遍——取一個20條樣本的小表分別用三種指標(biāo)算同一個屬性的得分你就知道它們的結(jié)果差在哪了。不親手算只看公式你永遠記不牢。為了更直觀這里放一個我當(dāng)年手工推演的對照小表虛構(gòu)數(shù)據(jù)集“天氣、溫度、是否出門”劃分屬性信息增益增益率基尼指數(shù)按劃分后加權(quán)均值天氣0.2470.2860.350溫度0.1070.1390.408選擇結(jié)論選“天氣”若增益率比較仍可能偏向“天氣”選“天氣”不同指標(biāo)在大部分簡單數(shù)據(jù)上結(jié)論一致但在特征取值數(shù)差異很大的數(shù)據(jù)集上ID3和C4.5會有明顯分歧。這也是為什么工程上更常用CART因為它計算快而且后面能直接對接梯度提升框架。3. 剪枝處理為什么樹不能任它長到完美在我第一次用默認參數(shù)訓(xùn)練決策樹時訓(xùn)練集的準確率直逼100%一到測試集立刻掉到剛及格的水平。當(dāng)時的我把鍋甩給數(shù)據(jù)集太小后來讀了剪枝一節(jié)才恍然大悟——樹長過頭了把訓(xùn)練集里的細枝末節(jié)全記下來了這種狀態(tài)叫過擬合。剪枝是決策樹對抗噪聲和過擬合的主要手段。書里講了兩種思路預(yù)剪枝和后剪枝。預(yù)剪枝的策略是邊構(gòu)建邊剪每次嘗試劃分一個節(jié)點時先用驗證集估算一下如果這個劃分不做的精度再估算一下做了的精度只有后者更高才允許生成。它可以防止樹長得太大減少訓(xùn)練時間但風(fēng)險在于“只看一步”——當(dāng)前收益不高不代表后續(xù)幾步不會帶來更大收益。這種貪心式的近視眼可能會導(dǎo)致某些有潛力的分支還沒展開就夭折了精度提升有限。后剪枝的策略是先讓你把那棵樹完整長出來然后自底向上對每個非葉節(jié)點做手腳如果把以它為首的分支整個換成一個葉節(jié)點驗證集精度不降反升那就果斷砍掉。這個方案保留了更多分支空間通常比預(yù)剪枝更能降低過擬合風(fēng)險但代價是訓(xùn)練時間明顯增加。我曾拿一個中等規(guī)模的數(shù)據(jù)集做過對比用預(yù)剪枝生成的樹小了一半訓(xùn)練時間少了一大截但測試集精度比后剪枝低了三個多點。可見“懶得多花時間”這種心態(tài)在機器學(xué)習(xí)里經(jīng)常要付出精度代價。書里還暗示了一個在實際建模時很重要、但寫得比較含蓄的點剪枝用的驗證集數(shù)據(jù)會參與“訓(xùn)練”嗎嚴格說驗證集參與了模型超參數(shù)的選擇也就是結(jié)構(gòu)的選擇這部分信息依然可能造成一定程度的間接過擬合。很多人在做交叉驗證時會忽略這層耦合關(guān)系。我的習(xí)慣是如果數(shù)據(jù)量充足預(yù)留30%作為最終測試集剪枝只在內(nèi)部做交叉驗證數(shù)據(jù)量緊張時寧可少剪幾刀也要保證測試集是“干凈”的。4. 連續(xù)值與缺失值處理容易被漏掉的工程細節(jié)如果說剪枝是這章最容易丟分的主觀題那連續(xù)值和缺失值就是最容易被跳過的客觀題。很多人學(xué)完ID3、C4.5就覺得自己會決策樹了一上手遇到“年齡27.5歲”這種連續(xù)特征就愣住因為信息增益那套理論默認屬性是離散的。書里給的標(biāo)準解法叫二分法思路極簡屬性有N個不同取值就排序把相鄰取值的中間點作為候選劃分點把連續(xù)值變成“大于等于這個點”和“小于這個點”兩個離散塊然后按離散屬性去算信息增益。注意連續(xù)值特征可以被多次使用不同層次的節(jié)點可以在不同切分點上重復(fù)利用它這一點和離散屬性“用一次就不能再用”完全不同。這一節(jié)還有一處對小白尤其不友好就是缺失值的處理。訓(xùn)練集里如果某條樣本缺少了當(dāng)前劃分屬性上的取值既不能直接扔掉樣本太少會浪費信息也不能隨便填個均值會引入噪聲。書里給出的方案是找劃分屬性時用無缺失值樣本作為子集計算信息增益再按缺失樣本比例折算。某個樣本在劃分屬性上缺失時把它按不同權(quán)重劃分到所有子節(jié)點權(quán)重和樣本落入子節(jié)點的比例相關(guān)。權(quán)重機制貫穿始終每個樣本初始權(quán)重為1缺失值樣本每次劃分都按比例更新權(quán)重最后被用于葉節(jié)點的類別統(tǒng)計。這個機制讀起來很容易被繞暈我建議你在紙上畫一個只有10條數(shù)據(jù)的小例子手動走一遍“1號樣本缺失顏色特征”時的權(quán)重流動過程比看十遍公式都管用。真要在具體庫中處理時實現(xiàn)略有差異但思路相同處理好缺失值后模型對比才有意義。5. 從單棵樹到一片森林這本書埋下的進階線索CART樹在實踐中的使用是深度學(xué)習(xí)中也會用到的構(gòu)件。因為任何基于決策樹的集成方法除了極少數(shù)情況外都需要在每一輪迭代中擬合一棵樹這棵樹的分裂質(zhì)量直接決定了集成的上限。所以看第四章的時候多留一個心眼底層邏輯扎實了后面學(xué)梯度提升時會順利得多。在此之前你手頭的工具配置就可以先跑通了。裝好環(huán)境后隨便找一個公開的表格數(shù)據(jù)比如鳶尾花、泰坦尼克用默認參數(shù)擬合一棵CART樹再打印出樹結(jié)構(gòu)圖你會對“劃分”“純度”“葉節(jié)點樣本數(shù)”這些詞有非常直觀的認知。不用急著調(diào)參主要為了建立體感讓博士式的符號變成看得見的圖形。剪枝在庫中通常由成本復(fù)雜度參數(shù)控制數(shù)值越大、樹被砍得越狠可以簡單地把這個參數(shù)理解成后剪枝力度的一種實現(xiàn)。這部分再往后就是調(diào)參藝術(shù)了。6. 多變量決策樹線性的根邏輯的葉這一節(jié)在初讀時很容易被當(dāng)成“選讀內(nèi)容”掠過但它其實回答了一個關(guān)鍵問題——決策樹的分類邊界為什么總是橫平豎直的普通決策樹在每個節(jié)點只做單屬性判斷學(xué)到的分類邊界是軸平行的也就是和坐標(biāo)軸垂直的線。如果真實數(shù)據(jù)的最優(yōu)邊界是斜的普通決策樹就尷尬了——它必須用一堆階梯狀的折線去反復(fù)逼近那條斜線樹深直接翻倍泛化能力自然受影響。多變量決策樹的想法是一個節(jié)點的劃分不用單個屬性而用多個屬性的線性組合。每個非葉節(jié)點維護一組系數(shù)相當(dāng)于在以這些屬性為坐標(biāo)的空間中畫一條任意方向的斜線作為邊界。這樣針對斜向分布的類別樹不用長很高就能分開。書的第四章在這里點到為止但對讀后續(xù)章節(jié)很重要因為很多集成模型中的隨機特征子空間、線性樹等概念都能從這里找到思想源頭。我在工作中用到的調(diào)參和模型融合方案也是基于這種思路做一些組合特征。比如給決策樹喂一些手工構(gòu)造的“組合后特征”而非原始單特征往往能顯著壓縮樹深度。這也算是多變量樹思想在工程里的“窮人手寫版”吧。7. 動手實現(xiàn)一版迷你決策樹從零開始不長篇大論這章的筆記如果看完就散那確實太可惜了。建議用最精簡的方式在十幾分鐘內(nèi)把核心跑通我寫過一版簡化實現(xiàn)核心偽代碼如下函數(shù) 生成節(jié)點(樣本集D, 屬性集A): 如果 D 全部屬于同一類: 返回葉節(jié)點 如果 A 為空 或 D 在A上取值相同: 返回葉節(jié)點標(biāo)記為 D 中最多的類 對每個屬性 a in A: 計算按 a 劃分后的純度指標(biāo) 選出最優(yōu)屬性 best_a 創(chuàng)建節(jié)點 node標(biāo)記為 best_a 對 best_a 的每個取值 v: 子集 Dv D 中 best_a v 的樣本 如果 Dv 為空: 創(chuàng)建葉節(jié)點標(biāo)記為 D 中最多的類 否則: 遞歸調(diào)用 生成節(jié)點(Dv, A \ {best_a})這里最有價值的是條件“D在A上取值相同”。很多人實現(xiàn)時會漏掉它導(dǎo)致遞歸無限循環(huán)——所有樣本在剩余屬性上完全一樣了再往下分已經(jīng)不可能但代碼意識不到還在硬選屬性。等你寫代碼親自踩一次這個坑就知道書中為什么特意加這個終止條件了。寫完這個骨架后再跑一下剪枝對比課堂味和工程味就都有了。8. 筆記之外結(jié)合實戰(zhàn)的三個提醒很多人在讀書筆記階段非常認真但一到自己的數(shù)據(jù)集上就陷入“默認參數(shù)流”。決策樹模型的有效性并不取決于那個“魔力參數(shù)”被調(diào)得有多準而取決于數(shù)據(jù)和模型的匹配度。針對樹的調(diào)優(yōu)我個人的經(jīng)驗有以下幾點樹的深度和葉子節(jié)點最小樣本數(shù)比分裂標(biāo)準對結(jié)果影響大得多。設(shè)置葉子節(jié)點最小樣本數(shù)可以連續(xù)抑制過擬合比每次調(diào)裁剪復(fù)雜度參數(shù)更易解釋。特征數(shù)值范圍敏感度低但特征重要性會被取值多的特征帶偏。決策樹的信息增益偏好會在真實數(shù)據(jù)中導(dǎo)致偏差用C4.5思路先算增益均值再選增益率最大往往比直接調(diào)默認參數(shù)更穩(wěn)。樹模型天然適合處理混合類型特征但前提是把缺失值編碼成顯式狀態(tài)而不是全部填成-1或者0。缺失本身可能是重要的信號。書里不會告訴你的是同樣的超參數(shù)在數(shù)據(jù)量變化超過一個數(shù)量級之后需要完全重調(diào)。樹的復(fù)雜度本質(zhì)上由樣本密度決定樣本越多樹越有空間長深。我在多個項目中的保守做法是先固定一個合理的葉子最小樣本數(shù)再通過交叉驗證選擇深度和特征數(shù)量并把這種配置寫入項目記錄中。沒有記錄不清的調(diào)參經(jīng)驗跟過擬合有什么區(qū)別9. 回頭看這一章到底教會了什么第四章看上去信息量巨大把原始樹的誕生過程拆開來看不過幾年時間沉淀下來的幾個經(jīng)驗找最有區(qū)分度的特征、控制生成規(guī)模、容忍真實數(shù)據(jù)的臟亂、必要時允許邊界傾斜。如果把這本書當(dāng)作一本“手藝集”第四章就是最核心的入門工具章。讀完筆記之后別忘了回原書看每個小節(jié)最后的小結(jié)和習(xí)題。習(xí)題雖少但每道題都值得認真推理尤其是那些要求你“用公式計算”的題——不親手算一遍你真的會以為自己懂了。這一章讀完之后再往后看神經(jīng)網(wǎng)絡(luò)、支持向量機這些黑箱模型時你會多一個對比參照黑箱模型犧牲了可解釋性換來了表達復(fù)雜邊界的能力而決策樹一直堅持把決策攤在臺面上代價是邊界表達受限。沒有十全十美的模型只有適不適合你當(dāng)前場景的選擇。就我個人而言很多模型上線后最煎熬的環(huán)節(jié)就是向業(yè)務(wù)方解釋預(yù)測邏輯每到這種時候我都會懷念決策樹的直白。