在本單元中,您將使用 YDF (Yggdrasil Decision Forest) 程式庫訓練及解讀決策樹。
本單元靈感來自 🧭 YDF 入門教學課程。
初賽
在研究資料集之前,請先執行下列操作:
- 建立新的 Colab 筆記本。
- 在新的 Colab 筆記本中放置並執行下列程式碼行,即可安裝 YDF 程式庫:
!pip install ydf -U
- 匯入下列程式庫:
import ydf import numpy as np import pandas as pd
Palmer Penguins 資料集
這個 Colab 使用 Palmer Penguins 資料集,其中包含三種企鵝的大小測量值:
- 下巴帶
- Gentoo
- Adelie
這是分類問題,目標是根據 Palmer's Penguins 資料集的資料,預測企鵝的種類。以下是企鵝:
圖 16. 三種不同的企鵝物種。圖片來源:@allisonhorst
以下程式碼會呼叫 pandas 函式,將 Palmer Penguins 資料集載入記憶體:
path = "https://storage.googleapis.com/download.tensorflow.org/data/palmer_penguins/penguins.csv"
dataset = pd.read_csv(path)
label = "species"
# Display the first 3 examples.
dataset.head(3)
下表列出 Palmer Penguins 資料集中的前 3 個示例格式:
表 3. Palmer Penguins 中的前 3 個範例
物種 | 島嶼 | bill_length_mm | bill_depth_mm | flipper_length_mm | body_mass_g | 性別 | 年 | |
---|---|---|---|---|---|---|---|---|
0 | Adelie | Torgersen | 39.1 | 18.7 | 181.0 | 3750.0 | 男性 | 2007 |
1 | Adelie | Torgersen | 39.5 | 17.4 | 186.0 | 3800.0 | 女性 | 2007 |
2 | Adelie | Torgersen | 40.3 | 18.0 | 195.0 | 3250.0 | 女性 | 2007 |
完整資料集包含數值 (例如 bill_depth_mm
)、類別 (例如 island
) 和缺少特徵的混合內容。與神經網路不同,決策樹會原生支援所有這些特徵類型,因此您不必進行一熱編碼、標準化或額外的 is_present 特徵。
以下程式碼單元會將資料集分割為訓練集和測試集:
# Use the ~20% of the examples as the testing set
# and the remaining ~80% of the examples as the training set.
np.random.seed(1)
is_test = np.random.rand(len(dataset)) < 0.2
train_dataset = dataset[~is_test]
test_dataset = dataset[is_test]
print("Training examples: ", len(train_dataset))
# >> Training examples: 272
print("Testing examples: ", len(test_dataset))
# >> Testing examples: 72
使用預設超參數訓練決策樹
您可以使用 CART (分類和迴歸樹) 學習演算法 (又稱為學習器) 訓練第一個決策樹,而無須指定任何超參數。這是因為 ydf.CartLearner
學習器會提供良好的預設超參數值。您將在課程後半部進一步瞭解這類模型的運作方式。
model = ydf.CartLearner(label=label).train(train_dataset)
先前的呼叫未指定要用作輸入特徵的欄。因此,系統會使用訓練集的每個資料欄。呼叫也未指定輸入特徵的語意 (例如數值、類別、文字)。因此,系統會自動推斷地圖項目語意。
呼叫 model.plot_tree()
即可顯示產生的決策樹:
model.plot_tree()
在 Colab 中,您可以使用滑鼠顯示特定元素的詳細資料,例如每個節點的類別分布。
圖 17. 使用預設超參數訓練的決策樹。
Colab 顯示根條件包含 243 個例項。不過,您可能還記得訓練資料集包含 272 個範例。系統會自動保留剩下的 29 個例子,用於驗證和樹狀結構修剪。
第一個條件會測試 bill_depth_mm
的值。表 4 和 5 顯示不同物種的可能性,取決於第一個條件的結果。
表 4. 如果 bill_depth_mm ≥
42.3
,不同物種的可能性
物種 | 可能性 |
---|---|
Adelie (紅色) | 8% |
Gentoo (藍色) | 58% |
下巴帶 (綠色) | 36% |
表 5. 如果 bill_depth_mm < 42.3
,不同物種的可能性
物種 | 可能性 |
---|---|
Adelie (紅色) | 97% |
Gentoo (藍色) | 2% |
下巴帶 (綠色) | 0% |
bill_depth_mm
是數值特徵。因此,我們使用精確分割數值特徵的二元分類演算法,找出 42.3 這個值。
如果 bill_depth_mm ≥ 42.3
為 True,請進一步測試 flipper_length_mm ≥ 207.5
是否能幾乎完美地將 Gentoos 與 Gentoos+Adelie 分開。
下列程式碼會提供模型的訓練和測試準確度:
train_evaluation = model.evaluate(train_dataset)
print("train accuracy:", train_evaluation.accuracy)
# >> train accuracy: 0.9338
test_evaluation = model.evaluate(test_dataset)
print("test accuracy:", test_evaluation.accuracy)
# >> test accuracy: 0.9167
測試準確度高於訓練準確度的情況很少見,但仍有可能發生。在這種情況下,測試集可能與訓練集不同。不過,這裡並非如此,因為訓練資料和測試資料是隨機分割的。更可能的解釋是,測試資料集非常小 (只有 72 個範例),因此精確度估計值不準確。
實際上,對於這麼小的資料集,建議使用交叉驗證,因為這可計算出更準確的評估指標值。不過,為了簡化說明,我們會在本例中繼續進行訓練與測試。
改善模型超參數
這個模型是使用預設超參數值訓練的單一決策樹。如要取得更準確的預測結果,您可以:
由於我們尚未看到隨機森林和梯度提升樹演算法,且示例數量太少,無法進行自動超參數調整,因此您將手動改善模型。
上圖所示的決策樹很小,而 61 個例子的葉節包含 Adelie 和 Chinstrap 標籤。為什麼演算法沒有進一步細分這個葉節?有兩個可能的原因:
- 每個葉節點的樣本數量可能已達到最低數量 (預設為
min_examples=5
)。 - 樹狀圖可能已分割並修剪,以免過度擬合。
將示例數量下限調降至 1,查看結果:
model = ydf.CartLearner(label=label, min_examples=1).train(train_dataset)
model.plot_tree()
圖 18. 使用 min_examples=1 訓練的決策樹。
包含 61 個例子的葉節點已多次進一步細分。
為了瞭解是否有必要進一步劃分節點,我們評估了這個新模型在測試資料集的品質:
print(model.evaluate(test_dataset).accuracy)
# >> 0.97222
模型品質提升,測試準確度從 0.9167 提高到 0.97222。這項超參數變更是個好主意。
先前的決策樹
持續改善超參數,我們就能達到完美的準確度。不過,我們可以訓練更強大的模型 (例如隨機森林),而非使用這項手動程序,看看是否能獲得更好的效果。
model = ydf.RandomForestLearner(label=label).train(train_dataset)
print("Test accuracy: ", model.evaluate(test_dataset).accuracy)
# >> Test accuracy: 0.986111
隨機森林的準確度優於簡單樹狀圖。您將在後續頁面中瞭解原因。
使用方式和限制
如前所述,單一決策樹的品質通常不如隨機森林、梯度提升樹和神經網路等新式機器學習方法。不過,決策樹仍可用於下列情況:
- 可做為評估更複雜方法的簡單且低成本基準。
- 模型品質和可解釋性之間的取捨。
- 做為解讀決策樹模型的替代方案,本課程稍後會進一步探討。