# 機能設計書 69-頻出パターンマイニング

## 概要

本ドキュメントは、Apache Spark MLlibにおける頻出パターンマイニング機能の設計を記述する。FP-Growthアルゴリズムによる頻出アイテムセットの抽出・相関ルール生成、およびPrefixSpanアルゴリズムによる頻出系列パターンの抽出機能を対象とする。

### 本機能の処理概要

**業務上の目的・背景**：大規模トランザクションデータからの頻出パターン発見は、マーケットバスケット分析や推薦システムの基盤技術である。「ある商品を購入した顧客は別の商品も購入する傾向がある」といった共起パターンを効率的に抽出し、ビジネス意思決定を支援する。FP-Growthは候補生成なしの効率的な頻出アイテムセット抽出、PrefixSpanは時系列を考慮した系列パターン抽出を提供する。

**機能の利用シーン**：ECサイトのマーケットバスケット分析（併買分析）、Webサイトのクリックストリーム分析、医療データの投薬パターン分析、ユーザー行動系列の分析など。

**主要な処理内容**：
1. **FP-Growth**: トランザクションデータから頻出アイテムセットを抽出
2. **相関ルール生成**: 頻出アイテムセットから信頼度・リフト・サポート付きの相関ルールを生成
3. **FPGrowthModel.transform()**: 相関ルールに基づく推薦（新規トランザクションに適用可能なルールの推奨結果を予測）
4. **PrefixSpan**: トランザクションの系列データから頻出系列パターンを抽出

**関連システム・外部連携**：Spark DataFrame APIと統合。FP-Growthはml APIのEstimator/Modelパターンに従い、PrefixSpanはfindFrequentSequentialPatterns()メソッドで直接実行する。内部的にmllib.fpmのアルゴリズム実装に委譲。

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

## 関連画面

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

## 機能種別

計算処理（データマイニング - パターン抽出）

## 入力仕様

### 入力パラメータ

#### FPGrowth
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| itemsCol | String | No | アイテムカラム名（デフォルト: "items"） | Array型カラム |
| minSupport | Double | No | 最小サポート（デフォルト: 0.3） | [0.0, 1.0] |
| minConfidence | Double | No | 最小信頼度（デフォルト: 0.8） | [0.0, 1.0] |
| numPartitions | Int | No | パーティション数 | >= 1 |
| predictionCol | String | No | 予測カラム名（デフォルト: "prediction"） | - |

#### PrefixSpan
| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sequenceCol | String | No | 系列カラム名（デフォルト: "sequence"） | ArrayType(ArrayType(T)) |
| minSupport | Double | No | 最小サポート（デフォルト: 0.1） | >= 0.0 |
| maxPatternLength | Int | No | 最大パターン長（デフォルト: 10） | > 0 |
| maxLocalProjDBSize | Long | No | ローカル投影DBの最大サイズ（デフォルト: 32000000） | > 0 |

### 入力データソース

FP-Growth: DataFrame（itemsCol: Array型カラムを含む）。各行がトランザクション（アイテムの集合）。
PrefixSpan: DataFrame（sequenceCol: ArrayType(ArrayType(T))型カラム）。各行がアイテムセットの系列。

## 出力仕様

### 出力データ

#### FPGrowth
| 項目名 | 型 | 説明 |
|--------|-----|------|
| freqItemsets | DataFrame(items, freq) | 頻出アイテムセットとその出現頻度 |
| associationRules | DataFrame(antecedent, consequent, confidence, lift, support) | 相関ルール |
| prediction | Array[T] | transform()による推薦結果 |

#### PrefixSpan
| 項目名 | 型 | 説明 |
|--------|-----|------|
| freqSequences | DataFrame(sequence, freq) | 頻出系列パターンとその出現頻度 |

### 出力先

FP-Growth: freqItemsets/associationRulesはDataFrame。transform()でpredictionカラムを追加。
PrefixSpan: findFrequentSequentialPatterns()がDataFrameを返す。

