決策樹算法測試代碼「決策樹代碼實現」

本教程介紹了用於分類的決策樹,即分類樹,包括分類樹的結構,分類樹如何進行預測,使用scikit-learn構造分類樹,以及超參數的調整。

使用Python了解分類決策樹(附代碼)

本教程詳細介紹了決策樹的工作原理

由於各種原因,決策樹一種流行的監督學習方法。決策樹的優點包括,它既可以用於回歸,也可用於分類,易於解釋並且不需要特徵縮放。它也有一些缺點,比如容易過擬合。本教程介紹了用於分類的決策樹,也被稱為分類樹。

除此之外,本教程還將涵蓋:

  • 分類樹的結構(樹的深度,根節點,決策節點,葉節點/終端節點)
  • 分類樹如何進行預測
  • 如何通過Python中的scikit-learn構造決策樹
  • 超參數調整

與往常一樣,本教程中用到的代碼可以在我的github(結構,預測)中找到,我們開始吧!

什麼是分類樹?

分類和回歸樹(CART)是由Leo Breiman引入的,用一種於解決分類或回歸預測建模問題的決策樹算法。本文只介紹分類樹。

分類樹

從本質上講,分類樹將分類轉化為一系列問題。下圖是在IRIS數據集(花卉種類)上訓練的一個分類樹。根節點(棕色)和決策節點(藍色)中包含了用於分裂子節點的問題。根節點即為最頂端的決策節點。換句話說,它就是你遍歷分類樹的起點。葉子節點(綠色),也叫做終端節點,它們不再分裂成更多節點。在葉節點處,通過多數投票決定分類。

使用Python了解分類決策樹(附代碼)

將三個花卉品種(IRIS數據集)一一進行分類的分類樹

如何使用分類樹

使用分類樹,要從根節點(棕色)開始,逐層遍歷整棵樹,直到到達葉節點(終端節點)。如下圖所示的分類樹,假設你有一朵花瓣長度為4.5cm的花,想對它進行分類。首先從根節點開始,先回答「花瓣長度(單位:cm)≤ 2.45嗎?」因為寬度大於2.45,所以回答否。然後進入下一個決策節點,回答「花瓣長度(單位:cm)≤ 4.95嗎?」。答案為是,所以你可以預測這朵花的品種為變色鳶尾(versicolor)。這就是一個簡單的例子。

使用Python了解分類決策樹(附代碼)

分類樹如何生長(非數學版)

分類樹從數據中學到了一系列「如果…那麼…」的問題,其中每個問題都涉及到一個特徵和一個分割節點。從下圖的局部樹(A)可看出,問題「花瓣長度(單位:cm)≤ 2.45」將數據基於某個值(本例中為2.45)分成兩個部分。這個數值叫做分割點。對分割點而言,一個好的值(使得信息增益最大)可將類與類之間分離開。觀察下圖中的B部分可知,位於分割點左側的所有點都被歸為山鳶尾類(setosa),右側的所有點則被歸為變色鳶尾類(versicolor)。

使用Python了解分類決策樹(附代碼)

從圖中可看出,山鳶尾類(setosa)中所有的38個點都已被正確分類。它是一個純節點。分類樹在純節點上不會分裂。它不再產生信息增益。但是不純節點可以進一步分裂。觀察圖B的右側可知,許多點被錯誤歸類到了變色鳶尾類(versicolor)。換而言之,它包含了分屬於兩個不同類(setosa和versicolor)的點。分類樹是個貪婪算法,這意味着它會默認一直分裂直到得到純節點。而且,該算法會為不純節點選擇最佳分割點(我們會在下節介紹數學方法)。

使用Python了解分類決策樹(附代碼)

在上圖中,樹的最大深度為2。樹的深度是對一棵樹在進行預測之前可分裂次數的度量。樹可進行多次分裂,直到樹的純度越來越高。多次重複此過程,會導致樹的深度越來越大,節點越來越多。這會引起對訓練數據的過擬合。幸運的是, 大多數分類樹的實現都允許控制樹的最大深度,從而減少過擬合。換而言之,可以通過設置決策樹的最大深度從而阻止樹的生長超過某個特定深度。可通過下圖直觀地了解最大深度。

使用Python了解分類決策樹(附代碼)

選擇準則

使用Python了解分類決策樹(附代碼)

本節解答了信息增益、基尼指數和熵是如何計算出來的。

在本節,你可以了解到什麼是分類樹中根節點/決策節點的最佳分割點。決策樹在某個特徵和相對應的分割點上進行分裂,從而根據給定的準則(本例中為基尼指數或熵)產生最大的信息增益(IG)。可以將信息增益簡單定義為:

IG = 分裂前的信息(父) – 分裂後的信息(子)

通過下圖的決策樹,我們可以更清晰的理解父與子。

使用Python了解分類決策樹(附代碼)

下圖為更準確的信息增益公式。

使用Python了解分類決策樹(附代碼)

因為分類樹是二元分裂,上述公式可以簡化為以下公式。

使用Python了解分類決策樹(附代碼)

基尼指數和熵是兩個用于衡量節點不純度的常用準則。

使用Python了解分類決策樹(附代碼)

為了更好的理解這些公式,下圖展示了如何使用基尼指數準則計算決策樹的信息增益。

使用Python了解分類決策樹(附代碼)

下圖展示了如何使用熵來計算決策樹的信息增益。

使用Python了解分類決策樹(附代碼)

我不打算對細節進行過多的闡述,但是你應當知道,不同的不純度度量(基尼指數和熵)通常會產生相似的結果。下圖就展示了基尼指數和熵是極其相似的不純度度量。我猜測,基尼指數之所以是scikit-learn的默認值,是因為熵的計算過程略慢一些(因為它使用了對數)。

