LESSON 30分

ストーリー

田中VPoE
MLモデルの開発で最もコストがかかるのは何だと思う?
あなた
モデルのチューニングですか?
田中VPoE
いや、フィーチャーエンジニアリングだ。データサイエンティストの作業時間の60-80%がフィーチャーの作成に費やされている。しかも、チームAが作ったフィーチャーをチームBが知らずに同じものを再作成するという無駄が発生する
あなた
フィーチャーを一元管理して再利用できるようにする仕組みが必要ですね
田中VPoE
それがフィーチャーストアだ。フィーチャーの定義、計算、保存、提供を一元管理する。さらに重要なのは「学習時と推論時で同じフィーチャーを使う」ことを保証する。これをTraining-Serving Skew(学習-推論の不整合)と呼び、モデルの精度を大きく損なう原因になる

フィーチャーストアとは

Training-Serving Skew問題

Training-Serving Skew:

学習時(オフライン):
  SQL: SELECT AVG(amount) FROM orders
       WHERE customer_id = ? AND order_date >= DATE_SUB(today, 90)
  → 過去90日の平均購入額を計算(BigQueryで実行)

推論時(オンライン):
  Python: orders = get_recent_orders(customer_id, days=90)
          avg_amount = sum(o.amount for o in orders) / len(orders)
  → 同じロジックだが異なる実装(アプリケーションコードで実行)

問題:
  - SQLとPythonで丸め処理が異なる
  - 学習時は日次バッチで計算、推論時はリアルタイムで計算
  - 日付の境界条件が微妙に異なる
  → モデルの精度が本番で低下する

フィーチャーストアの解決策

フィーチャーストア:

┌─────────────────────────────────────────────┐
│           フィーチャーストア                    │
│                                              │
│  ┌──────────────────────────────────────┐   │
│  │  フィーチャー定義(Feature Definition) │   │
│  │  customer_avg_purchase_90d:           │   │
│  │    entity: customer_id               │   │
│  │    sql: AVG(amount) WHERE            │   │
│  │         order_date >= today - 90     │   │
│  │    ttl: 1 day                        │   │
│  └──────────────────────────────────────┘   │
│                    │                         │
│         ┌──────────┴──────────┐              │
│         ↓                     ↓              │
│  ┌──────────────┐   ┌──────────────┐        │
│  │ オフラインストア │   │ オンラインストア │        │
│  │ (BigQuery)    │   │ (Redis)      │        │
│  │ 学習データ用   │   │ 推論用        │        │
│  │ 大量データ     │   │ 低レイテンシ   │        │
│  └──────────────┘   └──────────────┘        │
│         │                     │              │
│         ↓                     ↓              │
│  学習パイプライン        推論エンドポイント     │
│  (同じフィーチャー定義で計算)                  │
└─────────────────────────────────────────────┘

フィーチャーストアのアーキテクチャ

主要コンポーネント

コンポーネント役割実装例
フィーチャー定義フィーチャーの計算ロジックと型を宣言Python DSL, SQL
オフラインストア学習用の大量のフィーチャーデータを格納BigQuery, S3 + Parquet
オンラインストア推論用の最新フィーチャーを低レイテンシで提供Redis, DynamoDB
フィーチャーレジストリフィーチャーのメタデータ、バージョン、リネージカタログ連携
マテリアライゼーションオフライン→オンラインのデータ同期バッチ or ストリーム

主要ツール比較

ツールライセンスオフラインオンラインストリーミング特徴
FeastOSSBigQuery, S3Redis, DynamoDBKafka対応軽量、マルチクラウド
Tecton商用Spark/SnowflakeDynamoDBネイティブエンタープライズ向け
Vertex AI Feature StoreGCPBigQueryBigtableDataflowGCP統合
SageMaker Feature StoreAWSS3DynamoDBKinesisAWS統合
HopsworksOSS/商用HiveMySQL/RonDBKafkaフル機能

