論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
ランダムフォレスト
Random Forest (RF)
多数の決定木をブートストラップサンプリングで学習させ、結果を平均/多数決するアンサンブル手法。
機械学習RFRandom Forestランダムフォレスト

🔖 キーワード索引

random forest」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「random forest」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

random forest統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「random forest の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

たくさんの決定木(判断の木)が集まった森のような手法です。

データの予測をより正確にするために使います。

スマホのアプリで好みの商品を当てるような仕組みです。

この章では、この手法の結論を短くまとめます。

📖 包括的解説 — この概念を完全マスター

📍 学習の3ステップ

  1. 定義を理解する:この概念は何か? 数式や条件を確認
  2. 具体例を見る:実データ(SSDSE 等)で計算してみる
  3. 応用する:自分のデータに適用、 結果を解釈

🔧 Python実装パターン

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 L322101(食料費(二人以上の世帯)) L322102(住居費(二人以上の世帯)) L322108(教育費(二人以上の世帯)) 北海道 74,341 26,730 6,911 東京都 97,776 26,457 24,160 沖縄県 73,453 27,521 6,356 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 基本パターン
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns

# データ読み込み(1 行目=英字コード, 2 行目=日本語名なので skiprows=[1])
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])

# 基本統計量
df.describe()

# 可視化
sns.pairplot(df[['L322101', 'L322108', 'L322102']])  # 食料/教育/住居
plt.show()
📥 入力例: data/raw/SSDSE-B-2026.csv X: 47 都道府県 × 複数変数 y: 目的変数
📤 このブロックは標準出力には何も出さない
💬 読み方: 木の数 n_estimators は多いほど安定(100-500 が標準)。 max_depth で過学習を制御。 feature_importances_ で変数選択ができる。 OOB score は CV 不要の汎化性能推定。

📚 ランダムフォレストの概念マップでの位置

ランダムフォレストは決定木を多数 (典型 100〜500 本) 並べたバギング系のアンサンブル学習。 上位概念はアンサンブル、 並列概念は単一決定木 / Extra Trees / Bagging (ブートストラップ集約)、 派生概念は勾配ブースティング (XGBoost, LightGBM, CatBoost)、 競合は SVM / ロジスティック回帰。 「列のサブセット (max_features) と行のサブセット (bootstrap) で木を脱相関し、 多数決 / 平均で集約」が中核アイデア。

🎯 SSDSE-B-2026 でランダムフォレストを試す

47 都道府県の社会経済データで、 RF の標準ワークフロー (前処理 → 学習 → 重要度 → OOB) を一通り体験する。

💡 ランダムフォレストでよく使うコマンド集

機能 Python (scikit-learn) 補足
分類器RandomForestClassifier()criterion='gini' or 'entropy'
回帰器RandomForestRegressor()criterion='squared_error'
OOB スコアRF(oob_score=True).oob_score_bootstrap=True が必須
Gini 重要度model.feature_importances_高カーディナリティを過大評価
Permutation 重要度sklearn.inspection.permutation_importance()Gini の偏りを回避
SHAP 重要度shap.TreeExplainer(model).shap_values(X)個別予測の説明にも使える
木の可視化sklearn.tree.plot_tree(model.estimators_[0])深い木は読めないので max_depth=3 推奨

🚧 ランダムフォレストの落とし穴と対策

📊 ランダムフォレストの結果報告フォーマット

🌐 ランダムフォレストが活きる分野

🎓 ランダムフォレストをさらに学ぶための文献

🔗 ランダムフォレストを理解するための関連用語ネットワーク

RF は「決定木」「アンサンブル」「特徴量重要度」「ハイパーパラメータ調整」「モデル説明可能性 (XAI)」が交差する位置にある。 単独で理解しようとせず、 周辺の概念を辿りながら学ぶ。

ランダムフォレストを学ぶ上で押さえたい概念グループ

グループ RF と関連の深い概念
基礎 (1 本の木)決定木 (CART)Gini 不純度、 エントロピー、 情報利得
アンサンブル戦略Bagging、 Boosting、 Stacking、 Voting
サンプリングブートストラップ、 Out-of-Bag、 Subsampling
列のランダム化max_features (√p, log2(p))、 Extra Trees の閾値ランダム化
並列・後継モデルGradient Boosting、 XGBoost、 LightGBM、 CatBoost
汎化性能評価OOB スコア、 k-fold CV、 hold-out
重要度の指標Gini 重要度、 Permutation 重要度、 SHAP 値、 LIME
バイアス・バリアンスバリアンス削減、 木間相関、 偏りと分散のトレードオフ
不均衡データclass_weight、 SMOTE、 BalancedRandomForest
RF 派生Isolation Forest (異常検知)、 quantile random forest (分位点予測)

ランダムフォレストを中心とした学習順序の推奨

  1. 決定木 (CART) を 1 本理解する: Gini 分割と max_depth の役割
  2. バギングを理解する: ブートストラップ標本 + 平均で分散が下がる仕組み
  3. RF = バギング + 列のランダム化、 と統合する
  4. OOB スコアで CV 無しに汎化性能を推定する
  5. feature_importances_ (Gini) → Permutation → SHAP と段階的に
  6. n_estimators, max_depth, max_features の 3 つだけで GridSearchCV
  7. 勾配ブースティング (XGBoost / LightGBM) との比較で長所短所を整理

📝 ランダムフォレストの実践練習 — SSDSE-B-2026

初級課題 (基本ワークフロー)

  1. 47 都道府県データを 6:4 に分割、 RF で平均寿命を回帰
  2. n_estimators を 10, 100, 500 と変えて RMSE の変化を確認
  3. model.feature_importances_ を棒グラフで可視化、 top-5 を抽出
  4. oob_score=True にして OOB R² と test R² がどれくらい近いか確認

中級課題 (チューニングと重要度)

  1. GridSearchCV で max_depth ∈ {3, 5, 8, None}, max_features ∈ {sqrt, log2, 0.5} を探索
  2. permutation_importance() で重要度を再計算、 Gini と順位がどう変わるか比較
  3. SHAP の summary plot を描き、 影響の方向 (正/負) を確認
  4. 個別の県 (例: 東京・沖縄) の SHAP force plot を描き、 予測根拠を説明

上級課題 (高度な応用)

  1. 分類タスクに切替: 「人口減少県」二値分類で、 class_weight='balanced' の効果を ROC-AUC で評価
  2. Extra Trees, XGBoost, LightGBM と RF を同じデータで比較し、 CV スコアを表に
  3. BalancedRandomForestClassifier (imblearn) で不均衡データの性能改善
  4. quantile random forest で予測区間 (10%, 50%, 90% 分位点) を出し、 単一点予測との差を可視化

📍 あなたが今見ているもの

🍰 まずはやさしく

多くの決定木を組み合わせて使う分析の手法です。

複雑なデータから正しい答えを導き出すために使います。

都道府県のデータを使って分析する時に役立ちます。

ここでは、この用語がどこで使われるかを説明します。

論文中に 「ランダムフォレスト」として登場する用語。

ランダムフォレスト とは:多数の決定木をブートストラップサンプリングで学習させ、結果を平均/多数決するアンサンブル手法。

本ページでは「random forest」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の実データを使った再現可能な学習を目指す。

「random forest」は統計・データサイエンスの体系における重要概念のひとつ。 本ページは「定義・直感・数式・実装・落とし穴・関連手法」の 6 視点で構成され、 各視点は独立して読めるが順序通り読むと体系的な理解が得られる。

🎨 直感で掴む — ランダムフォレスト の本質

🍰 まずはやさしく

みんなで相談して答えを決める多数決のようなものです。

一人の判断ミスを防いで、結果を安定させるために使います。

