# 機能設計書 67-モデル評価

## 概要

本ドキュメントは、Apache Spark MLlibにおけるモデル評価機能の設計を記述する。二値分類、多クラス分類、回帰、クラスタリング、ランキングの各タスクに対応する評価指標算出機能を対象とする。

### 本機能の処理概要

**業務上の目的・背景**：機械学習モデルの性能を客観的に評価することは、モデル選択やハイパーパラメータチューニングにおいて不可欠である。各タスク種別に応じた適切な評価指標を算出することで、モデルの品質を定量的に測定し、最適なモデルの選択を支援する。CrossValidatorやTrainValidationSplitと組み合わせて自動モデル選択に利用される。

**機能の利用シーン**：モデル訓練後の性能評価、CrossValidatorによるハイパーパラメータチューニング時の評価指標、A/Bテストにおけるモデル比較、本番運用前のモデル品質チェックなど。

**主要な処理内容**：
1. **BinaryClassificationEvaluator**: 二値分類の評価（AUC-ROC、AUC-PR）
2. **MulticlassClassificationEvaluator**: 多クラス分類の評価（F1、accuracy、precision、recall、logLoss等）
3. **RegressionEvaluator**: 回帰の評価（RMSE、MSE、R2、MAE、explained variance）
4. **ClusteringEvaluator**: クラスタリングの評価（Silhouette係数）
5. **RankingEvaluator**: ランキングの評価（MAP、MAP@K、NDCG@K、Precision@K、Recall@K）

**関連システム・外部連携**：Spark DataFrame APIおよびPipeline APIと統合。CrossValidatorやTrainValidationSplitのevaluatorパラメータとして使用される。mllib.evaluationパッケージに実際のメトリクス計算を委譲。

**権限による制御**：特になし。Sparkアプリケーション実行権限に依存する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | MLlib機能はWeb UIに専用画面を持たない |

## 機能種別

計算処理（機械学習 - モデル評価）

## 入力仕様

### 入力パラメータ

#### BinaryClassificationEvaluator
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| rawPredictionCol | String | No | 生予測値カラム名（デフォルト: "rawPrediction"） | Double型またはVector型 |
| labelCol | String | No | ラベルカラム名（デフォルト: "label"） | 数値型 |
| metricName | String | No | 評価指標（"areaUnderROC"/"areaUnderPR"、デフォルト: "areaUnderROC"） | - |
| numBins | Int | No | カーブのダウンサンプリングbin数（デフォルト: 1000） | >= 0 |
| weightCol | String | No | 重みカラム名 | 非負の数値型 |

#### MulticlassClassificationEvaluator
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| predictionCol | String | No | 予測カラム名（デフォルト: "prediction"） | - |
| labelCol | String | No | ラベルカラム名（デフォルト: "label"） | - |
| metricName | String | No | 評価指標（"f1"/"accuracy"/"weightedPrecision"/"weightedRecall"等、デフォルト: "f1"） | - |
| metricLabel | Double | No | ByLabel系指標の対象クラス（デフォルト: 0.0） | >= 0 |

#### RegressionEvaluator
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| predictionCol | String | No | 予測カラム名（デフォルト: "prediction"） | - |
| labelCol | String | No | ラベルカラム名（デフォルト: "label"） | - |
| metricName | String | No | 評価指標（"rmse"/"mse"/"r2"/"mae"/"var"、デフォルト: "rmse"） | - |
| throughOrigin | Boolean | No | 原点回帰か（デフォルト: false） | - |

#### ClusteringEvaluator
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| predictionCol | String | No | 予測カラム名（デフォルト: "prediction"） | - |
| featuresCol | String | No | 特徴量カラム名（デフォルト: "features"） | Vector型 |
| metricName | String | No | 評価指標（"silhouette"、デフォルト: "silhouette"） | - |
| distanceMeasure | String | No | 距離尺度（"squaredEuclidean"/"cosine"、デフォルト: "squaredEuclidean"） | - |

#### RankingEvaluator
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| predictionCol | String | No | 予測カラム名（デフォルト: "prediction"） | Array型 |
| labelCol | String | No | ラベルカラム名（デフォルト: "label"） | Array型 |
| metricName | String | No | 評価指標（"meanAveragePrecision"等、デフォルト: "meanAveragePrecision"） | - |
| k | Int | No | ランキング位置（デフォルト: 10） | > 0 |

### 入力データソース

モデルのtransform()出力であるDataFrame（予測結果とラベルを含む）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| metric | Double | evaluate()メソッドが返すスカラーメトリクス値 |

### 出力先

evaluate()メソッドの返り値としてDouble値を返す。

## 処理フロー

### 処理シーケンス

```
1. スキーマバリデーション
   └─ 必要なカラムの存在・型を検証
2. データの抽出
   └─ 予測値・ラベル・重みカラムを選択
3. メトリクス計算
   └─ mllib.evaluationのメトリクスクラスに委譲
4. 評価値の返却
   └─ 指定されたmetricNameに対応する値を返す
```

### フローチャート

