DecisionTreeRegressorを使いこなす!Scikit-learnによる決定木回帰の実装とパラメータチューニング

Python

PythonのScikit-learnライブラリの中でも、決定木はモデルの内部構造がわかりやすく、非常に人気の高いアルゴリズムです。特に、数値を予測する回帰タスクで用いられるDecisionTreeRegressorは、その手軽さから多くの場面で利用されます。

しかし、デフォルト設定のまま使うだけでは、その真価を発揮することはできません。決定木は「過学習」という大きな課題を抱えており、これを乗り越えてこそ「使いこなす」ことができるのです。

この記事を読めば、以下のスキルが身につきます。

  • DecisionTreeRegressorの基本的な実装フローを理解できる
  • なぜパラメータチューニングが重要なのか(過学習の概念)を理解できる
  • max_depthなどの主要パラメータを使ったチューニング方法を具体的に学べる
  • 学習済みモデルを可視化し、モデルを深く解釈できるようになる

DecisionTreeRegressorを使ってみたけど、精度が出ない」「過学習の対策方法がわからない」といった悩みを持つ方は、ぜひ本記事でその解決策を学んでください。

DecisionTreeRegressorの基本と課題

まずは、DecisionTreeRegressorの基本的な仕組みと、なぜパラメータチューニングが不可欠なのかについておさらいします。

決定木回帰の仕組み(おさらい)

決定木回帰は、非常にシンプルなルールで予測を行います。手元のデータをある条件(質問)で次々と2つに分割していき、これ以上分割できなくなった領域(葉ノード)に属するデータの平均値を、その領域の予測値とします。

この「質問」と「分割」を繰り返すことで、データ空間内に樹木のような構造(ツリーモデル)を作り上げていくのが特徴です。

なぜパラメータチューニングが必要か? – 過学習の罠

このシンプルな仕組みには大きな落とし穴があります。それは**過学習(Overfitting)**です。

パラメータを何も設定しないDecisionTreeRegressorは、訓練データを完璧に説明しようとして、非常に複雑で深い木を生成します。その結果、訓練データに対しては驚くほど高い精度を出しますが、ノイズや個別のデータが持つ偶然のパターンまで学習してしまいます。

このようなモデルは、未知の新しいデータ(テストデータ)に対しては全く対応できず、予測精度が著しく低下します。これが「過学習の罠」です。この罠を回避し、未知のデータにも対応できる汎化性能の高いモデルを作ることこそが、パラメータチューニングの最大の目的なのです。

実践!DecisionTreeRegressorの実装フロー

それでは、実際にコードを見ながら実装の基本フローを確認しましょう。

開発環境とライブラリ

scikit-learn, numpy, matplotlibを使用します。インストールされていない場合は、pipでインストールしてください。

import numpy as np
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn import tree

データ準備から学習・予測まで

ここでは、ある製品の広告費 X と売上 y の関係を模したシンプルなデータセットで実装を進めます。

# サンプルデータの生成
# 広告費 (特徴量 X)
X = np.arange(1, 21, 1).reshape(-1, 1) * 10
# 売上 (目的変数 y)
y = np.array([30, 35, 33, 45, 55, 58, 62, 60, 68, 75, 
              80, 82, 85, 83, 88, 92, 95, 99, 98, 105])

# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# デフォルト設定でモデルを学習
tree_default = DecisionTreeRegressor(random_state=42)
tree_default.fit(X_train, y_train)

# 予測と評価
y_pred_default = tree_default.predict(X_test)
score_default = tree_default.score(X_test, y_test)

print(f"デフォルトモデルのスコア (R^2): {score_default:.4f}")

まずはベースとなるモデルを作成しました。ここからパラメータチューニングを行い、精度がどう変化するかを見ていきましょう。

過学習を防ぐ!主要パラメータチューニング詳解

ここがこの記事の核心です。過学習を効果的に抑制し、モデルを使いこなすための3つの重要なパラメータを解説します。

max_depth:木の「深さ」を制御する最重要パラメータ

max_depthは、文字通り決定木の最大の深さを制限するパラメータです。これを設定しないと(デフォルトはNone)、ノードが不純でなくなるまで無限に分割を続け、過学習の直接的な原因となります。

