建立決策樹

在本單元中,您將使用 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 資料集,其中含有三種企鵝物種的大小測量結果:

  • 熱土歐
  • 阿德利

這是一個分類問題—我們的目標是根據帕爾馬企鵝資料集內的資料預測企鵝的物種。以下為企鵝:

三種不同的企鵝類型

圖 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. 巴爾默企鵝的前 3 個例子

物種 島嶼 bill_length_mm bill_depth_mm flipper_length_mm body_mass_g 性愛
0 號 阿德利 托爾森 39.1 18.7 181.0 3,750.0 男性 2007 年
1 阿德利 托爾森 39.5 17.4 186.0 3,800.0 女性 2007 年
2 阿德利 托爾森 40.3 18.0 195.0 3,250.0 女性 2007 年

完整資料集包含數值 (例如 bill_depth_mm)、類別 (例如 island) 和缺少的特徵組合。與類神經網路不同,決策樹會以原生支援所有地圖項目類型,因此您不必執行 one-hot 編碼、正規化或額外的 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

物種 Likelihood
阿德利 (紅色) 8%
基多 (藍色) 58%
氯 (綠色) 36%

 

表 5. 如果 bill_depth_mm < 42.3

品種 Likelihood
阿德利 (紅色) 97%
基多 (藍色) 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 個範例),因此估算準確度不會有雜訊。

實際上,針對這類小型資料集,建議使用交叉驗證,因為它可以計算更準確的評估指標值。 不過,為了簡單起見,本例會繼續進行訓練和測試。

改善模型超參數

模型是一個決策樹狀圖,我們使用預設的超參數值進行訓練。如要獲得更準確的預測結果,您可以:

  1. 請使用更強大的學習功能,例如隨機樹系梯度強化樹狀結構模型。我們會在下一頁說明這些學習演算法。

  2. 根據觀察結果和直覺,最佳化超參數。模型改善指南也可以助您一臂之力。

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

由於我們尚未看到隨機樹系和梯度增強的樹狀演算法,且範例數量過少,因此無法自動調整超參數,您將手動改善模型。

上方顯示的決策樹很小,有 61 個範例的分葉含有 Adelie 和 Chinstrap 標籤的組合。為什麼演算法沒有進一步區分這片葉子?有兩個可能的原因:

  • 每個分葉的樣本數量 (預設為 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(pandas_train_dataset)
print("Test accuracy: ", model.evaluate(pandas_test_dataset).accuracy)
# >> Test accuracy: 0.986111

隨機森林的準確度比我們簡單的樹林更勝一籌。您將在後續頁面中瞭解原因。

使用方式和限制

如先前所述,單一決策樹狀圖的品質通常低於現代機器學習方法,例如隨機森林、漸層強化樹狀結構和類神經網路。不過,決策樹狀圖在下列情況下仍非常實用:

  • 這是一種簡單又便宜的基準,可用來評估更複雜的方法。
  • 在模型品質和可解釋性之間取得取捨。
  • 課程稍後會探討來解讀決策樹系模型。