【機械学習】ランダムフォレスト入門：決定木の集約と実装

## 目次

1. [はじめに](#1-はじめに)
2. [ランダムフォレストとは](#2-ランダムフォレストとは)
    - [基本概念](#基本概念)
    - [構造](#構造)
3. [ランダムフォレストの構築方法](#3-ランダムフォレストの構築方法)
    - [バギング(Bagging)](#バギングbagging)
    - [特徴量の無作為選択](#特徴量の無作為選択)
4. [Pythonでのランダムフォレストの実装](#4-pythonでのランダムフォレストの実装)
    - [必要なライブラリのインストール](#必要なライブラリのインストール)
    - [サンプルデータの準備とランダムフォレストの構築](#サンプルデータの準備とランダムフォレストの構築)
    - [モデルの可視化](#モデルの可視化)
5. [ランダムフォレストの利点と欠点](#5-ランダムフォレストの利点と欠点)
    - [利点](#利点)
    - [欠点](#欠点)
6. [まとめ](#6-まとめ)

## 1. はじめに

こんにちは！ご覧いただきありがとうございます。

新卒1年目の吉田です。

前回の記事では、機械学習の基本的なアルゴリズムである「決定木」について執筆いたしました。決定木はそのシンプルさと直感的な理解のしやすさから、多くの場面で活用されています。まだお読みでない方は、ぜひ前回の記事をご覧いただけますと幸いです。

https://qiita.com/yoshida_slj/items/ecb7e51f7e303168f66e

今回は、その決定木をさらに発展させた手法である「ランダムフォレスト（Random Forest）」についてご紹介いたします。ランダムフォレストは、複数の決定木を組み合わせることで、個々の決定木の弱点を克服し、予測精度を向上させる手法です。本記事では、ランダムフォレストの基本概念、構築方法、そしてPythonを用いた実装方法についてご紹介いたします。

ランダムフォレストは、多数の決定木を作成し、その予測結果を統合することで、より強力な予測モデルを構築します。このアプローチにより、モデルの予測の安定性を高め、過学習を防ぐことができます。また、特徴量の重要度を評価する上でも有用であり、データ解析やモデル解釈の際にも役立ちます。

## 2. ランダムフォレストとは

### 基本概念

ランダムフォレストは、多数の決定木を用いて予測を行うアンサンブル学習の手法です。各決定木は独立して学習し、最終的な予測は各決定木の予測の平均または多数決で決定されます。

### 構造

ランダムフォレストの構造は以下の通りです：

- **複数の決定木**：ランダムフォレストは、多数の決定木を生成し、それぞれが部分的なデータセットを用いて学習します
- **アンサンブル学習**：各決定木の予測結果を集約し、全体としての予測を行います

## 3. ランダムフォレストの構築方法

ランダムフォレストの構築には、以下の要素が重要です。

### バギング（Bagging）

バギングとは、元のデータセットからランダムにサブセットを生成し、それぞれのサブセットを用いて個別の決定木を学習させる手法です。これにより、モデルの安定性を高め、過学習を防ぐことができます。

### 特徴量の無作為選択

各決定木の分割時に使用する特徴量をランダムに選択することで、相関の強い特徴量に依存しすぎることを防ぎ、モデルの多様性を高めます。

## 4. Pythonでのランダムフォレストの実装

### 必要なライブラリのインストール

ランダムフォレストを実装するために、以下のライブラリをインストールします。

```bash
pip install scikit-learn pandas matplotlib
```

### サンプルデータの準備とランダムフォレストの構築

以下のコードを使用して、ランダムフォレストを構築し、予測を行います。

従業員の特徴（年齢、職務経験、部署）に基づいて離職のリスクを予測します。

```python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix, accuracy_score
import matplotlib.pyplot as plt
import seaborn as sns

# サンプルデータ
data = {
    '年齢': [25, 45, 35, 50, 23, 40, 28, 50, 60, 36, 32, 25, 29, 41, 50, 38, 27, 46, 34, 49],
    '職務経験（年数）': [3, 20, 10, 30, 2, 15, 5, 29, 35, 11, 8, 3, 6, 18, 28, 12, 4, 21, 9, 25],
    '部署': ['営業', '技術', '人事', '技術', '営業', '人事', '営業', '技術', '営業', '技術', '人事', '営業', '営業', '技術', '人事', '技術', '営業', '技術', '人事', '技術'],
    '離職': [0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1]
}

dataset = pd.DataFrame(data)
print(dataset)

# 特徴量とラベルに分割
X = pd.get_dummies(dataset.iloc[:, :-1])
y = dataset.iloc[:, -1].values

# トレーニングデータとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

# ランダムフォレストモデルのトレーニング
classifier = RandomForestClassifier(n_estimators=100, criterion='entropy', random_state=0)
classifier.fit(X_train, y_train)

# テストデータで予測
y_pred = classifier.predict(X_test)

# 混同行列の作成
cm = confusion_matrix(y_test, y_pred)
print(cm)

# 精度の計算
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy: .2f}')
```

### モデルの可視化

ランダムフォレスト全体の可視化は難しいですが、各決定木を個別に可視化することは可能です。

```python
from sklearn.tree import export_graphviz
import graphviz

# ランダムフォレストの最初の決定木を可視化
estimator = classifier.estimators_[0]

dot_data = export_graphviz(estimator, out_file=None, feature_names=X.columns, class_names=classifier.classes_, filled=True, rounded=True, special_characters=True)
graph = graphviz.Source(dot_data)
graph.render("random_forest_tree")

# グラフを表示
graph
```

  以下のような決定木の図が生成されます。

  ![Qiita_ランダムフォレスト_決定木.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787204/72da20f1-8304-6bdf-81c9-2c16a9f84d17.png)


## 5. ランダムフォレストの利点と欠点

### 利点

- **高い精度**：複数の決定木を使用することで、過学習を防ぎ、高い予測精度を実現します
- **ロバスト性**：ノイズや外れ値に対して強い
- **特徴量の重要度**：各特徴量の重要度を計算することができ、モデルの解釈性を高めます

### 欠点

- **計算コスト**：大量の決定木を学習するため、計算コストが高くなる
- **ブラックボックス**：全体のモデルが複雑で解釈が難しい場合がある

## 6. まとめ

この記事では、ランダムフォレストの基本的な概念とその構築方法、Pythonを用いた実装方法を解説しました。ランダムフォレストは、個々の決定木の欠点を克服し、強力な予測モデルを構築するための手法です。

読者の皆さんからの貴重なフィードバックやご指摘をいただけると、非常に助かります！

最後までご覧いただき、ありがとうございました！