使用Python了解分類決策樹(附代碼)

不同的不純度度量(基尼指數和熵)通常會產生相似的結果。感謝Data Science StackExchange 和 Sebastian Raschka為本圖提供的靈感。

在結束本節之前,我應註明,各種決策樹算法彼此不同。比較流行的算法有ID3,C4.5和CART。Scikit-learn使用了CART算法的優化版本。你可以點擊此處了解它的時間複雜度。

使用Python實現分類樹

我們在上節介紹了分類樹的理論。之所以需要學習如何使用某個編程語言來實現決策樹,是因為處理數據可以幫助我們來理解算法。

加載數據

Iris數據集是scikit-learn自帶的數據集之一,不需要從外部網站下載。通過下列代碼載入數據。

import pandas as pd
from sklearn.datasets import load_iris
data = load_iris()
df = pd.DataFrame(data.data, columns=data.feature_names)
df['target'] = data.target
使用Python了解分類決策樹(附代碼)

原始Pandas df(特徵和目標)

將數據劃分為訓練集和測試集

下述代碼將75%的數據劃分到為訓練集,25%的數據劃分到測試集合。

X_train, X_test, Y_train, Y_test = train_test_split(df[data.feature_names], df['target'], random_state=0)
使用Python了解分類決策樹(附代碼)

圖中的顏色標註了數據框df中的數據劃分到了哪類(X_train, X_test, Y_train, Y_test)變量

注意,決策樹的優點之一是,你不需要標準化你的數據,這與PCA和邏輯回歸不同,沒有標準化的數據對它們的影響非常大。

Scikit-learn建模的四個步驟

第一步:導入你想使用的模型

在scikit-learn中,所有的機器學習模型都被封裝為Python中的類。

from sklearn.tree import DecisionTreeClassifier

第二步:構造模型的實例

在下列代碼中,我通過設定max_depth=2來預剪枝我的樹,從而確保它的深度不會超過2。請注意,這個教程的下一節將介紹如何為你的樹選擇恰當的max_depth值。

還需注意,在下列代碼中,我設定random_state=0,所以你也可以得到和我一樣的結果。

clf = DecisionTreeClassifier(max_depth = 2,
 random_state = 0)

第三步:基於數據訓練模型

該模型將學習X (sepal length, sepal width, petal length, and petal width) 和 Y(species of iris)之間的關係。

clf.fit(X_train, Y_train)

第四步:預測未知(測試)數據的標籤

# Predict for 1 observation
clf.predict(X_test.iloc[0].values.reshape(1, -1))
# Predict for multiple observations
clf.predict(X_test[0:10])

請記住,預測只是葉節點中實例的多數類。

評估模型性能

儘管有許多評估模型性能的方式(精度,召回率,F1得分,ROC曲線等),我們還是保持簡單的基調,使用準確率作為評估的標準。

準確率的定義為:(正確預測的比例):正確預測的數量/總數據量

# The score method returns the accuracy of the model
score = clf.score(X_test, Y_test)
print(score)

調整樹的深度

尋找max_depth最優值的過程就是調整模型的過程。下列代碼輸出了不同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,在準確率同樣高的情況下,模型的複雜度最低。

使用Python了解分類決策樹(附代碼)

選擇max_depth=3因為此時模型的精確率高且複雜度較低。

你需要謹記,max_depth和決策樹的深度並不是一回事。Max_depth是對決策樹進行預剪枝的一個方法。換而言之,如果一棵樹在某個深度純度已經足夠高,將會停止分裂。下圖分別展示了當max_depth的值為3,4,5時的決策樹。由下圖可知,max_depth為4和5時的決策樹是一模一樣的。它們的深度相同。

使用Python了解分類決策樹(附代碼)

請觀察我們是如何得到兩棵一模一樣的樹

如果想知道你訓練的決策樹的深度是多少,可以使用get_depth方法。除此之外,可以通過get_n_leaves方法得到葉子節點的數量。

儘管本教程已經介紹了一些選擇準則(基尼指數,熵等)和樹的max_depth,請記住你也可以調整要分裂的節點的最小樣本(min_samples_leaf),最大葉子節點數量(max_leaf_nodes)等。

特徵重要性

分類樹的優點之一是,它們相對易於解釋。基於scikit-learn的分類樹可以計算出特徵的重要性,即在給定特徵上分裂而導致基尼指數或熵減小的總量。Scikit-learn對每個特徵輸出一個0和1之間的數值。所有特徵的重要性之和為1。下列代碼展示了在決策樹模型中每個特徵的重要性。

importances = pd.DataFrame({'feature':X_train.columns,'importance':np.round(clf.feature_importances_,3)})
importances = importances.sort_values('importance',ascending=False)
使用Python了解分類決策樹(附代碼)

在上述例子中(iris的某個特定的訓練集測試集劃分),花瓣寬度的特徵重要性權重最高。我們可以通過察看相應的決策樹來確認。

使用Python了解分類決策樹(附代碼)

這個決策樹僅基於兩個特徵進行分裂,分別是花瓣寬度(單位:cm)和花瓣長度(單位:cm)

請注意,如果一個特徵的重要性分值較低,也並不意味着這個特徵對預測而言不重要,只是說明在樹的較早階段,它未被選擇到。該特徵也可能與另一個信息量較高的特徵完全相同或高度相關。特徵重要性值不能說明它們對哪個類別具有很好的預測性,也不會說明可能影響預測的特徵之間的關係。要注意的是,在進行交叉驗證或類似的驗證時,可以使用來自不同訓練集測試集劃分的特徵重要性值的平均值。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/208281.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-08 15:00
下一篇 2024-12-08 15:00

相關推薦

發表回復

登錄後才能評論