部活の試合で、チーム全員で作戦を考えるイメージです。

ここでは、仕組みを直感的に理解するための例を読みます。

ランダムフォレストは「たくさんの決定木を、 サンプルと特徴量をランダムに変えて作り、 平均する」アンサンブル手法。 個々の木は弱学習器でも、 集めると強い。 SSDSE-B-2026 で「都道府県の出生率」を 100 本の木で予測すると、 単一の決定木より分散が下がって安定する。

💡 ポイント:ランダムフォレスト を初めて学ぶときは「正確な定義」より「どんな問題を解くための道具か」を先に押さえてください。 数式は次の「📐 数式」セクションで丁寧に展開します。
📌 比喩がうまく刺さらないときは、 自分の身近な例(家計簿・スポーツの記録・成績表)に置き換えてみると理解が定着します。 SSDSE-B-2026 を電卓代わりに触りながら、 上の説明を再読すると効果的です。

🎨 概念図で押さえる — ランダムフォレストの仕組み

ランダムフォレストは「多数の決定木の多数決」。 ブートストラップ標本+特徴量サブセットで多様な木を作り、 平均(回帰)または多数決(分類)で予測する。

図 1: 多数決のアンサンブル

多数決アンサンブル図Tree 1: ATree 2: ATree 3: BTree N: A多数決→ クラス A"/>

→ 各木は弱学習器でも、 多数決により汎化性能が上がる。

図 2: ブートストラップ+特徴量サブセット

ブートストラップ図元データ N行標本1 (重複あり)特徴 √p ランダム標本2別の特徴サブセット標本K...K本の決定木"/>

→ 木同士の相関を下げることで、 集約の効果が最大化される。

図 3: バイアス・バリアンス分解

バイアスバリアンス図木の本数誤差バイアス (ほぼ一定)バリアンス (本数で減)合計誤差"/>

→ 木を増やすほどバリアンスが下がり、 合計誤差は飽和点まで減少する。

📝 練習問題 — 理解度チェック (5 問)

ランダムフォレスト (RF) について、 自分で説明できるか 5 問で確認しよう。 詰まった項目は該当章へ戻ること。 暗記でなく「なぜそうなるか」を 1-2 文で書けるかが目標。

Q1. ブートストラップ標本とは何か、 なぜ使うのか

ランダムフォレストの各決定木は「ブートストラップ標本」で訓練される。 これは何で、 なぜ全データを使わないのか。

答えの方向: ブートストラップ = 元データから「重複ありで」N 個をランダムサンプリング。 各木が見るデータが微妙に違うため、 木同士の相関が下がる。 多数決の効果は「木同士が無相関ほど大きい」ため、 ブートストラップは集約効果を最大化する仕組み。

Q2. なぜ各分岐で特徴量のサブセットだけを使うのか

分類なら √p、 回帰なら p/3 個の特徴量を各分岐でランダムに選ぶ。 強力な特徴量を毎回使った方がよさそうだが、 なぜわざわざ選択するのか。

答えの方向: もし全特徴量を使うと、 各木がほぼ同じ「最良の分岐」を選ぶため木同士が似通う (= 相関が高い)。 これでは集約してもバリアンスが下がらない。 ランダムに特徴を制限することで木のバリエーションを増やし、 アンサンブルの効果を高める。

Q3. 木の本数 n_estimators を増やすデメリットは

木の本数を増やしてもバイアスは増えず、 バリアンスは減るので「多ければ多いほどよい」と言われる。 ではデメリットは何か。

答えの方向: 計算コスト・メモリ使用量が線形に増える。 また、 ある本数を超えると性能向上は飽和し、 学習時間だけが伸びる。 実務では 100-500 本程度から CV で頭打ちを確認し、 そこを採用する。

Q4. OOB スコアとは何か

RF には「OOB (Out-of-Bag) スコア」という独自の指標がある。 これはなぜ "ほぼ無料の交差検証" と呼ばれるのか。

答えの方向: ブートストラップでサンプリングされる時、 各木の訓練には平均で全体の約 63% のデータしか使われず、 残り 37% は「Bag の外 (OOB)」になる。 これを当該木のテストデータとして使えるので、 別途 CV を回さなくても汎化性能を推定できる。

Q5. 特徴量重要度を因果として読んではいけない理由

RF の feature_importances_ は便利だが、 これを「この特徴量が結果を引き起こしている」と解釈してはいけない。 なぜか。

答えの方向: 重要度は「予測にどれだけ寄与するか」を示すだけで、 因果関係ではない。 例: アイスクリーム売上が水着売上を予測しても、 因果的には「気温」が両方を引き起こしている (交絡)。 因果効果を測りたいなら DiD、 IV、 RCT などの因果推論手法が必要。

→ 5 問とも自分の言葉で 2 文で説明できれば RF の理解は OK。 詰まった部分は「ブートストラップ」「特徴量ランダム選択」「OOB」セクションを再読しよう。

🚧 ランダムフォレストの前提条件・限界・誤解回避

RF は「とりあえずベースライン」として最も使われるが、 万能ではない。 前提・限界・誤解を整理する。

前提条件 1: 「弱学習器が独立」が成立するデータ構造

集約効果の理論は「木同士のエラーが独立」を仮定する。 完全に同じ特徴量しか効かないデータ (= 真の構造が 1 つしかない) では、 ブートストラップ + 特徴量サブセットを使っても木同士が似てしまい、 集約効果が薄い。

前提条件 2: 一定以上のサンプル数

各木がブートストラップ標本で学習するので、 元データが極端に少ない (n < 50) と、 各木の学習データの質が悪化する。 小規模データでは線形モデル + 正則化や交差検証で慎重に評価する方が安全。

限界 1: 外挿に弱い

RF (および決定木) は訓練データの「葉ノード代表値」で予測する。 訓練データの範囲外 (例: 訓練時に最高温度 35 度しか見ていないのに 40 度を予測しようとする) では、 葉ノードの値で頭打ちになる。 時系列の外挿、 トレンド予測などは線形回帰や GAM の方が向く。

限界 2: スパース高次元データでは勾配ブースティングに劣る

RF は「並列」のアンサンブル。 一方 XGBoost/LightGBM は「逐次」で前回の誤差を学習する。 構造化データのコンペでは XGBoost/LightGBM が RF を上回ることが多い。 ただし RF は OOB スコアとハイパーパラメータの少なさで実装が楽。

よくある誤解 1: 「RF はハイパーパラメータが不要」

「デフォルトで動く」は確かだが、 max_depth、 min_samples_leaf、 max_features は性能に大きく影響する。 特に max_depth を制限しないとメモリと過学習の問題が出る。 必ず CV でチューニングする。

よくある誤解 2: 「特徴量重要度 = 因果効果」

Q5 で見たとおり、 重要度は「予測寄与」であって因果ではない (相関と因果)。 また、 RF の Gini importance (ジニ不純度の減少量ベース) はカーディナリティの高い特徴量 (連続値) を過大評価する傾向があり、 さらに相関の強い特徴量同士では重要度が分散して両方とも低く見える点にも注意。 Permutation importanceSHAP を併用して頑健に評価する。

よくある誤解 3: 「木の本数を増やせば過学習が起きる」

直感に反して、 木の本数を増やしても過学習は基本的に起きない (バリアンスが減るだけ)。 過学習を起こす主因は max_depth の深さや個別木のサイズ。 「木が多いと過学習」と勘違いして本数を絞ると、 単にバリアンスが下がりきらない弱いモデルになる。

→ RF は「弱学習器の独立性 + 多数決」が成立するように設計するモデル。 集約効果が出ないなら、 特徴量設計や手法選択を見直すサイン。 XGBoost/LightGBM との比較は必ず行う。

