ディシジョン ツリーを作成する

このユニットでは、YDF(Yggdrasil デシジョン フォレスト)ライブラリを使用して、ディシジョン ツリーをトレーニングして解釈します。

このユニットは、🧭 YDF スタートガイドのチュートリアルを参考にしています。

準備

データセットを調べる前に、次のことを行います。

  1. 新しい Colab ノートブックを作成します。
  2. 新しい Colab ノートブックに次のコード行を配置して実行し、YDF ライブラリをインストールします。
    !pip install ydf -U
  3. 次のライブラリをインポートします。
    import ydf
    import numpy as np
    import pandas as pd

Palmer Penguins データセット

この Colab では、 Palmer Penguins データセットを使用します。このデータセットには、次の 3 種類のペンギンのサイズ測定値が含まれています。

  • 顎ストラップ
  • Gentoo
  • Adelie

これは分類問題です。目標は、Palmer's Penguins データセットのデータに基づいてペンギンの種を予測することです。ペンギンは次のとおりです。

3 種類のペンギン。

図 16. 3 種類のペンギン。@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 つの例

island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g 性別
撮影していない 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 の場合、異なる種である可能性

Likelihood
Adelie(赤) 8%
Gentoo(青) 58%
ヒゲペンギン(緑) 36%

 

表 5. bill_depth_mm < 42.3 の場合、異なる種である可能性

Likelihood
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 個のサンプルのみ)ため、精度の推定にノイズが混入しているということです。

実際には、このような小さなデータセットでは、より正確な評価指標値を計算できるため、クロス バリデーションを使用することをおすすめします。ただし、この例では、単純にするため、トレーニングとテストを続行します。

モデルのハイパーパラメータを改善する

このモデルは、デフォルトのハイパーパラメータ値でトレーニングされた単一のディシジョン ツリーです。より正確な予測を取得するには、次の方法があります。

  1. ランダム フォレスト勾配ブーストツリーモデルなど、より強力な学習ツールを使用します。これらの学習アルゴリズムについては、次のページで説明します。

  2. 観察と直感を使用してハイパーパラメータを最適化します。モデルの改善ガイドが役に立ちます。

  3. ハイパーパラメータ チューニングを使用して、考えられる多数のハイパーパラメータを自動的にテストします。

まだランダム フォレストと勾配ブースト ツリー アルゴリズムを確認しておらず、サンプル数が少すぎてハイパーパラメータの自動チューニングを行うことができないため、モデルを手動で改善します。

上記のディシジョン ツリーは小さく、61 個のサンプルを含むリーフには、アデリーとチンストラップのラベルが混在しています。アルゴリズムがこのリーフをさらに分割しなかったのはなぜですか?理由は 2 つ考えられます。

  • リーフあたりの最小サンプル数(デフォルトは 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

ランダム フォレストの精度は、単純なツリーよりも優れています。理由については、次のページで説明します。

使用と制限

前述のように、単一のデシジョン ツリーは、ランダム フォレスト、勾配ブースト ツリー、ニューラル ネットワークなどの最新の ML 手法よりも品質が低いことがよくあります。ただし、次のような場合は、決定木が有用です。

  • より複雑なアプローチを評価するためのシンプルで低コストのベースラインとして。
  • モデルの品質と解釈可能性の間でトレードオフがある場合。
  • デシジョン フォレスト モデルの解釈の代用として使用します。このコースでは後で説明します。