# 機能設計書 91-シーケンス特徴量

## 概要

本ドキュメントは、TensorFlowにおけるシーケンス特徴量（Sequence Feature Column）機能の設計を記述する。時系列データ向けのシーケンス特徴量カラムを提供し、RNNなどのシーケンスモデルへの入力データ変換を行う。

### 本機能の処理概要

**業務上の目的・背景**：時系列データや可変長シーケンスデータ（例：ユーザの行動履歴、テキストのトークン列、センサーデータ列）を機械学習モデルに入力する際には、可変長データを適切なテンソル形式に変換する必要がある。本機能は、Feature Column APIのシーケンス拡張として、カテゴリカルシーケンスおよび数値シーケンスデータを、LSTM・GRUなどのRNN層に直接入力可能な密テンソルに変換する。

**機能の利用シーン**：ユーザの購買履歴や閲覧履歴をRNNモデルで学習する際、シーケンスカテゴリカルカラム（`sequence_categorical_column_with_identity`等）を`embedding_column`と組み合わせて利用する。また、時系列センサーデータには`sequence_numeric_column`を用いて数値シーケンスをそのまま入力する。

**主要な処理内容**：
1. シーケンスカテゴリカルカラムの生成（identity, hash_bucket, vocabulary_file, vocabulary_list）
2. シーケンス数値カラムの生成（`sequence_numeric_column`）
3. SparseTensorからDenseTensorへの変換とシーケンス長の計算
4. コンテキスト入力とシーケンス入力の結合（`concatenate_context_input`）

**関連システム・外部連携**：Feature Column v2 API（`feature_column_v2.py`）の`SequenceCategoricalColumn`クラス、`SequenceDenseColumn`基底クラス、および`SequenceFeatures` Kerasレイヤーと連携する。

**権限による制御**：特になし。ただし本APIは非推奨であり、Keras前処理レイヤーへの移行が推奨されている。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はAPI機能であり、直接関連する画面はない |

## 機能種別

データ変換処理（特徴量エンジニアリング）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | string | Yes | 入力特徴量を識別する一意の文字列キー | 空文字不可 |
| num_buckets | int | Yes（identity） | 入力値の範囲 [0, num_buckets) | 1以上 |
| hash_bucket_size | int | Yes（hash_bucket） | ハッシュバケット数 | 1より大きい |
| vocabulary_file | string | Yes（vocabulary_file） | 語彙ファイルのパス | ファイルが存在すること |
| vocabulary_list | list | Yes（vocabulary_list） | 語彙リスト | 空でないこと、重複なし |
| shape | tuple | No | 数値データの形状（デフォルト: (1,)） | 各次元が正の整数 |
| default_value | float/int | No | パディング用デフォルト値 | dtype互換 |
| dtype | DType | No | データ型（デフォルト: float32） | float変換可能 |
| normalizer_fn | callable | No | 正規化関数 | callableであること |

### 入力データソース

`tf.io.parse_example`でパースされたSparseTensor形式のシーケンスデータ。`VarLenFeature`として解析される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| dense_tensor | Tensor [batch_size, max_seq_len, feature_dim] | 密テンソルに変換されたシーケンスデータ |
| sequence_length | Tensor [batch_size] | 各サンプルのシーケンス長 |

### 出力先

RNNレイヤー（SimpleRNN, LSTM, GRU等）への入力として使用される。`SequenceFeatures`レイヤー経由で取得。

## 処理フロー

### 処理シーケンス

```
1. FeatureColumnオブジェクト生成
   └─ sequence_categorical_column_with_* または sequence_numeric_column を呼び出し
2. parse_example_spec生成
   └─ VarLenFeature(dtype)をパース仕様として返却
3. 特徴量変換（transform_feature）
   └─ SparseTensorの取得、normalizer_fnの適用（数値カラムの場合）
4. シーケンス密テンソル取得（get_sequence_dense_tensor）
   └─ sparse_tensor_to_denseでSparseTensorを密テンソルに変換
   └─ [batch_size, T, variable_shape]にreshape
   └─ sequence_length_from_sparse_tensorでシーケンス長を計算
5. （オプション）コンテキスト入力の結合
   └─ concatenate_context_inputでコンテキストをタイムステップ分タイリング
```

