【機械学習】決定木入門：直感的な理解と実装

## 目次

1. [はじめに](#1-はじめに)
2. [決定木とは](#2-決定木とは)
    - [基本概念](#決定木の基本概念)
    - [構造](#決定木の構造)
3. [決定木の構築方法](#3-決定木の構築方法)
    - [データの純度と分割基準](#データの純度と分割基準)
    - [エントロピーとは](#エントロピーとは)
    - [分割の例](#分割の例)
    - [構築アルゴリズム](#決定木の構築アルゴリズム)
4. [Pythonでの決定木の実装](#4-pythonでの決定木の実装)
    - [必要なライブラリのインストール](#必要なライブラリのインストール)
    - [サンプルデータの準備と決定木の構築](#サンプルデータの準備と決定木の構築)
    - [モデルの可視化](#モデルの可視化)
5. [決定木の利点と欠点](#5-決定木の利点と欠点)
    - [利点](#利点)
    - [欠点](#欠点)
6. [まとめ](#6-まとめ)

## 1. はじめに

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

新卒1年目の吉田です。

データサイエンスに対する興味から、機械学習の基本的なアルゴリズムの一つ「決定木（Decision Tree）」について学び始めました。その直感的な理解と基本的な実装方法を共有することで、同じく学習を進める皆さんの助けになればと思います。

決定木は、その名の通り、木のような構造を持つアルゴリズムで、データの分類や回帰に広く使用されています。本記事では、決定木の基本概念を直感的に理解しやすいよう説明し、その後、Pythonを使った簡単な実装方法を紹介します。

## 2. 決定木とは

### 決定木の基本概念

決定木は、データを一連の質問（または条件）を通じて分類するアルゴリズムです。木の各ノードは質問を表し、枝は質問に対する答え（はい/いいえ）を表します。葉（リーフ）ノードは最終的なクラスラベルや予測値を表します。

### 例：フルーツの分類

フルーツを分類するための決定木の例を考えてみましょう。

**質問1**: フルーツの色は赤ですか？
- 「はい」の場合、次の質問へ進みます
- 「いいえ」の場合、そのフルーツは「バナナ」と判断されます

**質問2**: フルーツのサイズは小さいですか？
- 「はい」の場合、そのフルーツは「チェリー」と判断されます
- 「いいえ」の場合、そのフルーツは「リンゴ」と判断されます

このように、決定木は一連の質問を通じてデータを分類します。

### 決定木の構造

決定木の構造は以下の通りです：

- **ルートノード**: データセット全体を最初に受け取る最上位のノード
- **内部ノード**: 分岐を表すノード。各ノードは属性（特徴量）に基づいて質問を持ちます
- **葉ノード**: 最終的な決定または予測を表すノード

## 3. 決定木の構築方法

決定木を構築するためには、どの特徴量を基にデータを分割するかを決定する必要があります。ここでは、データの純度を高めるための分割方法を直感的に説明します。

### データの純度と分割基準

決定木を構築する主な目標は、データセットを可能な限り「純粋な」サブセットに分割することです。純粋なサブセットとは、同じクラスラベルを持つデータが多く含まれているグループのことです。これを実現するために、エントロピーなどの分割基準を使用します。

### エントロピーとは

エントロピーは、データの不純度を測る指標の一つです。エントロピーが低いほど、そのノード内のデータは純粋です。エントロピーを使って分割基準を決めることで、データセットをより純粋なサブセットに分割することができます。

### 分割の例

例えば、次のようなデータセットがあるとします。

| 色 | サイズ | フルーツ |
| --- | --- | --- |
| 赤 | 大 | リンゴ |
| 赤 | 小 | チェリー |
| 黄 | 大 | バナナ |
| 黄 | 小 | チェリー |

このデータセットを「色」と「サイズ」に基づいて分割する際に、どの特徴量を最初に使うかを決めるために、各特徴量の分割によるエントロピーの変化を計算します。直感的には、データを分割することで、同じフルーツが多く含まれるようにするのが目標です。

### 決定木の構築アルゴリズム

決定木の構築には、以下の手順を用います。

1. **全データセットから開始**: ルートノードを作成します
2. **最良の分割を見つける**: エントロピーなどの基準に基づいて、データを最も純粋なサブセットに分割する特徴量を選びます
3. **データを分割する**: 選ばれた特徴量に基づいてデータを二分します
4. **再帰的に繰り返す**: 各サブセットで再び最良の分割を見つけ、分割を続けます。これを葉ノードに到達するまで繰り返します

このプロセスを通じて、決定木はデータを分類するためのルールを学習します。

## 4. Pythonでの決定木の実装

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

まずは、Pythonのライブラリをインストールします。

```bash
pip install scikit-learn pandas graphviz

```

### サンプルデータの準備と決定木の構築

サンプルデータを用意し、決定木を構築します。以下のコードは、前処理、モデルのトレーニング、テストデータでの評価を行います。

```python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.tree import export_graphviz
import graphviz

# サンプルデータ
data = {
    '色': ['赤', '赤', '赤', '黄', '黄', '黄', '赤', '赤', '黄', '黄', '赤', '黄', '黄', '赤', '赤', '黄', '黄', '赤', '黄', '赤', '黄', '赤', '黄', '赤', '黄', '赤', '黄', '赤', '黄'],
    'サイズ': ['大', '大', '小', '大', '小', '小', '小', '大', '小', '大', '大', '大', '小', '小', '大', '小', '大', '小', '大', '大', '小', '小', '大', '大', '小', '大', '大', '小', '大'],
    'フルーツ': ['リンゴ', 'リンゴ', 'チェリー', 'バナナ', 'チェリー', 'バナナ', 'チェリー', 'リンゴ', 'バナナ', 'リンゴ', 'チェリー', 'バナナ', 'リンゴ', 'チェリー', 'バナナ', 'リンゴ', 'チェリー', 'リンゴ', 'バナナ', 'リンゴ', 'チェリー', 'バナナ', 'リンゴ', 'チェリー', 'バナナ', 'リンゴ', 'バナナ', 'チェリー', 'リンゴ']
}

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 = DecisionTreeClassifier(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
# 決定木の可視化
dot_data = export_graphviz(classifier, 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("decision_tree")

# グラフを表示
graph

```

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

![decision_tree_classifier.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3787204/94a35aff-e2fe-097c-8484-1396ca1c58a5.png)


## 5. 決定木の利点と欠点

### 利点

- **直感的で分かりやすい**: 視覚的に理解しやすく、その構造からデータの分岐と決定プロセスが明確になります
- **データの前処理が少ない**: カテゴリーデータと数量データの両方に対応可能で、データの前処理が比較的少なくて済みます
- **高速な予測**: モデルがシンプルなため、予測が高速です

### 欠点

- **過学習しやすい**: データに過剰に適合してしまい、新しいデータに対する汎化性能が低下することがあります
- **小さなデータセットでは不安定**: データのバリエーションが少ない場合、モデルが不安定になることがあります
- **計算量が多い**: 特に大規模なデータセットでは、計算量が増加する可能性があります

## 6. まとめ

この記事では、決定木の基本的な概念とその直感的な理解方法、Pythonを用いた簡単な実装方法を解説しました。読者の皆さんからの貴重なフィードバックやご指摘をいただけると、非常に助かります！

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