## 処理フロー

### 処理シーケンス

```
1. FP-Growth fit()
   1-1. スキーマバリデーション（itemsColがArray型か検証）
   1-2. NULL行のフィルタリング
   1-3. MLlib FPGrowthの設定と実行
   1-4. 頻出アイテムセットのDataFrame生成
   1-5. FPGrowthModelの生成（freqItemsets, itemSupport, numTrainingRecords保持）

2. FPGrowthModel transform()
   2-1. 相関ルールの生成（minConfidenceでフィルタリング）
   2-2. ルールのブロードキャスト
   2-3. 各トランザクションに対し適用可能ルールの consequentを収集
   2-4. predictionカラムの追加

3. PrefixSpan findFrequentSequentialPatterns()
   3-1. スキーマバリデーション
   3-2. MLlib PrefixSpanの設定と実行
   3-3. 頻出系列パターンのDataFrame生成
```

### フローチャート

```mermaid
flowchart TD
    A[開始: FPGrowth.fit] --> B[スキーマ検証]
    B --> C[NULL行フィルタ]
    C --> D[MLlib FPGrowth実行]
    D --> E[freqItemsets DataFrame生成]
    E --> F[FPGrowthModel生成]
    F --> G[transform呼び出し]
    G --> H[相関ルール生成]
    H --> I[ルールブロードキャスト]
    I --> J[UDFでルール適用]
    J --> K[prediction追加]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-69-01 | サポート閾値 | minSupport * データ件数以上の出現頻度を持つアイテムセットのみ抽出 | FP-Growth |
| BR-69-02 | 信頼度閾値 | confidence >= minConfidenceのルールのみ生成 | 相関ルール生成 |
| BR-69-03 | NULL無視 | itemsColがNULLの行はfit()時に無視される | FP-Growth |
| BR-69-04 | 推薦ルール | transform()で既存アイテムに含まれないconsequentのみ推薦 | FP-Growth transform |
| BR-69-05 | ルールキャッシュ | minConfidenceが変更されない限りassociationRulesをキャッシュ | FPGrowthModel |

### 計算ロジック

- サポート: support(X) = count(X) / N
- 信頼度: confidence(X→Y) = support(X∪Y) / support(X)
- リフト: lift(X→Y) = confidence(X→Y) / support(Y)

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

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IllegalArgumentException | スキーマエラー | itemsColがArray型でない | Array型カラムを指定 |
| IllegalArgumentException | スキーマエラー | sequenceColがArrayType(ArrayType)でない | 正しい型のカラムを指定 |

### リトライ仕様

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

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

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

## パフォーマンス要件

FP-GrowthはPFP（Parallel FP-Growth）として並列実行される。numPartitionsで並列度を制御。transform()時の相関ルールはドライバーに収集されブロードキャストされるため、大量ルール時はドライバーメモリに注意。

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

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

## 備考

- FP-Growth: Spark 2.2.0で導入
- PrefixSpan: Spark 2.4.0で導入
- FP-GrowthはEstimator/Modelパターン、PrefixSpanは直接実行メソッド
- Li et al., "PFP: Parallel FP-Growth for Query Recommendation" に基づく並列実装
- transform()での推薦はルールベースのため、ALS等の協調フィルタリングとは異なるアプローチ

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FPGrowth.scala | `mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala` | **44-115行目**: FPGrowthParamsでminSupport/minConfidence/itemsCol定義 |
| 1-2 | PrefixSpan.scala | `mllib/src/main/scala/org/apache/spark/ml/fpm/PrefixSpan.scala` | **29-92行目**: PrefixSpanParamsでminSupport/maxPatternLength定義 |

**読解のコツ**: FP-GrowthはEstimator[FPGrowthModel]パターンだが、PrefixSpanはEstimatorではなくParams直接継承。PrefixSpanはfindFrequentSequentialPatterns()メソッドで結果を得る。

#### Step 2: FP-Growth Estimatorを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FPGrowth.scala | `mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala` | **128-203行目**: FPGrowthクラスのfit()/genericFit() |

**主要処理フロー**:
1. **162-163行目**: genericFit()でStorageLevelチェック
2. **170行目**: NULL行フィルタとRDD変換
3. **171-173行目**: MLlib FPGrowth設定
4. **179-181行目**: items.count()とparentModel.run(items)
5. **182-186行目**: freqItemsetsのDataFrame生成
6. **192行目**: FPGrowthModel生成（freqItemsets, itemSupport, inputRowCount）

#### Step 3: FPGrowthModelの推薦処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FPGrowth.scala | `mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala` | **218-335行目**: FPGrowthModelクラス |

**主要処理フロー**:
- **255-265行目**: associationRulesプロパティ（minConfidenceに基づくキャッシュ付き）
- **285-305行目**: genericTransform()でルールのブロードキャストと UDFによる推薦
- **293-300行目**: 各トランザクションに対しルールの前件部が全て含まれるか確認し、consequentを収集

#### Step 4: PrefixSpanを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | PrefixSpan.scala | `mllib/src/main/scala/org/apache/spark/ml/fpm/PrefixSpan.scala` | **106-170行目**: findFrequentSequentialPatterns() |

**主要処理フロー**:
- **138-148行目**: スキーマ検証とデータ変換
- **154-157行目**: MLlib PrefixSpanの設定
- **159-163行目**: 実行とDataFrame生成

#### Step 5: 相関ルール生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | FPGrowth.scala | `mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala` | **393-432行目**: AssociationRules.getAssociationRulesFromFP() |

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

```
FPGrowth.fit(dataset)
    |
    +-- genericFit(dataset)
    |       +-- items.persist()
    |       +-- MLlibFPGrowth.run(items)
    |       +-- freqItemsets DataFrame生成
    |       +-- FPGrowthModel(uid, freqItemsets, itemSupport, inputRowCount)
    |