### フローチャート

```mermaid
flowchart TD
    A[入力: SparseTensor] --> B[parse_example_specでVarLenFeature定義]
    B --> C[transform_feature: 特徴量変換]
    C --> D{normalizer_fnあり?}
    D -->|Yes| E[normalizer_fn適用]
    D -->|No| F[そのまま]
    E --> G[get_sequence_dense_tensor]
    F --> G
    G --> H[sparse_tensor_to_dense変換]
    H --> I[reshape: batch_size x T x feature_dim]
    I --> J[sequence_length計算]
    J --> K[TensorSequenceLengthPair返却]
    K --> L{コンテキスト入力あり?}
    L -->|Yes| M[concatenate_context_input]
    L -->|No| N[RNNレイヤーへ入力]
    M --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-91-01 | 非推奨警告 | 本APIは非推奨であり、Keras前処理レイヤーへの移行が推奨される | 全てのAPI呼び出し時 |
| BR-91-02 | dtype制約（数値） | sequence_numeric_columnのdtypeはfloat変換可能である必要がある | sequence_numeric_column使用時 |
| BR-91-03 | OOV処理 | num_oov_bucketsとdefault_valueは同時指定不可 | vocabulary系カラム使用時 |
| BR-91-04 | シーケンス長計算 | 2Dの場合はnum_elementsで除算、3Dの場合はnum_elements=1 | get_sequence_dense_tensor実行時 |

### 計算ロジック

シーケンス長の計算:
- SparseTensorのindicesからrow_idsとcolumn_idsを抽出
- `segment_max(column_ids + 1, row_ids)`で各行の最大列インデックスを取得
- `ceil(seq_length / num_elements)`で要素グルーピング後のシーケンス長を算出

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

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

本機能はデータベース操作を行わない。テンソル演算のみで構成される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ValueError | バリデーション | num_bucketsが1未満 | 1以上の値を指定 |
| ValueError | バリデーション | hash_bucket_sizeが1以下 | 2以上の値を指定 |
| ValueError | バリデーション | vocabulary_listが空または重複 | 一意の値リストを指定 |
| ValueError | バリデーション | dtypeがfloat変換不可（数値カラム） | float互換のdtypeを指定 |
| TypeError | 型エラー | normalizer_fnがcallableでない | callable関数を指定 |
| ValueError | ランク不正 | sequence_inputのrankが3でない | 3次元テンソルを入力 |

### リトライ仕様

リトライは不要。入力バリデーションエラーは即座に例外送出。

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

該当なし。ステートレスなテンソル変換処理。

## パフォーマンス要件

- SparseTensorからDenseTensorへの変換はバッチ単位で実行
- シーケンス長が長い場合、メモリ使用量が増加する（最大シーケンス長分のパディング）

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

- vocabulary_fileの読み込み時はファイルアクセス権限に注意
- ユーザ提供のnormalizer_fnが任意コードを実行する可能性がある

## 備考

- 本APIは非推奨（deprecated）であり、`tf.keras.layers`の前処理レイヤーまたは`tf.keras.utils.FeatureSpace`への移行が推奨されている
- `SequenceFeatures` Kerasレイヤーと組み合わせて使用する

---

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

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

### 推奨読解順序

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

まず、シーケンス特徴量カラムの基底クラスとデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | feature_column_v2.py | `tensorflow/python/feature_column/feature_column_v2.py` | `SequenceDenseColumn`基底クラス（1943-1959行目）と`TensorSequenceLengthPair` namedtuple |
| 1-2 | feature_column_v2.py | `tensorflow/python/feature_column/feature_column_v2.py` | `SequenceCategoricalColumn`クラス（4052-4056行目）、CategoricalColumnを継承 |

**読解のコツ**: `SequenceDenseColumn`は抽象基底クラスで`get_sequence_dense_tensor`メソッドを定義。戻り値は`TensorSequenceLengthPair`（dense_tensor, sequence_length）のnamedtuple。

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

シーケンス特徴量カラムを生成するファクトリ関数群が本モジュールのエントリーポイントである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sequence_feature_column.py | `tensorflow/python/feature_column/sequence_feature_column.py` | ファクトリ関数群（105-397行目） |

**主要処理フロー**:
1. **105-149行目**: `sequence_categorical_column_with_identity` - 整数シーケンスのカテゴリカルカラム生成
2. **155-196行目**: `sequence_categorical_column_with_hash_bucket` - ハッシュバケット方式のカラム生成
3. **202-266行目**: `sequence_categorical_column_with_vocabulary_file` - 語彙ファイル方式のカラム生成
4. **272-333行目**: `sequence_categorical_column_with_vocabulary_list` - 語彙リスト方式のカラム生成
5. **339-397行目**: `sequence_numeric_column` - 数値シーケンスカラム生成

#### Step 3: SequenceNumericColumnクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sequence_feature_column.py | `tensorflow/python/feature_column/sequence_feature_column.py` | `SequenceNumericColumn`クラス（413-507行目） |

**主要処理フロー**:
- **430-432行目**: `parse_example_spec`プロパティ - `VarLenFeature(self.dtype)`を返す
- **434-451行目**: `transform_feature` - normalizer_fnの適用
- **458-487行目**: `get_sequence_dense_tensor` - SparseTensor→DenseTensor変換とシーケンス長計算

#### Step 4: ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | utils.py | `tensorflow/python/feature_column/utils.py` | `sequence_length_from_sparse_tensor`関数（26-48行目） |
| 4-2 | sequence_feature_column.py | `tensorflow/python/feature_column/sequence_feature_column.py` | `concatenate_context_input`関数（53-99行目） |

**主要処理フロー**:
- **26-48行目（utils.py）**: SparseTensorからシーケンス長を計算。`segment_max`で行ごとの最大列インデックスを取得し、`num_elements`で除算
- **53-99行目**: コンテキスト入力を全タイムステップに複製してシーケンス入力に結合

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

```
sequence_categorical_column_with_identity / hash_bucket / vocabulary_file / vocabulary_list
    │
    └─ fc.SequenceCategoricalColumn(fc.categorical_column_with_*)
           │
           ├─ parse_example_spec → VarLenFeature
           ├─ transform_feature → SparseTensor取得
           └─ get_sequence_dense_tensor
                  ├─ sparse_ops.sparse_tensor_to_dense
                  ├─ array_ops.reshape → [batch, T, dim]
                  └─ fc_utils.sequence_length_from_sparse_tensor
                         ├─ math_ops.segment_max
                         └─ math_ops.ceil