🎮 触って理解する

2 次元・2 クラスの分類データに対して、 1 本の決定木(左)と ランダムフォレスト(右)の決定境界をその場で学習・描画します。 木の学習はジニ不純度による情報利得で分割点を選ぶ簡易 CART を実装しています(近似ではなく実際に木を育てています)。 スライダーで 木の本数 n を増やすと、 1 本の木のギザギザした階段状の境界が、 多数の木の平均によって滑らかな確率グラデーションへと均されていく様子(=バギングによる分散低減)を体感できます。

学習データ 120 点 / 別に用意したテストデータで精度を測定。 各木はブートストラップ標本 + 分割ごとに 1 特徴をランダム選択(max_features='sqrt')。 左の単一木は全データ・全特徴で学習した比較用です。

テスト精度の改善幅(フォレスト − 単一木)
+0.0 pt
n を増やすと分散が減り、境界が安定します
🌳 単一の決定木(1本)
テスト精度:
階段状(ギザギザ)の境界
🌲 ランダムフォレスト(30本)
テスト精度:
平均化された滑らかな確率境界

背景色 = 予測クラス(青=クラス0 / 赤=クラス1)。 右図は色の濃淡が「何本の木がそのクラスに投票したか(確率)」を表し、境界付近ほど中間色になります。 ● は学習データ点です。

🧭 もっと深く理解する

💡 直感: なぜ平均すると良くなるのか

1 本の木は訓練データのわずかな違いで境界が大きく変わる高バリアンスな弱学習器です。 だが各木の誤差がある程度独立していれば、 多数の木で多数決/平均を取ると誤差が打ち消し合い、 予測の分散が 1/n 近くまで低下します(バイアスはほぼ不変)。 スライダーの n を 1 → 60 と動かすと、 右図の確率グラデーションが滑らかに収束していくのが分散低減そのものです。 詳しくは バイアス-バリアンス分解ブートストラップ(バギング) を参照。

⚠️ よくある落とし穴
  • 解釈性の低下: 1 本なら「if 分割 > 閾値 …」と読める(決定木参照)が、 60 本の平均は人間が読めません。 SHAP や permutation importance で補います。
  • 木が相関すると効果が消える: すべての木が同じ強い特徴で分割すると誤差が独立にならず、 平均しても分散が減りません。 だから RF は分割ごとに特徴をランダムに絞る(max_features)。 サンプリング率を 100% にしても、 特徴サブサンプリングが効いている点に注目。
  • 深さの取り違え: 木の本数を増やしても過学習は基本起きません。 過学習は max_depth を上げすぎたとき。 max_depth を 8、 n を 1 にして単一木の過度に細かい境界を確認してみてください(過学習)。
🚀 発展
  • 分割の中身: 各ノードは ジニ不純度 が最も下がる(=情報利得が最大の)しきい値を全候補から探索します。 このデモも同じ基準で分割しています。
  • 特徴量重要度: 各特徴が全木でどれだけ不純度を下げたかを合計すると 特徴量重要度(mean decrease in impurity)が得られます。 ただし高カーディナリティ変数に偏るため permutation importance との併用が定石。
  • 勾配ブースティングとの違い: RF は木を並列・独立に育てて平均する(分散を下げる)のに対し、 勾配ブースティングは前の木の残差を次の木が逐次補正する(主にバイアスを下げる)。 高精度競争では GBM 系が上回ることが多い一方、 RF はチューニングに鈍感で頑健です。

📐 数式または定義 — ランダムフォレスト の形式的表現

🍰 まずはやさしく

たくさんの決定木の答えを平均したり、多数決したりする仕組みです。

計算で正しく予測値を出すために使います。

テストの点数を予想して、平均を出す計算に似ています。

ここでは、数式を使った厳密な定義について読みます。

直感で全体像を掴んだら、 次は厳密な定義を見ます。 数式は短いものでも、 「何を入力にして、 何を出力するのか」を意識して読むと早く慣れます。

