使用Python了解分類決策樹(附代碼)(python決策樹分類算法代碼)
作者:Michael Galarnyk
翻譯:李潤嘉
校對:和中華
本文約3600字,建議閱讀15分鐘。
本教程介紹了用于分類的決策樹,即分類樹,包括分類樹的結構,分類樹如何進行預測,使用scikit-learn構造分類樹,以及超參數(shù)的調整。
本教程詳細介紹了決策樹的工作原理
由于各種原因,決策樹一種流行的監(jiān)督學習方法。決策樹的優(yōu)點包括,它既可以用于回歸,也可用于分類,易于解釋并且不需要特征縮放。它也有一些缺點,比如容易過擬合。本教程介紹了用于分類的決策樹,也被稱為分類樹。
除此之外,本教程還將涵蓋:
- 分類樹的結構(樹的深度,根節(jié)點,決策節(jié)點,葉節(jié)點/終端節(jié)點)
- 分類樹如何進行預測
- 如何通過Python中的scikit-learn構造決策樹
- 超參數(shù)調整
與往常一樣,本教程中用到的代碼可以在我的github(結構,預測)中找到,我們開始吧!
什么是分類樹?
分類和回歸樹(CART)是由Leo Breiman引入的,用一種于解決分類或回歸預測建模問題的決策樹算法。本文只介紹分類樹。
分類樹
從本質上講,分類樹將分類轉化為一系列問題。下圖是在IRIS數(shù)據(jù)集(花卉種類)上訓練的一個分類樹。根節(jié)點(棕色)和決策節(jié)點(藍色)中包含了用于分裂子節(jié)點的問題。根節(jié)點即為最頂端的決策節(jié)點。換句話說,它就是你遍歷分類樹的起點。葉子節(jié)點(綠色),也叫做終端節(jié)點,它們不再分裂成更多節(jié)點。在葉節(jié)點處,通過多數(shù)投票決定分類。
將三個花卉品種(IRIS數(shù)據(jù)集)一一進行分類的分類樹
如何使用分類樹
使用分類樹,要從根節(jié)點(棕色)開始,逐層遍歷整棵樹,直到到達葉節(jié)點(終端節(jié)點)。如下圖所示的分類樹,假設你有一朵花瓣長度為4.5cm的花,想對它進行分類。首先從根節(jié)點開始,先回答“花瓣長度(單位:cm)≤ 2.45嗎?”因為寬度大于2.45,所以回答否。然后進入下一個決策節(jié)點,回答“花瓣長度(單位:cm)≤ 4.95嗎?”。答案為是,所以你可以預測這朵花的品種為變色鳶尾(versicolor)。這就是一個簡單的例子。
分類樹如何生長(非數(shù)學版)
分類樹從數(shù)據(jù)中學到了一系列“如果…那么…”的問題,其中每個問題都涉及到一個特征和一個分割節(jié)點。從下圖的局部樹(A)可看出,問題“花瓣長度(單位:cm)≤ 2.45”將數(shù)據(jù)基于某個值(本例中為2.45)分成兩個部分。這個數(shù)值叫做分割點。對分割點而言,一個好的值(使得信息增益最大)可將類與類之間分離開。觀察下圖中的B部分可知,位于分割點左側的所有點都被歸為山鳶尾類(setosa),右側的所有點則被歸為變色鳶尾類(versicolor)。
從圖中可看出,山鳶尾類(setosa)中所有的38個點都已被正確分類。它是一個純節(jié)點。分類樹在純節(jié)點上不會分裂。它不再產生信息增益。但是不純節(jié)點可以進一步分裂。觀察圖B的右側可知,許多點被錯誤歸類到了變色鳶尾類(versicolor)。換而言之,它包含了分屬于兩個不同類(setosa和versicolor)的點。分類樹是個貪婪算法,這意味著它會默認一直分裂直到得到純節(jié)點。而且,該算法會為不純節(jié)點選擇最佳分割點(我們會在下節(jié)介紹數(shù)學方法)。
在上圖中,樹的最大深度為2。樹的深度是對一棵樹在進行預測之前可分裂次數(shù)的度量。樹可進行多次分裂,直到樹的純度越來越高。多次重復此過程,會導致樹的深度越來越大,節(jié)點越來越多。這會引起對訓練數(shù)據(jù)的過擬合。幸運的是, 大多數(shù)分類樹的實現(xiàn)都允許控制樹的最大深度,從而減少過擬合。換而言之,可以通過設置決策樹的最大深度從而阻止樹的生長超過某個特定深度??赏ㄟ^下圖直觀地了解最大深度。
選擇準則
本節(jié)解答了信息增益、基尼指數(shù)和熵是如何計算出來的。
在本節(jié),你可以了解到什么是分類樹中根節(jié)點/決策節(jié)點的最佳分割點。決策樹在某個特征和相對應的分割點上進行分裂,從而根據(jù)給定的準則(本例中為基尼指數(shù)或熵)產生最大的信息增益(IG)。可以將信息增益簡單定義為:
IG = 分裂前的信息(父) – 分裂后的信息(子)
通過下圖的決策樹,我們可以更清晰的理解父與子。
下圖為更準確的信息增益公式。
因為分類樹是二元分裂,上述公式可以簡化為以下公式。
基尼指數(shù)和熵是兩個用于衡量節(jié)點不純度的常用準則。
為了更好的理解這些公式,下圖展示了如何使用基尼指數(shù)準則計算決策樹的信息增益。
下圖展示了如何使用熵來計算決策樹的信息增益。
我不打算對細節(jié)進行過多的闡述,但是你應當知道,不同的不純度度量(基尼指數(shù)和熵)通常會產生相似的結果。下圖就展示了基尼指數(shù)和熵是極其相似的不純度度量。我猜測,基尼指數(shù)之所以是scikit-learn的默認值,是因為熵的計算過程略慢一些(因為它使用了對數(shù))。
不同的不純度度量(基尼指數(shù)和熵)通常會產生相似的結果。感謝Data Science StackExchange 和 Sebastian Raschka為本圖提供的靈感。
在結束本節(jié)之前,我應注明,各種決策樹算法彼此不同。比較流行的算法有ID3,C4.5和CART。Scikit-learn使用了CART算法的優(yōu)化版本。你可以點擊此處了解它的時間復雜度。
使用Python實現(xiàn)分類樹
我們在上節(jié)介紹了分類樹的理論。之所以需要學習如何使用某個編程語言來實現(xiàn)決策樹,是因為處理數(shù)據(jù)可以幫助我們來理解算法。
加載數(shù)據(jù)
Iris數(shù)據(jù)集是scikit-learn自帶的數(shù)據(jù)集之一,不需要從外部網(wǎng)站下載。通過下列代碼載入數(shù)據(jù)。
import pandas as pdfrom sklearn.datasets import load_irisdata = load_iris()df = pd.DataFrame(data.data, columns=data.feature_names)df[‘target’] = data.target
原始Pandas df(特征和目標)
將數(shù)據(jù)劃分為訓練集和測試集
下述代碼將75%的數(shù)據(jù)劃分到為訓練集,25%的數(shù)據(jù)劃分到測試集合。
X_train, X_test, Y_train, Y_test = train_test_split(df[data.feature_names], df[‘target’], random_state=0)
圖中的顏色標注了數(shù)據(jù)框df中的數(shù)據(jù)劃分到了哪類(X_train, X_test, Y_train, Y_test)變量
注意,決策樹的優(yōu)點之一是,你不需要標準化你的數(shù)據(jù),這與PCA和邏輯回歸不同,沒有標準化的數(shù)據(jù)對它們的影響非常大。
Scikit-learn建模的四個步驟
第一步:導入你想使用的模型
在scikit-learn中,所有的機器學習模型都被封裝為Python中的類。
from sklearn.tree import DecisionTreeClassifier
第二步:構造模型的實例
在下列代碼中,我通過設定max_depth=2來預剪枝我的樹,從而確保它的深度不會超過2。請注意,這個教程的下一節(jié)將介紹如何為你的樹選擇恰當?shù)膍ax_depth值。
還需注意,在下列代碼中,我設定random_state=0,所以你也可以得到和我一樣的結果。
clf = DecisionTreeClassifier(max_depth = 2, random_state = 0)
第三步:基于數(shù)據(jù)訓練模型
該模型將學習X (sepal length, sepal width, petal length, and petal width) 和 Y(species of iris)之間的關系。
clf.fit(X_train, Y_train)
第四步:預測未知(測試)數(shù)據(jù)的標簽
# predict for 1 observationclf.predict(X_test.iloc[0].values.reshape(1, -1))# Predict for multiple observationsclf.predict(X_test[0:10])
請記住,預測只是葉節(jié)點中實例的多數(shù)類。
評估模型性能
盡管有許多評估模型性能的方式(精度,召回率,F(xiàn)1得分,ROC曲線等),我們還是保持簡單的基調,使用準確率作為評估的標準。
準確率的定義為:(正確預測的比例):正確預測的數(shù)量/總數(shù)據(jù)量
# The score method returns the accuracy of the modelscore = clf.score(X_test, Y_test)print(score)
調整樹的深度
尋找max_depth最優(yōu)值的過程就是調整模型的過程。下列代碼輸出了不同max_depth值所對應的決策樹的準確率。
# List of values to try for max_depth:max_depth_range = list(range(1, 6))# List to store the accuracy for each value of max_depth:accuracy = []for depth in max_depth_range: clf = DecisionTreeClassifier(max_depth = depth, random_state = 0)clf.fit(X_train, Y_train) score = clf.score(X_test, Y_test) accuracy.append(score)
由下圖可看出,當max_depth的值大于或等于3時,模型的準確率最高,所以選擇max_depth=3,在準確率同樣高的情況下,模型的復雜度最低。
選擇max_depth=3因為此時模型的精確率高且復雜度較低。
你需要謹記,max_depth和決策樹的深度并不是一回事。Max_depth是對決策樹進行預剪枝的一個方法。換而言之,如果一棵樹在某個深度純度已經足夠高,將會停止分裂。下圖分別展示了當max_depth的值為3,4,5時的決策樹。由下圖可知,max_depth為4和5時的決策樹是一模一樣的。它們的深度相同。
請觀察我們是如何得到兩棵一模一樣的樹
如果想知道你訓練的決策樹的深度是多少,可以使用get_depth方法。除此之外,可以通過get_n_leaves方法得到葉子節(jié)點的數(shù)量。
盡管本教程已經介紹了一些選擇準則(基尼指數(shù),熵等)和樹的max_depth,請記住你也可以調整要分裂的節(jié)點的最小樣本(min_samples_leaf),最大葉子節(jié)點數(shù)量(max_leaf_nodes)等。
特征重要性
分類樹的優(yōu)點之一是,它們相對易于解釋。基于scikit-learn的分類樹可以計算出特征的重要性,即在給定特征上分裂而導致基尼指數(shù)或熵減小的總量。Scikit-learn對每個特征輸出一個0和1之間的數(shù)值。所有特征的重要性之和為1。下列代碼展示了在決策樹模型中每個特征的重要性。
importances = pd.DataFrame({‘feature’:X_train.columns,’importance’:np.round(clf.feature_importances_,3)})importances = importances.sort_values(‘importance’,ascending=False)
在上述例子中(iris的某個特定的訓練集測試集劃分),花瓣寬度的特征重要性權重最高。我們可以通過察看相應的決策樹來確認。
這個決策樹僅基于兩個特征進行分裂,分別是花瓣寬度(單位:cm)和花瓣長度(單位:cm)
請注意,如果一個特征的重要性分值較低,也并不意味著這個特征對預測而言不重要,只是說明在樹的較早階段,它未被選擇到。該特征也可能與另一個信息量較高的特征完全相同或高度相關。特征重要性值不能說明它們對哪個類別具有很好的預測性,也不會說明可能影響預測的特征之間的關系。要注意的是,在進行交叉驗證或類似的驗證時,可以使用來自不同訓練集測試集劃分的特征重要性值的平均值。
結束語
雖然這篇文章只介紹了用于分類的決策樹,但請隨意閱讀我的其他文章《用于回歸的決策樹(Python)》。分類和回歸樹(CART)是一個相對較老的技術(1984),是更復雜的技術的基礎。決策樹的主要缺點之一是它們通常不是最準確的算法。部分原因是決策樹是一種高方差算法,這意味著訓練數(shù)據(jù)中的不同劃分會導致非常不同的樹。如果您對本教程有任何疑問或想法,請隨時通過以下評論或通過Twitter與我們聯(lián)系。
作者簡介:
Michael Galarnyk是一名數(shù)據(jù)科學家和企業(yè)培訓師。他目前在Scripps翻譯研究所工作。
您可以在:
Twitter(https://twitter.com/GalarnykMichael)
Medium(https://medium.com/@GalarnykMichael)
GitHub(https://github.com/mGalarnyk)上找到他。
原文標題:
Understanding Decision Trees for Classification in Python
原文鏈接:
https://www.kdnuggets.com/2019/08/understanding-decision-trees-classification-python.htm
編輯:于騰凱
校對:林亦霖
譯者簡介
李潤嘉,首都師范大學應用統(tǒng)計碩士在讀。對數(shù)據(jù)科學和機器學習興趣濃厚,語言學習愛好者。立志做一個有趣的人,學想學的知識,去想去的地方,敢想敢做,不枉歲月。
— 完 —
關注清華-青島數(shù)據(jù)科學研究院官方微信公眾平臺“THU數(shù)據(jù)派”及姊妹號“數(shù)據(jù)派THU”獲取更多講座福利及優(yōu)質內容。