```mermaid
flowchart TD
    A[開始: evaluate呼び出し] --> B[スキーマ検証]
    B --> C[予測値・ラベル抽出]
    C --> D[mllib Metrics計算]
    D --> E{metricName}
    E -->|areaUnderROC| F[AUC-ROC計算]
    E -->|rmse| G[RMSE計算]
    E -->|f1| H[F1計算]
    E -->|silhouette| I[Silhouette計算]
    E -->|meanAveragePrecision| J[MAP計算]
    F --> K[Double値返却]
    G --> K
    H --> K
    I --> K
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-67-01 | isLargerBetter | 評価値が大きいほど良いかを示すフラグ。回帰のRMSE等はfalse | 常時 |
| BR-67-02 | BinaryClassification | rawPredictionColはDouble型（二値確率）またはVector型（長さ2） | BinaryClassificationEvaluator |
| BR-67-03 | numBins | 0の場合ダウンサンプリングなし | BinaryClassificationEvaluator |
| BR-67-04 | metricLabel | ByLabel系指標の計算対象クラスを指定 | MulticlassClassificationEvaluator |

### 計算ロジック

- AUC-ROC: ROC曲線下面積
- RMSE: sqrt(sum((y - y')^2) / n)
- F1: 2 * precision * recall / (precision + recall)
- Silhouette: (b(i) - a(i)) / max(a(i), b(i))
- MAP: 全クエリのAverage Precisionの平均

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

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし（インメモリ処理） |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalArgumentException | パラメータ検証エラー | metricNameが不正 | サポートされるメトリクス名を指定 |
| SchemaValidationError | スキーマエラー | 必要カラムが存在しない | transform()済みDataFrameを入力 |

### リトライ仕様

リトライ機構は組み込まれていない。

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

トランザクション管理なし。

## パフォーマンス要件

評価計算はデータサイズに比例。BinaryClassificationEvaluatorのnumBinsでROC/PRカーブのダウンサンプリングによりメモリ使用量を制御可能。

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

特段のセキュリティ制御なし。

## 備考

- 全EvaluatorはEvaluator抽象クラスを継承
- isLargerBetterプロパティによりCrossValidator等が最適化方向を判断
- getMetrics()メソッドでmlllib Metricsオブジェクトに直接アクセス可能

---

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

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Evaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/Evaluator.scala` | **28-63行目**: Evaluator抽象クラスの定義。evaluate(), isLargerBetter, copy()の3つのメソッドが核心 |

**読解のコツ**: 全Evaluatorの共通インターフェースを理解することが最優先。evaluate()メソッドがスカラー値を返し、isLargerBetterで最適化方向を指定するパターン。

#### Step 2: 代表的なEvaluatorを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | BinaryClassificationEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/BinaryClassificationEvaluator.scala` | **37-39行目**: HasRawPredictionCol, HasLabelCol, HasWeightColを継承 |

**主要処理フロー**:
1. **98-106行目**: evaluate()でgetMetrics()を呼び、metricNameに応じた値を返却
2. **116-138行目**: getMetrics()でスキーマ検証、データ抽出、BinaryClassificationMetrics生成
3. **142行目**: isLargerBetterはtrue（AUCは大きいほど良い）

#### Step 3: 各種Evaluatorを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MulticlassClassificationEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/MulticlassClassificationEvaluator.scala` | **35行目**: 14種類のメトリクスをサポート |
| 3-2 | RegressionEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/RegressionEvaluator.scala` | **34行目**: rmse/mse/r2/mae/varの5種類 |
| 3-3 | ClusteringEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/ClusteringEvaluator.scala` | **36行目**: silhouetteメトリクス |
| 3-4 | RankingEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/RankingEvaluator.scala` | **36行目**: ランキングメトリクス |

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

```
Evaluator.evaluate(dataset)
    |
    +-- BinaryClassificationEvaluator
    |       +-- getMetrics(dataset)
    |       |       +-- SchemaUtils.checkColumnTypes()
    |       |       +-- dataset.select() → RDD変換
    |       |       +-- BinaryClassificationMetrics(scoreAndLabels)
    |       +-- metrics.areaUnderROC() or metrics.areaUnderPR()
    |
    +-- RegressionEvaluator
    |       +-- getMetrics(dataset)
    |       |       +-- RegressionMetrics(predAndLabels)
    |       +-- metrics.rootMeanSquaredError / mse / r2 / mae
    |
    +-- MulticlassClassificationEvaluator
    |       +-- getMetrics(dataset)
    |       |       +-- MulticlassMetrics(predAndLabels)
    |       +-- metrics.weightedFMeasure / accuracy / etc.
    |
    +-- ClusteringEvaluator
    |       +-- SquaredEuclideanSilhouette / CosineSilhouette
    |
    +-- RankingEvaluator
            +-- RankingMetrics(predAndLabels)
```

### データフロー図

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

DataFrame              Evaluator.evaluate()           Double
(prediction,       --> スキーマ検証                 --> メトリクス値
 label,                mllib Metrics計算
 weight?)              metricNameに応じた値抽出
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Evaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/Evaluator.scala` | ソース | 基底クラス |
| BinaryClassificationEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/BinaryClassificationEvaluator.scala` | ソース | 二値分類評価 |
| MulticlassClassificationEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/MulticlassClassificationEvaluator.scala` | ソース | 多クラス分類評価 |
| RegressionEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/RegressionEvaluator.scala` | ソース | 回帰評価 |
| ClusteringEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/ClusteringEvaluator.scala` | ソース | クラスタリング評価 |
| RankingEvaluator.scala | `mllib/src/main/scala/org/apache/spark/ml/evaluation/RankingEvaluator.scala` | ソース | ランキング評価 |
