# 機能設計書 54-ランダムフォレスト回帰

## 概要

本ドキュメントは、Apache Spark MLlibが提供するランダムフォレスト回帰（RandomForestRegressor）機能の設計を記述する。本機能は、複数の決定木のアンサンブルによる回帰モデルの訓練と予測を提供する。

### 本機能の処理概要

ランダムフォレスト回帰は、ブートストラップサンプリングと特徴量のランダムサブセット選択を用いて多数の決定木を訓練し、それらの予測値の平均を出力するアンサンブル手法である。

**業務上の目的・背景**：単一決定木は過学習しやすく特徴量重要度の分散が大きいという問題がある。ランダムフォレストは複数の決定木を集約することで、予測精度の向上と安定した特徴量重要度の推定を実現する。

**機能の利用シーン**：高精度な回帰予測が求められる場面、特徴量選択・重要度分析、非線形関係のモデリングに利用される。

**主要な処理内容**：
1. ブートストラップサンプリングによるデータの多様化
2. 特徴量サブセット戦略による木の多様化
3. 複数決定木の並列訓練
4. 予測値の平均による最終予測

**関連システム・外部連携**：RandomForest実装を内部利用。EnsembleModelReadWriteによる永続化。

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能に直接関連する画面はなし |

## 機能種別

計算処理（機械学習 - アンサンブル回帰）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| numTrees | Int | No | 木の数（デフォルト: 20） | >= 1 |
| featureSubsetStrategy | String | No | 特徴量サブセット戦略（デフォルト: "auto"） | "auto","all","onethird","sqrt","log2" |
| subsamplingRate | Double | No | サブサンプリング率（デフォルト: 1.0） | (0, 1] |
| bootstrap | Boolean | No | ブートストラップ使用（デフォルト: true） | - |
| maxDepth | Int | No | 木の最大深度（デフォルト: 5） | >= 0 |
| maxBins | Int | No | 分割ビン数（デフォルト: 32） | >= 2 |
| impurity | String | No | 不純度指標（デフォルト: "variance"） | "variance" |
| seed | Long | No | ランダムシード | - |
| weightCol | String | No | 重み列名 | - |

### 入力データソース

DataFrame形式。ラベル列はDouble型、特徴量列はVector型。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| prediction | Double | 全木の予測値の平均 |
| leaf | Vector | 各木のリーフノードインデックス（leafCol設定時） |

### 出力先

入力DataFrameに予測列を追加。モデルはEnsembleModelReadWrite形式で永続化。

## 処理フロー

### 処理シーケンス

```
1. カテゴリカル特徴量の抽出
2. 訓練インスタンスの構築
3. 訓練戦略の生成（ブートストラップ設定含む）
4. RandomForest.runで複数木の並列訓練
5. RandomForestRegressionModel生成
```

### フローチャート

```mermaid
flowchart TD
    A[開始: train] --> B[カテゴリカル特徴量抽出]
    B --> C[訓練インスタンス構築]
    C --> D[訓練戦略生成 + bootstrap設定]
    D --> E[RandomForest.run numTrees=N]
    E --> F[DecisionTreeRegressionModel配列取得]
    F --> G[RandomForestRegressionModel生成]
    G --> H[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-54-01 | 最小木数 | 1つ以上の木が必要 | 常時 |
| BR-54-02 | 予測ルール | 全木の予測値の単純平均 | 予測時 |
| BR-54-03 | 特徴量重要度 | 全木の重要度の平均を正規化 | featureImportances呼出時 |

### 計算ロジック

- 予測: `trees.map(_.rootNode.predictImpl(features).prediction).sum / numTrees`
- 特徴量重要度: 全木の特徴量重要度の平均（sum to 1に正規化）

## データベース操作仕様

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | RequireError | 木の配列が空 | numTrees >= 1を設定 |

### リトライ仕様

特になし。

## トランザクション仕様

Sparkの遅延評価に基づく。

## パフォーマンス要件

- モデルはbroadcast変数として各Executorに配信
- 木の並列訓練をサポート

## セキュリティ考慮事項

Sparkの標準セキュリティ機構に従う。

## 備考

- Spark 1.4.0で導入
- 全木の重みは均等（全て1.0）
- Hastie et al. "The Elements of Statistical Learning" に基づく特徴量重要度計算

---

## コードリーディングガイド

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RandomForestRegressor.scala | `mllib/src/main/scala/org/apache/spark/ml/regression/RandomForestRegressor.scala` | RandomForestRegressorParams の継承構造 |
| 1-2 | RandomForestRegressor.scala | 同上 | RandomForestRegressionModel（197-307行目）のtrees配列とtreeWeights |

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RandomForestRegressor.scala | 同上 | train()（136-167行目） |

**主要処理フロー**:
1. **138-139行目**: カテゴリカル特徴量抽出
2. **148-150行目**: OldStrategy生成、bootstrap設定
3. **159-161行目**: RandomForest.runで複数木を訓練
4. **166行目**: RandomForestRegressionModelを生成

#### Step 3: 予測処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RandomForestRegressor.scala | 同上 | predict()（269-273行目）で全木の平均を計算 |
| 3-2 | RandomForestRegressor.scala | 同上 | transform()（238-267行目）でbroadcast使用の予測 |

### プログラム呼び出し階層図

```
RandomForestRegressor.train(dataset)
    |
    +-- MetadataUtils.getCategoricalFeatures()
    +-- getOldStrategy(categoricalFeatures)
    +-- RandomForest.run(instances, strategy, numTrees, featureSubsetStrategy)
    +-- new RandomForestRegressionModel(uid, trees, numFeatures)

RandomForestRegressionModel.transform(dataset)
    |
    +-- sparkContext.broadcast(this)
    +-- predict(features)
            +-- trees.map(_.rootNode.predictImpl(features).prediction).sum / numTrees
```

### データフロー図

```
[入力]                    [処理]                              [出力]

DataFrame          train()
  (label,          +-- ブートストラップ + 特徴量サブセット  RandomForestRegressionModel
   features,       +-- N本の決定木を並列訓練                  (trees[N],
   weight)                                                     treeWeights)

DataFrame          transform()
  (features)       +-- 全木の予測値を平均              DataFrame
                                                         (prediction,
                                                          leaf)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RandomForestRegressor.scala | `mllib/src/main/scala/org/apache/spark/ml/regression/RandomForestRegressor.scala` | ソース | Estimator/Model の実装 |
| RandomForest.scala | `mllib/src/main/scala/org/apache/spark/ml/tree/impl/RandomForest.scala` | ソース | ツリー構築アルゴリズム |
| DecisionTreeRegressor.scala | `mllib/src/main/scala/org/apache/spark/ml/regression/DecisionTreeRegressor.scala` | ソース | 個々の決定木モデル |
| EnsembleModelReadWrite.scala | `mllib/src/main/scala/org/apache/spark/ml/tree/EnsembleModelReadWrite.scala` | ソース | アンサンブルモデルの永続化 |