FPGrowthModel.transform(dataset)
    |
    +-- associationRules (キャッシュ付き)
    |       +-- AssociationRules.getAssociationRulesFromFP()
    |               +-- MLlibAssociationRules.run()
    |
    +-- genericTransform(dataset)
            +-- rules.collect() → broadcast
            +-- predictUDF: 各行に対しルール適用
```

### データフロー図

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

DataFrame           FPGrowth.fit()                 FPGrowthModel
(items:         --> MLlib FPGrowth実行          --> (freqItemsets,
 Array[T])          頻出アイテムセット抽出            associationRules,
                                                     itemSupport)

DataFrame           FPGrowthModel.transform()      DataFrame
(items)        --> ルール適用                   --> (items + prediction)
                    ブロードキャスト+UDF

DataFrame           PrefixSpan                     DataFrame
(sequence:     --> .findFrequentSeq...()       --> (sequence, freq)
 Array[Array[T]])   頻出系列パターン抽出
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FPGrowth.scala | `mllib/src/main/scala/org/apache/spark/ml/fpm/FPGrowth.scala` | ソース | FP-Growth ml API（Estimator/Model/AssociationRules） |
| PrefixSpan.scala | `mllib/src/main/scala/org/apache/spark/ml/fpm/PrefixSpan.scala` | ソース | PrefixSpan ml API |
| FPGrowth.scala | `mllib/src/main/scala/org/apache/spark/mllib/fpm/FPGrowth.scala` | ソース | MLlib層のFP-Growthアルゴリズム |
| PrefixSpan.scala | `mllib/src/main/scala/org/apache/spark/mllib/fpm/PrefixSpan.scala` | ソース | MLlib層のPrefixSpanアルゴリズム |
| AssociationRules.scala | `mllib/src/main/scala/org/apache/spark/mllib/fpm/AssociationRules.scala` | ソース | MLlib層の相関ルール生成 |