【主定義: ランダムフォレストの予測($B$ 本の木の平均, 回帰)】
$$ \hat y_{RF}(x) = \frac{1}{B}\sum_{b=1}^{B} T_b(x; \Theta_b) $$
分類タスクでは多数決に置き換える: $\hat y_{RF}^{(\text{cls})}(x) = \mathrm{mode}\{T_b(x;\Theta_b)\}_{b=1}^{B}$。 ここで $T_b$ は CART (Classification And Regression Trees) で、 $\Theta_b$ は (i) ブートストラップ標本、 (ii) 各分割での候補特徴量サブセット (サイズ $m_{\text{try}}$) を表すランダム変数。
【別表現 1: バギングによる分散縮小】
$$ \mathrm{Var}[\hat y_{RF}(x)] = \rho\,\sigma^2 + \frac{1-\rho}{B}\sigma^2 $$
ここで $\sigma^2 = \mathrm{Var}[T_b(x;\Theta_b)]$ は単一木の分散、 $\rho = \mathrm{Corr}(T_b(x), T_{b'}(x))$ は木間相関 (Breiman 2001)。 $B \to \infty$ で第 2 項は消え、 残るのは $\rho\sigma^2$ — つまり木間相関を下げるほど分散が縮小する。 これが $m_{\text{try}} < p$ (各分割で特徴量を絞る) でランダム性を増やす理由。
【別表現 2: OOB 誤差 (Out-Of-Bag)】
$$ \widehat{\mathrm{Err}}_{\text{OOB}} = \frac{1}{n}\sum_{i=1}^{n} L\!\left(y_i,\; \frac{1}{|\mathcal{B}_i|}\sum_{b \in \mathcal{B}_i} T_b(x_i)\right),\quad \mathcal{B}_i = \{b : i \notin \text{boot}(b)\} $$
$\mathcal{B}_i$ はサンプル $i$ がブートストラップ標本に「選ばれなかった」木の集合 (期待値で $\approx 0.368B$ 本)。 OOB 誤差は cross-validation に近い「ほぼ不偏」な汎化誤差の推定量で、 追加計算なしで汎化性能を評価できる。 SSDSE-B-2026 (47 県) で $B=300$ なら 1 県あたり約 110 本が OOB として未使用。
【別表現 3: パラメータの推奨条件 ($m_{\text{try}}$ と木の深さ)】
$$ m_{\text{try}} = \begin{cases} \lfloor \sqrt{p} \rfloor & \text{(分類)} \\ \lfloor p/3 \rfloor & \text{(回帰)} \end{cases},\quad \min_{\text{leaf}} = \begin{cases} 1 & \text{(分類)} \\ 5 & \text{(回帰)} \end{cases} $$
Breiman (2001) の経験則。 SSDSE-B-2026 で特徴量数 $p=14$ なら、 回帰タスクでは $m_{\text{try}}=\lfloor 14/3 \rfloor=4$、 分類タスクでは $\lfloor\sqrt{14}\rfloor=3$。 木は通常剪定なし (max_depth=None) で bias を低く保ち、 分散はバギングで下げる戦略。
📚 数式が苦手な方へ:1 つの長い式を一度に理解しようとせず、 記号ごとに「言葉に翻訳」するのが王道。 紙に書き写してから、 自分の言葉で音読してみてください。 上記 4 式の対応関係は「主定義 → なぜ平均するのか (別表現 1) → どう評価するか (別表現 2) → パラメータの実用値 (別表現 3)」の順で読むと整理しやすい。

🔬 数式を言葉で読み解く — ランダムフォレスト の記号辞書

上の数式 $\hat{y}_{\text{RF}}(x) = \frac{1}{B}\sum_{b=1}^{B} T_b(x; \Theta_b)$ に出てくる各記号が何を表すかを、 言葉・読み方・SSDSE-B-2026 (47 都道府県データ) での具体例の 3 段で翻訳します。 1 つずつ自分の言葉で言い換えられるようになると、 論文や教科書のスピードが一気に上がります。

記号読み方意味SSDSE-B-2026 での例
$\hat{y}_{\text{RF}}(x)$わいハット アールエフ オブ エックスランダムフォレスト全体の予測値。 $B$ 本の木の予測の平均 (回帰) または多数決 (分類)。総人口・出生数・婚姻件数を入力 → 死亡数(A4200)の予測値
$B$ビー (number of trees)フォレスト内の木の本数。 大きいほど分散が減って安定する。 通常 100〜1000。$B=300$ で 47 都道府県を予測
$b$ビー (添字)何本目の木かを表すインデックス。 $b = 1, 2, \ldots, B$。$b=42$ なら 42 本目の木
$T_b(x; \Theta_b)$ティービー オブ エックス$b$ 番目の決定木 (CART)。 入力 $x$ に対して 1 つの予測値を返す。 ランダム性 $\Theta_b$ で異なる木になる。「総人口 > 500 万人なら死亡数 多」のような枝分かれ判定
$\Theta_b$シータビー$b$ 番目の木のランダム化要素。 (1) bootstrap サンプル (元データを復元抽出) と (2) 各分割で候補となる特徴量サブセット の 2 つから成る。47 件から 47 件を復元抽出 + 14 特徴量から $\lfloor\sqrt{14}\rfloor = 3$ 個ランダム選択
$x$エックス予測したい入力特徴量ベクトル。(人口, 所得, 高齢化率, …) の 14 次元ベクトル
$m_{\text{try}}$エムトライ各分割で候補にする特徴量の数。 回帰は $p/3$、 分類は $\sqrt{p}$ が経験則。$p=14$ → 分類は $\lfloor\sqrt{14}\rfloor = 3$、 回帰は $\lfloor 14/3 \rfloor = 4$
OOBオーオービー (Out-Of-Bag)bootstrap で「選ばれなかった」約 37% のサンプル。 各木に対する自然な検証セット。 cross-validation 不要。47 件中 約 17 件が OOB として未使用 → 精度評価に使う
$\frac{1}{B}\sum$B 分の 1 でシグマ$B$ 本の木の予測を平均する集約操作。 これにより分散が約 $1/B$ + 木間相関分に縮む (bias-variance 分解)。300 本の予測値の平均が最終予測
📌 数式の読み下し:「$B$ 本のランダム化された決定木 $T_b$ を作って、 それぞれの予測値 $T_b(x; \Theta_b)$ を平均すると、 ランダムフォレストの予測値 $\hat{y}_{\text{RF}}(x)$ になる」。 ポイントは ① 木ごとに 異なる bootstrap + feature subset で 多様性を作ること、 ② 平均で 分散縮小すること、 ③ OOB で 追加コストゼロで精度評価できることの 3 つです。

🧮 SSDSE-B を使ったランダムフォレストの実例

「合計特殊出生率(A4103)」を予測するランダムフォレスト回帰を、 SSDSE-B-2026 の 2023 年度データで構築します。

① データ準備と訓練

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1303(65歳以上人口) A4103(合計特殊出生率) A5101(転入者数(日本人移動者)) A9101(婚姻件数) 北海道 5,092,000 1,681,000 1.06 47,388 17,281 東京都 14,086,000 3,205,000 0.99 406,749 71,774 沖縄県 1,468,000 350,000 1.6 26,410 6,316 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split, cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df.rename(columns={'SSDSE-B-2026': '年度'})
d = df[df['年度'] == 2023].dropna()

features = ['A1303', 'A9101', 'B4101', 'A5101',  # 高齢人口/婚姻/気温/転入
            'L3221', 'A1101']  # 消費支出/総人口
X, y = d[features], d['A4103']  # 合計特殊出生率
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)

rf = RandomForestRegressor(n_estimators=500, max_depth=10,
                            min_samples_leaf=2, oob_score=True,
                            random_state=42, n_jobs=-1)
rf.fit(X_tr, y_tr)
print(f'Train R² = {rf.score(X_tr, y_tr):.3f}')
print(f'Test  R² = {rf.score(X_te, y_te):.3f}')
print(f'OOB   R² = {rf.oob_score_:.3f}')
📥 入力例: data/raw/SSDSE-B-2026.csv X: 47 都道府県 × 複数変数 y: 目的変数
📤 実行例(実測) Train R² = 0.887 Test R² = 0.272 OOB R² = 0.516
💬 読み方: 木の数 n_estimators は多いほど安定(100-500 が標準)。 max_depth で過学習を制御。 feature_importances_ で変数選択ができる。 OOB score は CV 不要の汎化性能推定。

実測結果:Train R² = 0.887, Test R² = 0.273, OOB R² = 0.517。 Train と Test の大きな差は過学習の兆候で、 合計特殊出生率のように変動幅の小さい比率は 47 県の小標本では予測が難しい。 OOB R²(0.517)はテスト R² より高く、 少標本ゆえ評価指標がばらつくことを示す。 単一の指標に頼らず OOB・テスト・CV を併記するのが安全。

② 特徴量重要度

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
1
2
3
4
import pandas as pd
imp = pd.Series(rf.feature_importances_, index=features).sort_values(ascending=False)
print(imp)
# L3221消費支出: 0.35, B4101気温: 0.27, A1303高齢人口: 0.17, A1101総人口: 0.09, A5101転入: 0.07, A9101婚姻: 0.05
📥 入力例: data/raw/SSDSE-B-2026.csv X: 47 都道府県 × 複数変数 y: 目的変数
📤 実行例(実測) L3221 0.352329 B4101 0.271613 A1303 0.165673 A1101 0.085538 A5101 0.070758 A9101 0.054089 dtype: float64
💬 読み方: 木の数 n_estimators は多いほど安定(100-500 が標準)。 max_depth で過学習を制御。 feature_importances_ で変数選択ができる。 OOB score は CV 不要の汎化性能推定。

「L3221 消費支出」が最重要(35%)、 次が「B4101 年平均気温」(27%)、 「A1303 高齢人口」(17%)と続く。 相関する人口系の変数間では重要度が分散するため、 次の Permutation Importance で頑健に確認する。

③ Permutation Importance(より頑健)

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
1
2
3
4
5
6
from sklearn.inspection import permutation_importance
r = permutation_importance(rf, X_te, y_te, n_repeats=30, random_state=42)
for i in r.importances_mean.argsort()[::-1]:
    print(f'{features[i]:20s}: {r.importances_mean[i]:.3f} ± {r.importances_std[i]:.3f}')
# テストセットで「変数をシャッフルしたら精度がどれだけ落ちるか」で測る
# 標準の feature_importances_ よりバイアスが少ない(特にカテゴリ・スケール違いに頑健)
📥 入力例: data/raw/SSDSE-B-2026.csv X: 47 都道府県 × 複数変数 y: 目的変数
📤 実行例(実測) B4101 : 0.156 ± 0.107 A1303 : 0.106 ± 0.062 A5101 : 0.102 ± 0.039 L3221 : 0.080 ± 0.123 A1101 : 0.068 ± 0.043 A9101 : 0.016 ± 0.025
💬 読み方: 木の数 n_estimators は多いほど安定(100-500 が標準)。 max_depth で過学習を制御。 feature_importances_ で変数選択ができる。 OOB score は CV 不要の汎化性能推定。

数式だけでは「分かった気になる」だけで終わりがち。 ここで SSDSE-B-2026(教育用標準データセット — 47 都道府県 × 100+ 指標、 2012-2023 年度)の実値を当てはめて、 ランダムフォレスト の挙動を電卓的に追体験します。

👉 計算例:SSDSE-B-2026(2023 年度)で「総人口(A1101)・高齢人口(A1303)・年平均気温(B4101)・婚姻件数(A9101)」から死亡数(A4200)を予測。 ランダムフォレスト(B=500, max_depth=5)で 5-fold CV の R²=0.942。 特徴量重要度の上位は「高齢人口 A1303(0.38)、 総人口 A1101(0.34)、 婚姻件数 A9101(0.28)」となり、 気温 B4101 はほぼ寄与しない(0.01)。

SSDSE-B-2026 は 統計センターの SSDSE 配布ページ から CSV を直接ダウンロードできます。 本サイトでは data/raw/SSDSE-B-2026.csv に配置している前提でコードを書いています。

🧮 数式に値を入れて手で計算する: アンサンブル分散減少

合成データで木数 B 別の予測分散減少を計算する。

Step 1: 仮定

単一木の分散 σ² = 4 木間相関 ρ = 0.3

Step 2: 公式

Var(平均) = ρσ² + (1-ρ)σ²/B B=10: 0.3·4 + 0.7·4/10 = 1.2 + 0.28 = 1.48 B=100: 1.2 + 0.028 = 1.228 B→∞: 1.2 (相関による下限)

🐍 Python で再現

1
2
3
4
5
import numpy as np
sigma2, rho = 4, 0.3
B = np.array([1, 10, 100, 1000])
var = rho*sigma2 + (1-rho)*sigma2/B
print(f"B 別分散: {var.round(3)}")

📤 実行結果

B 別分散: [4. 1.48 1.228 1.203]

💬 手計算 (Step 2) と Python 出力が完全一致。

🐍 実装バリエーション — scikit-learn / XGBoost / LightGBM / CatBoost

(A) scikit-learn RandomForestRegressor — 標準

🎯 このコードでやること: SSDSE-B-2026(47 都道府県 × 2023 年度)から死亡数 A4200 を 5 個の特徴量(総人口・年少人口・高齢人口・出生数・婚姻件数)で予測する Random Forest 回帰の最小完全例。 訓練/テスト分割 → fit → predict → OOB / R² / RMSE / 特徴量重要度を一括で出力する。
📥 入力データ: data/raw/SSDSE-B-2026.csv(47 都道府県 × 2023 年度) features = [A1101, A1301, A1303, A4101, A9101] target = A4200 (死亡数, 人) R13000 東京都 A1101=14,086,000 A4200=137,241 R27000 大阪府 A1101= 8,763,000 A4200=104,964 R31000 鳥取県 A1101= 537,000 A4200= 8,290 → train 32 件 / test 15 件で分割
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_squared_error

# SSDSE-B-2026 を読み込み、 死亡数 A4200 を 5 変数で予測
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]).rename(columns={'SSDSE-B-2026': '年度'})
df = df[df['年度'] == 2023]
features = ['A1101', 'A1301', 'A1303', 'A4101', 'A9101']  # 総人口/年少/高齢/出生数/婚姻件数
X = df[features].astype(float)
y = df['A4200'].astype(float)