sequence_numeric_column
    │
    └─ SequenceNumericColumn(key, shape, default_value, dtype, normalizer_fn)
           │
           ├─ parse_example_spec → VarLenFeature
           ├─ transform_feature → normalizer_fn適用
           └─ get_sequence_dense_tensor
                  ├─ sparse_ops.sparse_tensor_to_dense
                  ├─ array_ops.reshape → [batch, T, dim]
                  └─ fc_utils.sequence_length_from_sparse_tensor

concatenate_context_input(context_input, sequence_input)
    │
    ├─ check_ops.assert_rank / assert_type
    ├─ array_ops.expand_dims + tile
    └─ array_ops.concat
```

### データフロー図

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

SparseTensor          SequenceFeatures Layer
(VarLenFeature)  ───▶  transform_feature()             ───▶  TensorSequenceLengthPair
                       get_sequence_dense_tensor()              ├─ dense_tensor [B, T, D]
                         ├─ sparse_to_dense                     └─ sequence_length [B]
                         ├─ reshape
                         └─ seq_length計算

Context Tensor   ───▶  concatenate_context_input()     ───▶  結合Tensor [B, T, D+C]
[B, C]                   ├─ expand_dims + tile
                         └─ concat
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sequence_feature_column.py | `tensorflow/python/feature_column/sequence_feature_column.py` | ソース | シーケンス特徴量カラムのファクトリ関数とSequenceNumericColumnクラス |
| feature_column_v2.py | `tensorflow/python/feature_column/feature_column_v2.py` | ソース | SequenceDenseColumn基底クラス、SequenceCategoricalColumnクラス |
| utils.py | `tensorflow/python/feature_column/utils.py` | ソース | sequence_length_from_sparse_tensorユーティリティ |
| serialization.py | `tensorflow/python/feature_column/serialization.py` | ソース | FeatureColumnのシリアライズ・デシリアライズ |
