建立決策樹

在本單元中,您將使用 YDF (Yggdrasil Decision Forest) 程式庫訓練及解讀決策樹。

本單元的靈感來自 🧭 YDF 入門教學課程。

初賽

研究資料集之前,請先完成下列步驟:

  1. 建立新的 Colab 筆記本
  2. 在新的 Colab 筆記本中放置並執行下列程式碼行,即可安裝 YDF 程式庫:
    !pip install ydf -U
  3. 匯入下列程式庫:
    import ydf
    import numpy as np
    import pandas as pd

帕默企鵝資料集

本 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 阿德利 Torgersen 39.1 18.7 181.0 3750.0 男性 2007 年
1 阿德利 Torgersen 39.5 17.4 186.0 3800.0 女性 2007 年
2 阿德利 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

物種 可能性
阿德利 (紅色) 8%
Gentoo (藍色) 58%
下巴帶 (綠色) 36%

 

表 5. 不同物種的可能性 (如果 bill_depth_mm < 42.3

物種 可能性
阿德利 (紅色) 97%
Gentoo (藍色) 2%
下巴帶 (綠色) 0%

bill_depth_mm 是數值特徵。因此,我們使用「針對具有數值特徵的二元分類進行精確分割」演算法,找出 42.3 這個值。

如果 bill_depth_mm ≥ 42.3 為 True,請進一步測試 flipper_length_mm ≥ 207.5 是否能近乎完美地分離 Gentoo 和 Gentoo+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 個範例),因此準確度估計值有雜訊。

在實務上,對於這麼小的資料集,最好使用交叉驗證,因為這樣可以計算出更準確的評估指標值。不過,為了簡化,我們在本例中會繼續進行訓練和測試。

改善模型超參數

這個模型是使用預設超參數值訓練的單一決策樹。如要取得更準確的預測結果,可以採取下列做法:

  1. 使用更強大的學習者,例如隨機森林梯度提升樹模型。下一頁將說明這些學習演算法。

  2. 根據觀察結果和直覺,最佳化超參數。建議參閱模型改善指南

  3. 使用超參數調整功能,自動測試大量可能的超參數。

由於我們尚未瞭解隨機森林和梯度提升樹狀結構演算法,且範例數量太少,無法進行自動超參數調整,因此您將手動改善模型。

上方的決策樹很小,且包含 61 個範例的葉節點含有阿德利和帽帶標籤。為什麼演算法沒有進一步分割這個葉節點?有兩個可能的原因:

  • 可能已達到每個葉節點的最低樣本數 (預設為 min_examples=5)。
  • 樹狀結構可能經過分割,然後修剪,以避免過度擬合。

將範例數量下限設為 1,然後查看結果:

model = ydf.CartLearner(label=label, min_examples=1).train(train_dataset)
model.plot_tree()

以 min_examples=1 訓練的決策樹。

圖 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

隨機森林的準確度比簡單樹狀結構更高。您將在後續頁面瞭解原因。

使用方式和限制

如先前所述,單一決策樹的品質通常不如現代機器學習方法,例如隨機森林、梯度提升樹狀結構和類神經網路。不過,在下列情況下,決策樹仍相當實用:

  • 做為簡單且經濟實惠的基準,用來評估更複雜的方法。
  • 模型品質與可解讀性之間需要取捨時。
  • 做為 Decision Forest 模型解讀的 Proxy,課程稍後會探討這點。