はじめに
アンサンブル学習は、複数の弱学習器を組み合わせることで、単体モデルより高い汎化性能を実現する手法です。Kaggle等のコンペティションでもトップソリューションの多くがアンサンブル手法を採用しています。
本記事では、基本構成要素である決定木から、バギング(ランダムフォレスト)、**ブースティング(GBDT)**までを体系的に解説します。
決定木
CART アルゴリズム
分類木ではジニ不純度を最小化する分割を再帰的に探索します。
\[\text{Gini}(t) = 1 - \sum_{k=1}^{K} p_k^2 \tag{1}\]ここで \(p_k\) はノード \(t\) におけるクラス \(k\) の割合です。
回帰木では二乗誤差を使います。
\[\text{MSE}(t) = \frac{1}{|t|} \sum_{i \in t} (y_i - \bar{y}_t)^2 \tag{2}\]決定木の長所と短所
| 長所 | 短所 |
|---|---|
| 解釈しやすい | 過学習しやすい |
| 前処理が不要 | 決定境界が軸に平行 |
| 非線形に対応 | 分散が大きい(不安定) |
バギング
原理
**Bootstrap Aggregating(バギング)**は、ブートストラップサンプルで複数の決定木を独立に学習し、予測を平均化(回帰)または多数決(分類)します。
\[\hat{f}_{\text{bag}}(\mathbf{x}) = \frac{1}{B} \sum_{b=1}^{B} \hat{f}_b(\mathbf{x}) \tag{3}\]分散を削減する効果があります。
\[\text{Var}\left(\frac{1}{B}\sum_b f_b\right) = \frac{\sigma^2}{B} \quad (\text{独立な場合}) \tag{4}\]ランダムフォレスト
バギングに加えて、各分割で特徴量のランダムサブセット(\(m \approx \sqrt{p}\))のみを候補にします。これにより木の間の相関を下げ、さらに分散を削減します。
ブースティング
勾配ブースティング(GBDT)
弱学習器を逐次的に追加し、前の学習器の残差(負の勾配)をフィッティングします。
ステップ \(m\) での更新:
\[F_m(\mathbf{x}) = F_{m-1}(\mathbf{x}) + \eta \cdot h_m(\mathbf{x}) \tag{5}\]ここで \(h_m\) は擬似残差 \(r_{im} = -\frac{\partial L(y_i, F_{m-1}(\mathbf{x}_i))}{\partial F_{m-1}(\mathbf{x}_i)}\) にフィットした決定木、\(\eta\) は学習率です。
バギング vs ブースティング
| 特徴 | バギング | ブースティング |
|---|---|---|
| 学習方式 | 並列(独立) | 逐次(依存) |
| 主な効果 | 分散の削減 | バイアスの削減 |
| 過学習耐性 | 高い | 低い(要チューニング) |
| 代表手法 | ランダムフォレスト | GBDT, XGBoost, LightGBM |
Python実装
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import (RandomForestClassifier,
GradientBoostingClassifier)
from sklearn.metrics import accuracy_score
# --- データ生成 ---
X, y = make_classification(n_samples=1000, n_features=20, n_informative=10,
n_redundant=5, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3,
random_state=42)
# --- モデル比較 ---
models = {
'Decision Tree': DecisionTreeClassifier(max_depth=5, random_state=42),
'Random Forest': RandomForestClassifier(n_estimators=100, max_depth=5,
random_state=42),
'Gradient Boosting': GradientBoostingClassifier(n_estimators=100,
max_depth=3,
learning_rate=0.1,
random_state=42),
}
results = {}
for name, model in models.items():
cv_scores = cross_val_score(model, X_train, y_train, cv=5,
scoring='accuracy')
model.fit(X_train, y_train)
test_acc = accuracy_score(y_test, model.predict(X_test))
results[name] = {'cv_mean': cv_scores.mean(), 'cv_std': cv_scores.std(),
'test_acc': test_acc}
print(f"{name}: CV={cv_scores.mean():.3f}±{cv_scores.std():.3f}, "
f"Test={test_acc:.3f}")
# --- 特徴量重要度(ランダムフォレスト) ---
rf = models['Random Forest']
importances = rf.feature_importances_
indices = np.argsort(importances)[::-1][:10]
plt.figure(figsize=(10, 5))
plt.bar(range(10), importances[indices])
plt.xticks(range(10), [f'Feature {i}' for i in indices], rotation=45)
plt.ylabel('Importance')
plt.title('Random Forest Feature Importance (Top 10)')
plt.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
主要ハイパーパラメータ
ランダムフォレスト
| パラメータ | 説明 | 目安 |
|---|---|---|
n_estimators | 木の数 | 100-500(多いほど安定) |
max_depth | 木の深さ | 5-20 |
max_features | 分割候補の特徴量数 | \(\sqrt{p}\)(分類)、\(p/3\)(回帰) |
勾配ブースティング
| パラメータ | 説明 | 目安 |
|---|---|---|
n_estimators | ブースティングの反復数 | 100-1000 |
learning_rate | 学習率 \(\eta\) | 0.01-0.1 |
max_depth | 各木の深さ | 3-8(浅め) |
学習率と反復数にはトレードオフがあり、小さな学習率 + 多くの反復が一般的です。
関連記事
- サポートベクターマシン(SVM) - 別の強力な分類手法であるSVMとの比較に有用です。
- k-means法とGMM - 教師なし学習との対比。決定木は特徴量重要度の算出にも利用されます。
- SGDからAdamまで - 勾配ブースティングの「勾配」と最適化手法の関連です。
- ベイズ最適化の基礎とPython実装 - GBDTのハイパーパラメータ最適化にベイズ最適化を適用できます。
参考文献
- Breiman, L. (2001). “Random Forests”. Machine Learning, 45(1), 5-32.
- Friedman, J. H. (2001). “Greedy Function Approximation: A Gradient Boosting Machine”. Annals of Statistics, 29(5), 1189-1232.
- scikit-learn Ensemble Methods