【Python × 機械学習入門】決定木で売上を予測してみよう【初心者向け】

【Python × 機械学習入門】決定木で売上を予測してみよう【初心者向け】

Pythonの機械学習ライブラリ「scikit-learn」を使って、決定木による売上予測モデルを初心者向けに構築する方法を解説します。

この記事の対象読者と前提知識

  • Pythonの基礎文法が分かる方(ライブラリ未経験でもOK)
  • 実務に機械学習を取り入れたい方
  • ChatGPTなどの生成AIとの違いを体感したい方

決定木とは?アルゴリズムの基本

決定木(Decision Tree)は、条件分岐によって予測を行う機械学習アルゴリズムです。 データを「もし〜なら」というルールで枝分かれさせていくことで、最終的な予測結果(数値またはラベル)を導きます。

用途によって以下の2つに分類されます:

  • 回帰問題:数値を予測(例:売上、価格、気温など)
  • 分類問題:カテゴリを予測(例:合格 or 不合格、購入する or しない)

以下のような特徴があります:

  • 直感的で可視化しやすい:どの条件で分岐したかがツリー構造で見える
  • 前処理が少なくて済む:スケーリングや正規化が不要で、カテゴリ変数も扱いやすい
  • 過学習に注意:木が深くなりすぎると学習データに過剰適合しやすい

また、決定木を複数組み合わせたアンサンブル学習として、「ランダムフォレスト」や「勾配ブースティング決定木(GBDT)」などの手法も発展しています。 これらは決定木を基礎として、より高精度・高汎化性能なモデルを実現します。

初心者向け用語解説

用語意味
決定木(Decision Tree)条件に応じて分岐を繰り返し、最終的に予測を行う「木」構造のモデル。可視化が容易で直感的に理解できる。
特徴量(Feature)予測に使う変数や情報(例:月、来店回数など)。モデルの入力データ。
目的変数(Target / Label)モデルが予測したい値(例:購入金額)。出力となる「答え」に相当。
学習データ(Training Data)モデルを訓練するためのデータ。特徴量と目的変数のセット。
テストデータ(Test Data)学習後のモデルを評価するために使うデータ。モデルが未学習のデータで精度を検証。
バリデーションデータ(Validation Data)ハイパーパラメータ調整などに使う検証用データ。モデルの汎化性能を確認。
クロスバリデーション(Cross Validation)データを複数に分割して繰り返し検証する手法。過学習のリスクを減らす。
過学習(Overfitting)学習データにだけ精度が高く、未知データで性能が落ちる状態。
汎化性能(Generalization)未知のデータに対しても高精度を維持する力。モデルの実用性に直結。
ハイパーパラメータ(Hyperparameter)学習前に設定するパラメータ(例:木の深さ、分岐の最小サンプル数など)。
木の深さ(max_depth)決定木の階層の深さを制御するパラメータ。深すぎると過学習、浅すぎると学習不足に。
バギング(Bagging)複数のモデルを並列に学習し平均化する手法(例:ランダムフォレスト)。分散を抑えて安定した性能を得る。
ブースティング(Boosting)モデルを逐次的に重ねて学習し、誤差を減らしていく手法(例:XGBoost、LightGBM)。高精度だが学習に時間がかかる。
平均二乗誤差(MSE)誤差の2乗平均。大きな誤差をより重視。単位は元データと同じだが解釈しづらい。
平均絶対誤差(MAE)予測値と実測値の差の絶対値の平均。単位が直感的で、外れ値にやや弱い。
決定係数(R²)モデルがどれだけうまく目的変数を説明できているか(1に近いほど良い)。

Pythonで売上予測モデルを実装しよう

ここでは、決定木を使って「月」と「来店回数」から「購入金額(円)」を予測するモデルを構築します。以下のステップに従って、Pythonとscikit-learnを用いた機械学習の基本を体験しましょう。

ステップ1:ライブラリのインポート

まずは必要なライブラリを読み込みます。機械学習、評価、グラフ描画に必要なモジュールをすべてまとめておきましょう。

# データ操作と可視化
import pandas as pd
import matplotlib.pyplot as plt

# 機械学習のためのscikit-learnモジュール
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeRegressor, plot_tree
from sklearn.metrics import mean_squared_error, mean_absolute_error

ステップ2:データの読み込み

CSVファイルから売上データを読み込み、構造を確認します。

# CSVファイルをDataFrameとして読み込む
df = pd.read_csv("sales_data.csv")

# データの冒頭5行を表示して確認
print(df.head())