# 木の深さを3に制限してモデルを学習
tree_tuned = DecisionTreeRegressor(max_depth=3, random_state=42)
tree_tuned.fit(X_train, y_train)

# 予測と評価
y_pred_tuned = tree_tuned.predict(X_test)
score_tuned = tree_tuned.score(X_test, y_test)

print(f"チューニング後 (max_depth=3) のスコア (R^2): {score_tuned:.4f}")

多くの場合、max_depthに適切な値を設定するだけで、デフォルト状態よりも汎化性能が向上します。深すぎず浅すぎない、最適な深さを見つけることが重要です。

min_samples_leaf & min_samples_split:データの「細かさ」を制御する

これらのパラメータは、木の枝分かれのルールをより厳しくすることで、モデルの複雑化を抑制します。

  • min_samples_leaf: 1つの葉ノード(木の末端)に必要な最小サンプル数を指定します。例えばmin_samples_leaf=5とすると、5人未満のデータしか含まれないような極端なグループ分けを防ぎます。これにより、外れ値などの細かいノイズにモデルが過剰に反応するのを防ぎます。
  • min_samples_split: あるノードをさらに分割するために必要な最小サンプル数を指定します。例えばmin_samples_split=10とすると、ノードに10人以上のデータがない限り、それ以上分割しなくなります。

これらのパラメータを組み合わせることで、より頑健なモデルを構築できます。

# 複数のパラメータを組み合わせてチューニング
tree_tuned_adv = DecisionTreeRegressor(max_depth=4, 
                                     min_samples_split=5, 
                                     min_samples_leaf=3, 
                                     random_state=42)
tree_tuned_adv.fit(X_train, y_train)
score_tuned_adv = tree_tuned_adv.score(X_test, y_test)

print(f"複合チューニング後のスコア (R^2): {score_tuned_adv:.4f}")

モデルを「見て」理解する – 可視化テクニック

パラメータチューニングの効果は、スコアだけでなく、木の構造を直接見ることでより深く理解できます。

plot_treeで予測ロジックを可視化する

sklearn.tree.plot_treeを使えば、学習したモデルの構造を簡単に可視化できます。先ほどmax_depth=3でチューニングしたモデルを見てみましょう。

# 可視化
plt.figure(figsize=(18, 10))
tree.plot_tree(tree_tuned, 
               feature_names=['AD Cost'],
               filled=True,
               rounded=True,
               fontsize=12)
plt.title("Tuned Decision Tree (max_depth=3)")
plt.show()

この図を分析することで、モデルが「広告費がいくら以下か」という条件でデータを分割し、最終的にどのような予測値(value)を導き出しているかが一目瞭然となります。チューニングによって、木が適切に「剪定(Pruning)」され、シンプルで解釈しやすい構造になっていることが確認できます。

feature_importances_で特徴量の貢献度を知る

どの特徴量が予測に大きく貢献しているかを数値で確認することもできます。

# 特徴量の重要度
importances = tree_tuned.feature_importances_

print(f"特徴量 'AD Cost' の重要度: {importances[0]:.4f}")

特徴量が複数ある場合、この重要度を参考にすることで、どの変数がビジネス上重要なのかといったインサイトを得るきっかけにもなります。

まとめ:DecisionTreeRegressorを使いこなすために

今回は、DecisionTreeRegressorを単に使うだけでなく、「使いこなす」ためのパラメータチューニングと可視化の方法について深掘りしました。

使いこなしのポイント:

  • DecisionTreeRegressor過学習しやすいことを常に意識する。
  • max_depth は過学習抑制の第一歩であり、最も重要なパラメータの一つ。
  • min_samples_leafmin_samples_split で分割ルールを厳しくし、モデルの複雑さを制御する。
  • 可視化はチューニングの効果を確認し、モデルの挙動を深く理解するための強力な武器となる。

これらのテクニックを駆使してモデルの性能を最大限に引き出すことこそ、DecisionTreeRegressorを真に使いこなすということです。

ここからさらにステップアップするには、最適なパラメータを自動で探索するグリッドサーチなどの手法や、決定木を複数組み合わせることで精度を向上させたランダムフォレストや勾配ブースティングといったアルゴリズムを学んでいくと良いでしょう。

コメント

タイトルとURLをコピーしました