# 訓練/テスト分割
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)

# RandomForestRegressor: 500 本の木でアンサンブル
rf = RandomForestRegressor(n_estimators=500, max_depth=None,
                           min_samples_leaf=1, max_features='sqrt',
                           oob_score=True, n_jobs=-1, random_state=42)
rf.fit(X_tr, y_tr)

# 評価
y_pred = rf.predict(X_te)
r2_test = r2_score(y_te, y_pred)
rmse = np.sqrt(mean_squared_error(y_te, y_pred))

print(f'OOB スコア      = {rf.oob_score_:.4f}')
print(f'テスト R²       = {r2_test:.4f}')
print(f'テスト RMSE     = {rmse:,.0f} 人')
print('特徴量重要度 top3:')
imp = pd.Series(rf.feature_importances_, index=features).sort_values(ascending=False)
print(imp.head(3).to_string())
📤 実行例: 上記コードを実行すると次の出力が得られる OOB スコア = 0.9488 テスト R² = 0.8692 テスト RMSE = 12,795 人 特徴量重要度 top3: A1101 0.2059 A9101 0.2053 A1303 0.2006 → OOB(学習中の bootstrap 外標本評価)と test R² がともに高く、 過学習は軽微。 5 特徴量はいずれも人口規模と相関するため重要度はほぼ拮抗し、 A1101(総人口)が僅差で首位、 A9101(婚姻件数)・A1303(高齢人口)が続く。
💬 読み方: 木の数 n_estimators=500 は安定領域(100-500 が標準)。 max_features='sqrt' で各分岐に√5 ≒ 2 変数のみ候補 → 木間の相関を下げ、 分散低減。 OOB スコアは CV 不要の汎化性能推定で、 47 件しかない少標本に最適。 feature_importances_ により「総人口が死亡数を強く規定する」ことが確認でき、 単回帰(A1101→A4200)の R²≒0.98 と整合する。

(B) scikit-learn ExtraTreesRegressor — 高速・分散低減

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
1
2
3
from sklearn.ensemble import ExtraTreesRegressor
et = ExtraTreesRegressor(n_estimators=500, n_jobs=-1, random_state=42)
# 分割点もランダム化 → さらに分散低減・学習高速化
📥 入力例: data/raw/SSDSE-B-2026.csv X: 47 都道府県 × 複数変数 y: 目的変数
📤 このブロックは標準出力には何も出さない
💬 読み方: 木の数 n_estimators は多いほど安定(100-500 が標準)。 max_depth で過学習を制御。 feature_importances_ で変数選択ができる。 OOB score は CV 不要の汎化性能推定。

(C) XGBoost — 勾配ブースティング

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from xgboost import XGBRegressor
from sklearn.metrics import r2_score

# XGBoost 2.0 以降、 early_stopping_rounds は fit() ではなくコンストラクタ引数
xgb = XGBRegressor(n_estimators=500, learning_rate=0.05, max_depth=5,
                   subsample=0.8, colsample_bytree=0.8, random_state=42,
                   early_stopping_rounds=20)
xgb.fit(X_tr, y_tr, eval_set=[(X_te, y_te)], verbose=False)
print(f'早期終了した木の本数 = {xgb.best_iteration}')
print(f'テスト R2            = {r2_score(y_te, xgb.predict(X_te)):.4f}')
# RF より高精度になることが多い。 ハイパーパラメータ調整が肝心
📥 入力例: 前節と同じ SSDSE-B-2026 (2023 年 47 県) の分割済みデータ X_tr: 32 県 × 5 変数 (A1101 総人口 / A1301 年少人口 / A1303 65 歳以上人口 / A4101 出生数 / A9101 婚姻件数)、 y_tr: 死亡数 A4200 X_te, y_te: 残り 15 県 (early stopping の検証用)
📤 実行例: 早期終了した木の本数 = 359 テスト R2 = 0.8960
💬 読み方: n_estimators=500 を指定したが、 検証誤差が 20 回続けて改善しなかった時点 (359 本目) で打ち切られた。 テスト R²=0.896 は同じデータの RandomForest (0.869) をやや上回る。 なお XGBoost 2.0 以降、 early_stopping_rounds は fit() ではなく XGBRegressor(...) のコンストラクタ引数に移った (fit() に渡すと TypeError)。

(D) LightGBM — 大規模高速

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
1
2
3
4
5
import lightgbm as lgb
lgb_model = lgb.LGBMRegressor(n_estimators=500, learning_rate=0.05,
                               num_leaves=31, random_state=42)