📌 出力例(例)

   月  来店回数  購入金額(円)
0  1    15    23000
1  2    20    25000
2  3    12    18000

ステップ3:特徴量と目的変数の分割

特徴量(説明変数)と目的変数(予測したい値)を分けます。

# 特徴量:モデルが学習に使う情報
X = df[["月", "来店回数"]]

# 目的変数:予測対象となる値
y = df["購入金額(円)"]

※「特徴量」「目的変数」の詳しい意味は用語解説を参照。

ステップ4:データ分割(訓練データとテストデータ)

学習に使うデータと、予測精度を検証するためのデータに分けます。一般的には8:2や7:3の比率が多いです。

# データ全体の20%をテスト用に確保
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

🔍 Tips:random_stateを固定すると再現性が保てます。

ステップ5:モデル構築と予測・評価

決定木モデルを構築し、テストデータで予測した結果を評価します。 この際、モデルの性能を調整するための「ハイパーパラメータ(事前に手動設定する変数)」を指定することが重要です。

# 決定木モデルの作成(max_depthを指定して過学習を防ぐ)
model = DecisionTreeRegressor(
    max_depth=4,            # 木の最大深さ:大きすぎると過学習、小さすぎると学習不足に
    min_samples_split=2,    # 分割に必要な最小サンプル数(デフォルト値)
    min_samples_leaf=1,     # 葉ノードに必要な最小サンプル数
    random_state=42         # 再現性確保のための乱数シード
)

# 学習データでモデルを訓練
model.fit(X_train, y_train)

# テストデータに対する予測
y_pred = model.predict(X_test)

# 精度評価(MSE, MAE)
print("平均二乗誤差 (MSE):", mean_squared_error(y_test, y_pred))
print("平均絶対誤差 (MAE):", mean_absolute_error(y_test, y_pred))

📘 よく使われるパラメータの解説

  • max_depth:木の深さの上限を指定。
    値が大きすぎるとデータに過剰に適合してしまい、汎化性能が低下(=過学習)する。
  • min_samples_split:ノードを分割するために必要な最小サンプル数。
    値を大きくすると、細かい分割が減りモデルが単純になる。
  • min_samples_leaf:葉ノード(予測の最終出力)に必要な最小サンプル数。
    ノイズの多い小さな枝を避けるのに有効。
  • random_state:同じ結果を再現したい場合に設定する乱数の種。

📌 出力例(例)

平均二乗誤差 (MSE): 5803200.0  
平均絶対誤差 (MAE): 1800.45

🔍 評価指標の補足:
MSE(平均二乗誤差)は大きな外れ値に敏感、MAE(平均絶対誤差)は直感的にズレを把握できる指標です。

ステップ6:モデル構造の可視化

学習済みの決定木を視覚的に表示して、「どんな条件でどう分岐しているか」を確認できます。

# 決定木の構造をグラフとして描画
plt.figure(figsize=(10, 6))
plot_tree(model, feature_names=["月", "来店回数"], filled=True)
plt.show()

🧠 ポイント:可視化された決定木では、どの特徴量が予測にどの程度影響しているかが一目で分かります。

よくあるエラーと注意点(トラブルを未然に防ぐために)

Pythonやscikit-learnを使って決定木モデルを作成する際に、初心者がつまずきやすいエラーや注意点を以下にまとめました。

日本語カラム名によるエラー

例:df["購入金額(円)"] のような日本語カラム名は、文字コードの違いや入力ミスの温床となりやすく、エラーを引き起こすことがあります。

解決策: カラム名は英語にリネームしましょう(例:price_yen)。

欠損値(NaN)による学習エラー

決定木は欠損値に対応していないため、fit() 実行時に ValueError が発生します。

解決策: df.dropna()df.fillna() を使って欠損を処理しましょう。

# 欠損行を削除
df = df.dropna()

# 平均値で補完(未来情報を含まないよう注意)
df = df.fillna(df.mean(numeric_only=True))

過学習(Overfitting)

決定木は柔軟性が高いため、学習データに過剰に適合し、未知データへの汎化性能が下がることがあります。

解決策: max_depthmin_samples_leaf を設定してモデルの複雑さを抑えます。

from sklearn.tree import DecisionTreeRegressor

# 木の深さを制限して過学習を抑制
model = DecisionTreeRegressor(max_depth=4)

特徴量にカテゴリ変数が含まれる場合

scikit-learnの決定木はカテゴリ(文字列)変数をそのまま扱えず、エラーになります。

解決策: pd.get_dummies() を使って数値に変換(ワンホットエンコーディング)します。

