非IT企業に勤める中年サラリーマンのIT日記

非IT企業でしかもITとは全く関係ない部署にいる中年エンジニア。唯一の趣味がプログラミングという”自称”プログラマー。

【Python】決定木の最適な深さが毎回変わる理由とその対処法

   

決定木を使った機械学習モデルを構築する際に、最適なハイパーパラメータ(たとえば決定木の深さ)が複数回実行するたびに変わってしまう現象に悩んだことはありませんか?今回は、その理由と対処法について解説します。

実行コードの例

以下のコードでは、Irisデータセットを使ってGridSearchCVを用いて決定木の深さ(max_depth)の最適値を探索しています。

from sklearn.datasets import load_iris
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.tree import DecisionTreeClassifier

iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=123)

clf = DecisionTreeClassifier()
param_grid = {'max_depth': [3, 4, 5]}
cv = GridSearchCV(clf, param_grid=param_grid, cv=10)
cv.fit(X_train, y_train)

# 最適な深さを出力
print("最適な深さ:", cv.best_params_['max_depth'])
 

 

このコードを複数回実行すると、以下のようにGridSearchCVで選ばれる最適な深さが変わる場合があります。

$ python3 gridSearchCV.py 
最適な深さ: 3
$ python3 gridSearchCV.py 
最適な深さ: 4
$ python3 gridSearchCV.py 
最適な深さ: 3
$ python3 gridSearchCV.py 
最適な深さ: 4
$ python3 gridSearchCV.py 
最適な深さ: 4
$ python3 gridSearchCV.py 
最適な深さ: 3
 

 

最適な深さが変わる原因

交差検証の分割におけるランダム性

GridSearchCVでは、交差検証(クロスバリデーション)を使用してモデルの性能を評価します。この際、デフォルトではデータがランダムに分割されるため、異なる分割パターンが生成され、モデルの評価結果が変わる場合があります。これが最適なパラメータが変わる主な原因です。

小さいデータセットの影響

Irisデータセットのように小さいデータセットでは、交差検証でのデータ分割によるわずかな違いがモデルの性能に大きく影響を与えます。そのため、実行ごとに異なる最適値が選ばれる可能性があります。

決定木モデルのデータ変動への敏感性

決定木モデルはデータ分割の違いに敏感なアルゴリズムです。異なる分割によって異なる決定木が構築され、結果的に最適な深さが変わる場合があります。

 

対処法:ランダム性を固定する

この問題を解決するためには、GridSearchCVのクロスバリデーションにおけるランダム性を固定する必要があります。具体的には、StratifiedKFoldを使用してランダム性を制御します。

以下のコードはその例です。

from sklearn.datasets import load_iris
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import StratifiedKFold

iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=123)

cv_strategy = StratifiedKFold(n_splits=10, shuffle=True, random_state=123)
clf = DecisionTreeClassifier()
param_grid = {'max_depth': [3, 4, 5]}
cv = GridSearchCV(clf, param_grid=param_grid, cv=cv_strategy)
cv.fit(X_train, y_train)

# 最適な深さを出力
print("最適な深さ:", cv.best_params_['max_depth'])
 

 

このようにすることで、トレーニングデータの分割方法を一定にし、結果を安定させることができます。

$ python3 gridSearchCV.py 
最適な深さ: 5
$ python3 gridSearchCV.py 
最適な深さ: 5
$ python3 gridSearchCV.py 
最適な深さ: 5
$ python3 gridSearchCV.py 
最適な深さ: 5
$ python3 gridSearchCV.py 
最適な深さ: 5
 

 

まとめ

決定木モデルのハイパーパラメータ最適化で毎回異なる結果が得られる理由は、主に交差検証のランダム性にあります。random_stateを適切に設定することで、結果の再現性を高めることが可能です。再現性を確保したコードを作成し安定したモデリングを目指しましょう!

 

スポンサーリンク

 - Python