lgb_model.fit(X_tr, y_tr, eval_set=[(X_te, y_te)], callbacks=[lgb.early_stopping(20)])
# 数百万行データでも数秒で訓練。 カテゴリ・欠損値ネイティブ対応
📥 入力例: data/raw/SSDSE-B-2026.csv X: 47 都道府県 × 複数変数 y: 目的変数
📤 実行例(実測) [LightGBM] [Warning] There are no meaningful features which satisfy the provided configuration. Decreasing Dataset parameters min_data_in_bin or min_data_in_leaf and re-constructing Dataset might resolve this warning. [LightGBM] [Info] Total Bins 0 [LightGBM] [Info] Number of data points in the train set: 32, number of used features: 0 [LightGBM] [Info] Start training from score 29829.718750 [Ligh
💬 読み方: 木の数 n_estimators は多いほど安定(100-500 が標準)。 max_depth で過学習を制御。 feature_importances_ で変数選択ができる。 OOB score は CV 不要の汎化性能推定。

(E) CatBoost — カテゴリ変数特化

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
1
2
3
4
from catboost import CatBoostRegressor
cat = CatBoostRegressor(iterations=500, learning_rate=0.05, depth=6, verbose=0)
cat.fit(X_tr, y_tr, cat_features=[])
# カテゴリ変数の前処理不要、 デフォルトでも高精度
📥 入力例: data/raw/SSDSE-B-2026.csv X: 47 都道府県 × 複数変数 y: 目的変数
📤 このブロックは標準出力には何も出さない
💬 読み方: 木の数 n_estimators は多いほど安定(100-500 が標準)。 max_depth で過学習を制御。 feature_importances_ で変数選択ができる。 OOB score は CV 不要の汎化性能推定。

(F) SHAP による解釈

🎯 解説: ランダムフォレスト(Random Forest)は多数の決定木のアンサンブル。 bootstrap 標本+特徴量サブセットで多様性を確保。 SSDSE-B-2026 の都道府県データで高精度な予測と特徴量重要度を同時に得られる。
1
2
3
4
5
6
7
import shap
explainer = shap.TreeExplainer(rf)
sv = explainer(X_te)                     # Explanation(値・基準値・入力をまとめて持つ)
shap.summary_plot(sv, X_te, show=False)  # 各特徴の影響度・方向を可視化
shap.plots.waterfall(sv[0], show=False)  # 個別予測の説明(Explanation を 1 件渡す)
print('SHAP 値の形    =', sv.values.shape)
print(f'基準値 E[f(x)] = {sv.base_values[0]:,.0f} 人')
📥 入力例: 学習済みモデル rf (RandomForestRegressor) と X_te: 15 県 × 5 変数 (A1101 / A1301 / A1303 / A4101 / A9101)
📤 実行例: SHAP 値の形 = (15, 5) 基準値 E[f(x)] = 30,073 人
💬 読み方: 基準値 30,073 人は訓練データの平均死亡数で、 各県の予測値はこの基準値に 5 個の SHAP 値を足したものになる。 waterfall はその内訳を 1 県分表示する。 shap 0.4 以降は explainer(X) が Explanation を返し、 shap.plots.waterfall はこれを要求する — 旧来の explainer.shap_values(X) が返す生の ndarray を渡すと TypeError になる。

🐍 Python 実装 — ランダムフォレスト を SSDSE-B-2026 で動かす

🎯 このコードでやること: まず環境をそろえます。 必要なライブラリを入れ、 matplotlib の日本語フォント(Hiragino Sans)を設定し、 SSDSE を encoding='cp932' で読み込んで shapehead()describe() を確認します。 この後の節では、 47 都道府県データにランダムフォレストを当てます。 木のアンサンブルなので標準化は不要ですが、 特徴量重要度は「相関の強い変数どうしで分け合われる」ため、 重要度が低い=不要とは限らない点に注意が要ります。 SSDSE は人口系の列が互いに 0.99 近い相関を持つので、 この現象が起きやすいデータです。 エンコーディングを指定し忘れると UnicodeDecodeError で止まるのが最初の関門なので、 ここだけは丸暗記して構いません。 パスを変数にせず直書きしているのは、 初学者が「パスをどこに書くべきか」で迷わないようにするためです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ランダムフォレスト を SSDSE-B-2026 で確かめる最小コード
import pandas as pd
import numpy as np

# 1) SSDSE-B-2026(教育用標準データセット)を読み込み
#    1 行目=英字コード, 2 行目=日本語名 → skiprows=[1] で英字コードを列名に
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df.rename(columns={'SSDSE-B-2026': '年度'})  # 先頭列が年度
print('shape:', df.shape)        # (564, 112) — 47 都道府県 × 12 年度(2012-2023)
print('cols head:', list(df.columns[:8]))

# 2) 直近年度(2023 年度)に絞る
df23 = df[df['年度'] == 2023].copy()
print('rows in 2023:', len(df23))

# 3) ランダムフォレスト を動かすために必要な列だけ取り出す
y = df23['A4103'].astype(float)   # 合計特殊出生率
x = df23['A1101'].astype(float)   # 総人口
print('y stats:', y.describe().round(3).to_dict())
print('x stats:', x.describe().round(0).to_dict())

# 4) ランダムフォレスト の本処理(このページの主題)
#    — 具体実装は同カテゴリの個別ページにも掲載
print('---- ランダムフォレスト 結果 ----')
print('mean y:', y.mean().round(3), '/ std y:', round(y.std(), 3))
print('mean x:', x.mean().round(0), '/ std x:', round(x.std(), 0))
print('corr(x, y):', y.corr(x).round(3))

うまく動かないときは ①data/raw/SSDSE-B-2026.csv のパス、 ②encoding='cp932'(SSDSE-B は Shift_JIS 系)、 ③1 行目に英数字ヘッダ、 2 行目に日本語列名が入る構造なので skiprows=[1](日本語名の行だけ除外)が必要、 の 3 点を確認してください。

⚠️ 追加の落とし穴 — ランダムフォレストの実務

❌ feature_importances_ を「特徴の真の重要度」と思う
scikit-learn の feature_importances_(mean decrease in impurity)は分割回数・カーディナリティに偏る。 連続変数・高カーディナリティのカテゴリ変数が過大評価され、 二値変数が過小評価される傾向。 また学習データに対する重要度なので、 過学習を反映する場合も。 Permutation Importance(テストデータで実施)とSHAP値を併用してクロスチェックするのが現代的。
❌ 外挿(extrapolation)に使う
決定木ベースのモデル(RF・GBM)は訓練データ範囲外を予測できない。 訓練データの最大値以上の予測は、 訓練データの最大値あたりで頭打ちになる。 線形回帰は外挿可能だが、 RF は内挿のみ。 時系列予測でトレンドが続く場合、 RF は将来予測で失敗する。 そういう場面では線形モデル、 階差データへの変換、 Prophet 等を検討。
❌ デフォルトハイパーパラメータをそのまま使う
sklearn デフォルトは n_estimators=100, max_depth=None, min_samples_leaf=1 で過学習しやすい。 (i) n_estimators は 500-1000 程度に増やす、 (ii) max_depth を 5-20 で制限、 (iii) min_samples_leaf を 2-10 に、 (iv) max_features='sqrt'(分類)/ 0.33(回帰、 p/3 相当の小数指定)に。 GridSearchCV や RandomSearchCV、 Optuna でチューニング。 適切な調整で R² が 5-15% 改善することはざら。
❌ クラス不均衡への対応を怠る
分類で陽性クラスが 1% しかない時、 RF はすべて陰性予測でも accuracy 99% を達成。 対策:(i) class_weight='balanced'、 (ii) SMOTE などのオーバーサンプリング、 (iii) 評価指標を accuracy ではなく F1・AUC・recall に、 (iv) 閾値調整(デフォルト 0.5 を変える)。 「accuracy が高い」だけでは不均衡データでは無意味。
❌ 結果の解釈を「ブラックボックス」で済ます
RF は線形回帰より解釈が難しいが、 「ブラックボックス」と諦めるのは現代的ではない。 (i) SHAP 値で各予測の説明、 (ii) Partial Dependence Plot で変数効果の可視化、 (iii) ICE プロットで個別予測の感度分析、 (iv) Permutation Importance、 (v) Tree Visualization で1木をサンプル提示。 「説明可能AI(XAI)」の手法群が整備されている。
❌ 因果効果と関連を混同
RF の特徴量重要度は「予測に有用」を意味するが、 「原因」ではない。 たとえば「アイスクリーム売上」が「水難事故」予測に重要でも、 因果関係はない(共通の交絡=気温)。 因果効果には因果フォレスト (Generalized Random Forest)、 Double ML、 DID などの専用手法が必要。 ML と因果推論は別のツールセットと理解する。
❌ データリーク(特徴量ごし)
目的変数と高相関する特徴(実は派生変数や未来情報)が訓練データに紛れ込むと、 R² = 0.99 のような異常な高精度が出る。 例:「医師数」を予測したいのに「医療従事者数」が特徴に含まれる、 など。 異常な精度を疑う、 各特徴の妥当性を熟読、 時間順序を遵守する。 「うますぎる結果」はだいたいリーク。

⚠️ よくある落とし穴 — ランダムフォレスト で初学者がやりがちなミス

この用語を実務で使うときにつまずきやすい点を、 失敗パターン別に整理しました。 1 度経験すれば回避できるものばかりですが、 先に知っておくと事故が大幅に減ります。

❌ 特徴量重要度の解釈
高相関特徴量があると重要度が分散する。 Permutation Importance や SHAP で補完。
❌ 外挿不可
訓練データの範囲外(例:人口 2000 万人の超大都市)は予測精度が大幅低下。
❌ 木が深すぎる
max_depth を制限しないと過学習。 OOB スコアで監視。
❌ 不均衡データ
class_weight='balanced' を設定するか、 SMOTE 等でリサンプリング。
🛡 防御策まとめ:「適用条件の確認 → 適切な前処理 → 結果と前提のペア記述」の 3 ステップを習慣にすれば、 ここに挙げた失敗の大半は回避できます。

🗺️ 統計手法選択フローチャート

ランダムフォレスト 前提: 決定木 / バギング 並列: XGBoost / LightGBM 発展: 勾配ブースティング 応用: 分類・回帰 評価: OOB / 特徴量重要度 対比: 単一決定木

Q1: 何を知りたい?

Q2: データの種類は?

Q3: サンプルサイズは?

Q4: 仮定は?

📏 効果量の参照表

p値だけでなく効果量も併記するのが現代統計の標準。 主要な指標と Cohen の解釈基準:

統計量 効果量
2群平均差Cohen's d0.20.50.8
相関r0.10.30.5
線形回帰0.020.130.26
ANOVAη² (eta²)0.010.060.14
χ²Cramér's V0.10.30.5
ロジスティックOdds Ratio1.52.54.0

🚀 実務応用の深掘り

典型的なプロジェクトの流れ

  1. 問題理解:ステークホルダーとの対話、 KGI/KPI 設定
  2. データ収集:内部DB、 公的データ(SSDSE等)、 API
  3. EDA:データの全体像把握、 異常検出
  4. 仮説立案:ドメイン知識からの仮説
  5. モデリング:シンプルから複雑へ段階的に
  6. 検証:CV、 ホールドアウト、 A/Bテスト
  7. 解釈:可視化、 SHAP、 部分依存プロット
  8. 展開:本番デプロイ、 監視

ベストプラクティス

論文・コンペでよく使う言い回し

日本語 英語
統計的に有意statistically significant
効果量effect size
95%信頼区間95% confidence interval (CI)
標本サイズsample size
検出力statistical power
第1種の誤りType I error / false positive
第2種の誤りType II error / false negative
多重比較問題multiple comparisons problem
過学習overfitting
汎化性能generalization
交差検証cross-validation (CV)

統計データ活用コンペでのコツ

🗺️ 概念マップ — 3つの視点で体系を理解する

ランダムフォレスト がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 統計・データサイエンス › 機械学習 › 教師あり学習 › ランダムフォレスト

① 🔗 関係マップ — 「他の手法とどう繋がっているか」

中心に ランダムフォレスト を置き、 そこから 決定木・XGBoost・分類・LightGBM 計 4 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語あとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。

凡例:現在の用語上位カテゴリ兄弟(並列)前提発展形応用先2階層先

② ⭕ 包含マップ — 「どのカテゴリに含まれているか」

大きな円が小さな円を包含する Circle Packing 図。 「ランダムフォレスト」は緑色でハイライト

📍現在地:統計・データサイエンス

③ 🌳 ツリーマップ — 「面積で見るボリューム比較」

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「ランダムフォレスト」は緑色でハイライト

🎯 3つのマップの使い分け

マップ 分かること こんな時に見る
🔗 関係マップ手法間の横の関係(前提→発展→応用)「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ分類体系の入れ子構造(上位⊃下位)「この手法はどんなジャンルに属する?」
🌳 ツリーマップ分野の規模比較(面積=ボリューム)「データサイエンス全体の俯瞰像」

💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは ランダムフォレスト隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス教師あり学習 → ランダムフォレスト という入れ子の位置を示します。 「教師あり学習には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。

🔗 隣接手法への橋渡し

「ランダムフォレスト」は単独で完結する手法ではなく、 隣接領域と 接続 / 統合 / 比較 の 3 視点で連携して初めて真価を発揮する。 章 10 が派生カタログ、 章 15 が初期分岐、 本セクションは 実務で隣接技術と組み合わせる切替判断 に集中する。

🔌 接続: 上流 → ランダムフォレスト → 下流

ランダムフォレストを中心に、 データ準備から解釈・運用までの一気通貫パイプラインの隣接ノードを整理:

🧬 統合: ランダムフォレスト ×「他手法」の合わせ技 (3 セット)

ランダムフォレスト単独でも強いが、 以下 3 つの隣接手法と組み合わせるとさらに効く:

⚖️ 比較: 類似 ensemble / 解釈モデルとの切替判断

「ランダムフォレスト vs 類似手法」の選定で迷ったらこの表 (相補的 = 用途で使い分け、 競合的 = 1 つを選ぶ):

手法ランダムフォレストに切り替える条件利点注意点
単一決定木精度が必要で、 単一木では過学習する場合バギングで分散低減、 OOB スコアで内部検証無料、 ハイパラに鈍感解釈性が落ちる (300 本の木は人間が読めない、 SHAP で補完必要)
XGBoost / LightGBM / CatBoostハイパラ調整に時間が割けない、 並列学習が必要、 small/medium データで安定したいデフォルト設定でほぼ最強、 学習が並列 (n_jobs=-1)、 OOB で過学習検出無料、 欠損 OKピーク精度は GBM 系の方が 2-5% 高いことが多い、 RAM 消費大 (n_estimators × max_depth)
Extra TreesRF より少しだけ分散低減を強化、 訓練速度も上げたい分割閾値をランダム選択するため過学習しにくい、 訓練が RF より 1.5x 速い特徴量重要度はランダム選択の影響で不安定、 解釈用途には RF の方がよい
線形回帰 / ロジスティック回帰線形仮定では精度不足、 交互作用・非線形を捕捉したいRF は前処理が楽 (スケーリング不要、 外れ値耐性、 欠損 OK)、 交互作用自動検出線形回帰は係数で因果的解釈ができるが、 RF は予測専用 (相関ベース)
ニューラルネット (PyTorch)表形式中規模データ (≦ 数十万行)、 解釈性も欲しいRF は表形式データで NN を上回ることが多い (TabNet, NODE 等の DL Tabular より単純で強い)、 ハイパラ少ない、 解釈付き画像・音声・テキスト・系列データでは NN が圧倒、 RF はそれらに不向き

ランダムフォレストを選ぶべき場面の要約: (i) 表形式データで非線形・交互作用が予想される、 (ii) 前処理を最小化したい、 (iii) ハイパラチューニングに時間を割けない、 (iv) 特徴量重要度を出したい、 (v) 中規模データ (10^3–10^6 行) — のいずれかが該当するなら RF が第一候補。 SSDSE-B-2026 の死亡数予測は典型例: 47 サンプル × 数個〜数十特徴量で、 RF が線形回帰と XGBoost の中間的精度・解釈性を提供する。

🌳 手法選択フロー

「random forest」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。

典型シナリオ別の手法選択

シナリオ重視する観点候補手法
特徴量が多い (高次元) かつ非線形変数間の相互作用を自動捕捉ランダムフォレスト or 勾配ブースティング
外れ値・欠損が混在頑健性と前処理省略を重視ランダムフォレスト (分割基準は順位に強い)
解釈性を最優先したい1 本の木でルールを読みたい決定木 (深さ 4-6) を選ぶ
予測精度を最優先したいブースティング + ハイパラ調整XGBoost / LightGBM / CatBoost
変数重要度を出したいpermutation / impurity 重要度ランダムフォレストの feature_importances_

選んだ後の検証ステップ

  1. 前処理確認: Random Forest は標準化不要だがカテゴリ変数のエンコード (one-hot or label) と欠損処理は必要
  2. ハイパラ調整: n_estimators (100-500) / max_depth / min_samples_leaf を GridSearchCV や OOB スコアで調整
  3. 性能評価: OOB スコアと交差検証スコアを比較し、 一致するなら過剰適合は起きていない
  4. 頑健性チェック: 別シード (random_state=0, 1, 2, ...) で特徴量重要度の順位が安定しているか確認
  5. 解釈: feature_importances_ や SHAP で重要変数を抽出し、 SSDSE-B-2026 で死亡数を予測する主要因(高齢人口・総人口など)が分野知識と一致するかを検討

🧠 解説を深める — 直感・落とし穴・発展(追記)

既存の各章に加え、 ここでは直感 → 落とし穴 → 発展を一段掘り下げる。 数値はすべて data/raw/SSDSE-B-2026.csv(cp932, skiprows=[1], 2023 年度 47 都道府県)での実測値で、 合成データを使う箇所は「架空」と明記する。 関連ページへのリンクは 決定木アンサンブルジニ不純度ブートストラップSHAPXGBoost など既存の用語ページに接続している。

🎨 直感をもう一段(なぜ「多数決」が効くのか)

1 本の決定木は訓練データのわずかな入れ替えで枝分かれが大きく変わる高バリアンスな弱学習器。 ランダムフォレストは (1) ブートストラップ標本(行を復元抽出)と (2) 各分割での特徴量ランダム選択(列を max_features 個に制限)という 2 種類の撹乱で互いに脱相関した木を大量に作り、 回帰なら平均・分類なら多数決で集約する。 分散の縮小式 $\mathrm{Var}=\rho\sigma^2+\frac{1-\rho}{B}\sigma^2$ が示す通り、 木の本数 $B$ を増やすと第 2 項は消え、 残るのは木間相関 $\rho$ に比例する項だけ。 だから RF は「$\rho$ を下げる」ために列をわざとランダムに絞る(バギングとの違いはこの列サブサンプリング)。

📈 実測: 木の本数で OOB がどう収束するか(死亡数 A4200 の回帰)

特徴量=総人口 A1101・65歳以上人口 A1303・出生数 A4101・婚姻件数 A9101 の 4 つで死亡数 A4200 を予測。 n_estimators だけを動かした OOB R² の実測:

n_estimators151050100300
OOB R²−0.7820.6880.9460.9440.9450.942

→ 1 本では OOB R² が負(単一木は不安定)だが、 わずか 10 本で 0.946 まで一気に立ち上がり、 以降は増やしても過学習せず頭打ちで安定する。 これが「本数は多くても害がない(計算コストが増えるだけ)」の実測的裏付け。

🚧 落とし穴を実データで確かめる

① 外挿できない(訓練範囲外は頭打ち)

RF の予測は葉ノードに落ちた訓練サンプルの平均値なので、 訓練データの最大値を超えられない。 実測で確認:総人口が最大の東京都を訓練から除外し、 残り 46 県で RF(n_estimators=300)を学習して東京の死亡数を予測すると、 実測 137,241 人に対し予測は 100,156 人。 訓練データ中の死亡数の最大は 104,964 人で、 予測はほぼそこで飽和している。 時系列トレンドの外挿や、 訓練分布の外側を狙う予測には 線形回帰 や GAM を併用する。

② 特徴量重要度のバイアス(Gini は無関係列にも配る/高カーディナリティ有利)

Gini 重要度(mean decrease in impurity)は「分割に使われた回数×不純度減少」の集計なので、 取りうる値が多い連続変数・高カーディナリティ列ほど分割候補になりやすく過大評価されやすい。 検証として、 上記 4 特徴量に目的変数と無関係な架空の乱数列 NOISE_rand(標準正規, seed=1)を 1 本足すと、 Gini 重要度は NOISE_rand=0.005ゼロではない値を受け取る。 一方テストで測る Permutation importance では 0.001 とほぼ消える。 実測 Gini(65歳以上 0.277 / 総人口 0.268 / 出生数 0.240 / 婚姻 0.215)と Permutation(65歳以上 0.246 / 総人口 0.132 / 婚姻 0.130 / 出生数 0.089)で順位も配分も変わる点に注意。 相関の強い人口系変数どうしでは重要度が分散して両方低く見えることもあるため、 Gini 単独で結論せず PermutationSHAP を併記する。

③ 不均衡データで accuracy は無意味になる

「2022→2023 で総人口が増えた県」を分類対象にすると、 増加は東京都 1 県のみ・減少 46 県という極端な不均衡。 このとき「全県を減少と予測」する多数決ベースラインの精度は 0.979、 RF の OOB 精度も 0.979両者が区別できない。 accuracy だけ見れば「97.9% の高精度」に見えるが、 少数クラス(増加県)は 1 つも当てられていない可能性がある。 不均衡時は class_weight='balanced'、 F1・ROC-AUC・recall・PR 曲線での評価、 BalancedRandomForestClassifier などを使う。

④ 小データ・表形式では勾配ブースティングに劣ることもある/メモリ計算

47 県の小標本では、 分割閾値もランダム化する Extra Trees の方が RF より安定することがある(実測 CV5 R²:RF 0.931 ± 0.034 に対し Extra Trees 0.956)。 一方、 中〜大規模の構造化データでは逐次補正でバイアスを詰める XGBoost/LightGBM/CatBoost が RF を上回ることが多い。 RF は木を深く多数持つほどメモリと推論時間が線形に増える点、 単一木の解釈性は失われ SHAP 等の後付け説明が要る点も実務コスト。 OOB 推定は各サンプルが平均 37% の木でしか未使用にならないため、 木が少ない(上表 n=1〜5)とそもそもOOB 予測が付かず不安定になる(sklearn も警告を出す)。

🚀 発展トピック

※ 本節の R²・重要度・精度・外挿値はいずれも SSDSE-B-2026(2023 年・47 県)での実測。 乱数列 NOISE_rand のみ「架空」の合成列(seed 固定)で、 それ以外の特徴量・目的変数はすべて実データ列。