Feastによるフィーチャーストアの実装

フィーチャー定義

# feature_repo/features.py
from feast import Entity, Feature, FeatureView, FileSource
from feast.types import Float64, Int64, String
from datetime import timedelta

# エンティティ定義
customer = Entity(
    name="customer_id",
    description="顧客の一意識別子"
)

# データソース(オフラインストア)
customer_features_source = FileSource(
    path="gs://data-lake/gold/customer_features/",
    timestamp_field="feature_timestamp"
)

# フィーチャービュー定義
customer_features = FeatureView(
    name="customer_features",
    entities=[customer],
    ttl=timedelta(days=1),
    schema=[
        Feature(name="avg_purchase_90d", dtype=Float64),
        Feature(name="total_orders_30d", dtype=Int64),
        Feature(name="days_since_last_login", dtype=Int64),
        Feature(name="support_tickets_90d", dtype=Int64),
        Feature(name="plan_type", dtype=String),
    ],
    source=customer_features_source,
    description="顧客の行動フィーチャー(チャーン予測用)"
)

フィーチャーの取得

# 学習時(オフライン: 過去のフィーチャーを取得)
from feast import FeatureStore

store = FeatureStore(repo_path="feature_repo")

# 学習データの取得(Point-in-time correct join)
training_data = store.get_historical_features(
    entity_df=entity_df,  # customer_id + timestamp
    features=[
        "customer_features:avg_purchase_90d",
        "customer_features:total_orders_30d",
        "customer_features:days_since_last_login",
        "customer_features:support_tickets_90d",
        "customer_features:plan_type",
    ]
).to_df()

# 推論時(オンライン: 最新のフィーチャーを取得)
online_features = store.get_online_features(
    features=[
        "customer_features:avg_purchase_90d",
        "customer_features:total_orders_30d",
        "customer_features:days_since_last_login",
    ],
    entity_rows=[{"customer_id": "cust_12345"}]
).to_dict()
# レイテンシ: < 10ms(Redis)

Point-in-Time Correct Join

データリーク防止

Point-in-Time Correct Join:

学習時に「未来のデータ」を使ってしまう問題を防ぐ

誤ったJoin:
  学習データ: 2025年1月1日に解約した顧客のフィーチャー
  フィーチャー: 2025年1月15日時点のlogin_count(= 0)
  → 解約後のデータを使って学習 → データリーク → 精度が異常に高い

Point-in-Time Correct Join:
  学習データ: 2025年1月1日に解約した顧客のフィーチャー
  フィーチャー: 2024年12月31日時点のlogin_count(= 解約直前の値)
  → 解約前のデータのみで学習 → 正しいモデル

「フィーチャーストアは『MLエンジニアとデータエンジニアの橋渡し』だ。データ基盤のGold層で計算したフィーチャーをストアに格納し、MLモデルに提供する。データ品質が担保されたフィーチャーが、信頼性の高いMLモデルを支える」 — 田中VPoE


まとめ

ポイント内容
Training-Serving Skew学習と推論で異なるフィーチャー計算ロジックが原因の精度低下
フィーチャーストアフィーチャーの定義・計算・保存・提供を一元管理
オフライン/オンライン学習用は大量データ(BigQuery)、推論用は低レイテンシ(Redis)
Point-in-Time未来のデータを使わない正しいJoinでデータリークを防止

チェックリスト

  • Training-Serving Skew問題とその影響を説明できる
  • フィーチャーストアのオフライン/オンラインストアの違いを理解した
  • Feastの基本的な使い方(定義、取得)を理解した
  • Point-in-Time Correct Joinの重要性を説明できる

次のステップへ

次は「演習:MLOps基盤を設計しよう」です。Step 5で学んだMLOpsパイプラインとフィーチャーストアを使って、DataFlow社のチャーン予測基盤を設計します。


推定読了時間: 30分