# 地域カラムをダミー変数化
df = pd.get_dummies(df, columns=["地域"])

データが少なすぎる

決定木は少量でも動作しますが、極端に少ない場合は予測精度が不安定になります。

解決策: cross_val_score() を使ってクロスバリデーションによりモデルの安定性を確認しましょう。

from sklearn.model_selection import cross_val_score

# 5分割のクロスバリデーションを実施
scores = cross_val_score(model, X, y, cv=5)
print("CVスコア平均:", scores.mean())

FAQ(よくある質問)

Q. データが少なくても機械学習はできますか?

はい、可能です。特に決定木は構造がシンプルで、少量データでも前処理が少なく安定して動作する点が特徴です。
ただし、学習データが少ない場合、過学習(Overfitting)のリスクが高くなります。
そのため、max_depthmin_samples_leaf などのハイパーパラメータの調整が非常に重要です。

少量データで安定性を確保するには、以下の手法も選択肢になります:

  • 回帰木(DecisionTreeRegressor):本記事で使用している手法。少量データでもツリー構造の解釈が明確。
  • Lasso回帰:スパース性の高い線形モデル。特徴量選択が内蔵されており、過学習を抑制。
  • K近傍法(KNN):非常に小さいデータセットでも動作。ただし、距離尺度の設計に注意。

参考:10〜100件規模のデータでは、Lassoや決定木が有力。1000件以上ある場合はランダムフォレストやLightGBMも選択肢になります。

Q. scikit-learn以外にも使えるライブラリはありますか?

はい。実務レベルでは、scikit-learnよりも性能・柔軟性・チューニング性に優れた以下のようなライブラリが使われることが多いです:

  • LightGBM(Microsoft製):
    大規模・高次元データに強く、カテゴリ変数の自動処理・GPU対応など多機能。
  • XGBoost(DMLC):
    コンペティションの定番。正則化と欠損値対応が強力で、高精度な予測が可能。
  • CatBoost(Yandex製):
    カテゴリ変数を明示的なエンコーディングなしに扱え、使いやすさと精度のバランスが良い。

補足:
・PoC(実証実験)や教育目的では scikit-learn が適しています。
・プロダクションやKPI最適化が目的の場合は LightGBMXGBoost が推奨されます。

Q. 決定木はブラックボックスではないのですか?

いいえ。決定木はホワイトボックス型モデルに分類され、分岐構造・条件・閾値が明示されているため、
出力結果の説明性(Explainability)が非常に高いのが特徴です。

Pythonでは、以下のようにツリー構造を可視化することができます:

from sklearn.tree import plot_tree
plot_tree(model, feature_names=["月", "来店回数"], filled=True)

さらに、モデル全体ではなく「予測に対してどの特徴量が影響したか」を知りたい場合は、以下のような手法が有効です:

  • SHAP値(SHapley Additive explanations)
    特徴量ごとの寄与度を個別の予測単位で示す。
  • Permutation Importance
    予測精度への影響で特徴量の重要度を測る。

補足:ホワイトボックス性が求められる金融・医療・法務などの業界で、決定木は依然として重要なポジションを占めています。

ChatGPTを使ってこの分析を依頼するには?(プロンプト例)

ChatGPTに以下のようなプロンプトを入力することで、決定木による売上予測のPythonコードを自動生成できます:


    「以下のCSVデータを使って、決定木で売上を予測するPythonコードを生成してください。
    特徴量は '月', '来店回数'、目的変数は '購入金額(円)' です。」
    

さらに、次のような指示を追加すると分析が深まります:

  • 「ランダムフォレストに変更して精度比較してください」
  • 「max_depthの最適値をグリッドサーチで探してください」
  • 「plot_treeで可視化してください」

決定木に関する理論・実装・応用をさらに深掘りしたい方のために、代表的な文献・チュートリアル・ライブラリ公式をまとめました。

次にやってみよう!

  • ランダムフォレストとの比較
  • 新しい特徴量の追加

関連手法との比較

決定木 vs ランダムフォレスト(ベンチマーク比較)

項目決定木ランダムフォレスト
モデルの構造単一の木多数の決定木のアンサンブル
精度中程度(過学習しやすい)高い(汎化性能が高い)
解釈性高い(分岐が明確)低め(全体のロジックが複雑)
学習時間短い長め
おすすめ用途教材・PoC実務分析・精度重視

ライセンスと転載について

転載は可能ですが、以下の条件を守ってください:

出典の明記(例:「出典:AI × Data Science by Shuu」)

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