📚 背景知識(読んでから問題へ)
Phase 2 で学んだ「ランダムフォレスト」との違いを軸に理解していきます。ランダムフォレストは バギング(Bagging):たくさんの木を独立に・並行して作り多数決を取る方式でした。勾配ブースティングは ブースティング(Boosting):木を順番に・直列に作り、前の木が間違えた部分を次の木が補強する方式です。
たとえるなら、バギングは「複数人が独立にテストを解いて多数決を取る」方式。ブースティングは「1人目の答案を先生が採点し、間違えた問題だけを2人目に重点的に解かせ、その答案をまた採点して3人目に…」を繰り返す方式です。
| 用語 | 直感的な意味 |
|---|---|
| 弱学習器(weak learner) | 単体では精度の低い浅い決定木。これを大量に積み重ねる |
| 残差(residual) | 予測値と正解値のズレ。次の木が学習するターゲット |
| 学習率(learning rate) | 各木の補正をどれだけ強く反映するかの調整弁 |
| アンサンブル(ensemble) | 複数の弱いモデルを組み合わせて1つの強いモデルにする総称 |
🔀 バギング(並行)vs ブースティング(直列)
木の作られ方が根本的に違う。この一言をまず覚える。
🎯 問題
問1: バギング vs ブースティングの違い
問2: 「残差を学習する」を具体例で説明する
| ステップ | 内容 |
|---|---|
| 目的変数 | 正解の家賃 = [10万円, 20万円, 30万円] |
| Step 0(初期予測) | 全データの平均で予測 → [20万円, 20万円, 20万円] |
| Step 1 | 残差(正解 − 予測)を計算する → [?, ?, ?] |
| Step 2 | 木1がこの残差を予測 → 仮に [-8万円, 1万円, 9万円]。学習率 0.5 で予測を更新すると? |
問3: なぜGBDTはTabularデータで強いのか
📊 残差が縮まっていく様子を可視化する
正解 30万円のデータ1件が、木を積み重ねるたびに予測へ近づく例。
予測値の推移(正解 = 30万円)
💡 ヒント
問1は「複数の職人が独立に作品を作って良いものを選ぶ(バギング)」と「1人の職人が下書き→添削→修正を繰り返して1つの作品を仕上げる(ブースティング)」の違いをイメージする。過学習の挙動は、バギングは木を増やしても比較的安定するが、ブースティングは増やしすぎると訓練データに寄りすぎる、という非対称性がポイント。
- 問2:
残差 = 正解 - 予測を素直に引き算するだけ - 問2: 更新式は
予測 = 元の予測 + 学習率 × 木の予測 - 問3: 「特徴量の型(数値・カテゴリ混在、スケールがバラバラ)」と「データ量」の2軸で考える
y_true = [10, 20, 30] # 万円 y_pred_step0 = [20, 20, 20] # 初期予測(平均) residual = [t - p for t, p in zip(y_true, y_pred_step0)] print("残差:", residual) tree1_pred = [-8, 1, 9] # 木1が予測した残差 learning_rate = 0.5 y_pred_step1 = [p0 + learning_rate * t1 for p0, t1 in zip(y_pred_step0, tree1_pred)] print("Step1後の予測:", y_pred_step1)
✅ 模範解答
問1: バギング vs ブースティングの違い
| 観点 | バギング(ランダムフォレスト) | ブースティング(GBDT) |
|---|---|---|
| 木の作り方 | 並行。各木は独立にランダムサンプリングされたデータで作られる | 直列。前の木の結果(残差)を見てから次の木を作る |
| 各木が学習する対象 | 元の目的変数そのもの(同じ問題を別々の角度から解く) | 前の木までの予測の残差(ズレ)。1本ごとに解くべき問題が変わる |
| 過学習への挙動 | 木を増やしても分散が下がり比較的安定(過学習しにくい) | 木を増やしすぎると訓練データのノイズまで拾い過学習しやすい(early stopping が重要) |
問2: 「残差を学習する」の計算
1. Step 1 の残差:
残差 = 正解 - 予測
= [10-20, 20-20, 30-20]
= [-10万円, 0万円, +10万円]
2. Step 2 の更新後の予測(学習率0.5):
新しい予測 = 元の予測 + 学習率 × 木1の予測
1件目 = 20 + 0.5 × (-8) = 16万円
2件目 = 20 + 0.5 × 1 = 20.5万円
3件目 = 20 + 0.5 × 9 = 24.5万円
→ 更新後の予測 = [16万円, 20.5万円, 24.5万円]
(正解 [10, 20, 30] に少しずつ近づいている)
問3: なぜGBDTはTabularデータで強いのか
| # | 理由 | 説明 |
|---|---|---|
| 1 | 特徴量の前処理がほぼ不要 | 決定木は「値の大小で分岐する」だけなので、数値のスケール差を気にせず、正規化も不要。カテゴリ変数もLightGBM/CatBoostならほぼそのまま扱える |
| 2 | 中規模データでも強く、学習が高速 | ニューラルネットは大量データと長い学習時間で真価を発揮するが、GBDTは数千〜数百万行でも少ない試行回数で高精度が出やすく、限られた時間内の試行錯誤に向く |
(補足: 特徴量同士の非線形な組み合わせや、欠損値・外れ値への頑健性も理由に挙げられる)
🪜 Step-by-Step 解説
1バギングとブースティングを対比で覚える
ランダムフォレストは「並列・独立」、GBDTは「直列・依存」。この一言をまず暗記する。
バギング: 木1 ─┐
木2 ─┼─ 多数決/平均 → 最終予測
木3 ─┘
(3本は互いに無関係。同時に作れる)
ブースティング: 木1 → 残差計算 → 木2 → 残差計算 → 木3 → ... → 最終予測
(木2は木1の結果を知っている。順番が絶対に必要)
2残差計算を手を動かして確認する
Step 0(平均で予測)→ Step 1(残差計算)→ Step 2(木で残差を予測し反映)の3ステップを、実際に電卓で計算してみることが重要。
y_true = [10, 20, 30] y_pred_step0 = [sum(y_true) / len(y_true)] * 3 # [20, 20, 20] residual = [t - p for t, p in zip(y_true, y_pred_step0)] # [-10, 0, 10]
n_estimators, learning_rate)の意味が直感的に分かる。3学習率と木の本数はトレードオフ
学習率 大(例: 1.0) → 少ない木の本数で収束するが、過学習しやすい 学習率 小(例: 0.01) → 収束に多くの木が必要だが、慎重で汎化しやすい
learning_rate と n_estimators のセット調整として学ぶ。🧮 数学・統計の補足(文系向け)
身近な例: ダーツの狙い直し
1投目が的の中心から左に10cmずれた。2投目は「右に少し」狙いを調整する。3投目はさらに微調整する…。これを何十投も繰り返すと、平均してほぼ中心に当たるようになる。GBDTの「木を1本ずつ追加する」プロセスは、まさにこの投げるたびに狙いを補正していく動き。
もし数式を見たら
Fm(x) = Fm-1(x) + η · hm(x)
「m本目までの予測 = (m-1本目までの予測) + (学習率 η) × (m本目の木が予測した補正量)」を数学的に書いたもの。問2でやった計算そのもの。
🏆 Kaggleでの実践的な使い方
よく使われるコンペカテゴリ: ☑ 表形式データ(Tabular) / ☐ 自然言語処理(NLP) / ☐ 画像認識(CV) / ☑ 時系列(Time Series)
Kaggleの Tabular Playground Series や House Prices、多くの Featured コンペで、上位解法の大半が XGBoost / LightGBM / CatBoost のアンサンブルを核にしている。特に「特徴量エンジニアリングの効果を素早く検証したい」場面では、ニューラルネットより学習が速いGBDTが実験サイクルを回しやすく、Kagglerの主力ツールになっている。Phase 4 ではこの3ライブラリを順番に実装しながら、パラメータチューニング(Optuna)・アンサンブルへと発展させる。
⚠️ よくある誤解・ミス
| 誤解・ミス | なぜ起こるか | 正しい理解 |
|---|---|---|
| ランダムフォレストとGBDTを同じものと思う | どちらも「決定木の集まり」に見える | 木の作り方(並行 vs 直列)と学習対象(元データ vs 残差)が根本的に異なる |
| 木の本数を増やせば増やすほど良いと思う | バギングの感覚を持ち込む | GBDTは増やしすぎると過学習。early stoppingやCVでの本数決定が必須 |
| 学習率は小さいほど無条件に良いと思う | 「慎重=正義」という直感 | 学習率を下げるほど必要な木の本数が増え、学習時間が伸びるトレードオフがある |
| 勾配ブースティングは分類にしか使えないと思う | ロジスティック回帰との連想 | 回帰・分類どちらにも使える。損失関数を変えるだけで両対応 |
🚀 次のステップ
- 発展: 問2の残差計算を Step 3・Step 4 まで手動で続けてみて、予測値がどのように正解へ収束していくかを観察する
- 次回予告: Day 091「XGBoost① 実装」 — 今日学んだ直感を、実際に
xgboostライブラリでコードとして動かす
📝 自己評価(解いた後に記入)
自分の回答・気づき・メモ: