Mímisbrunnr知恵の泉

← MLOps 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:特徴量エンジニアリングのパイプライン化 | 関連:データドリフトとコンセプトドリフトの検知

要点(BLUF)

1. スキューとは何か

モデルは「学習時に見た特徴量の分布」を前提に予測します。推論時に特徴量の作り方がわずかでも違えば、モデルは未知の入力を見せられたのと同じで、精度が落ちます。厄介なのは、オフライン評価(学習データの一部)では完璧に見えること。学習と同じ経路で特徴量を作るので問題が顕在化せず、本番の別経路で初めて崩れます。

2. スキューの3類型

flowchart TB
  S["学習推論スキュー"] --> A["1 変換ロジックの二重実装"]
  S --> B["2 統計量の取り違え"]
  S --> C["3 鮮度と欠損挙動の差"]
  A --> A1["学習はバッチSQL 推論はAPIで別実装 -> 微妙にずれる"]
  B --> B1["推論で学習時平均でなく推論データ平均で標準化"]
  C --> C1["学習は完全な履歴 推論は遅延した最新値や別の欠損補完"]
類型何が起きるか防ぎ方
二重実装学習と推論で別コードがじわじわずれる変換を1つに統一・共有(特徴量エンジニアリングのパイプライン化
統計量取り違え推論で fit し直して別の標準化学習時統計量を保存・再利用(推論は transform のみ)
鮮度・欠損差更新遅延や欠損補完が学習と違う特徴量ストアで一貫供給(特徴量ストア

3. 動く最小例:スキューが精度を落とすことを実証する

学習と本番を**同じ分布(ドリフトなし)**にして、違いを「推論で変換を共有したか」だけに絞ります。推論経路が標準化を取りこぼす(二重実装で片方が抜ける)と何が起きるかを測ります。

import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

rng = np.random.default_rng(0)
# 学習・本番は同じ分布(ドリフトなし)。違いは変換の共有有無だけ
Xtr = rng.normal(5.0, 2.0, (800, 3))
ytr = (Xtr[:, 0] + Xtr[:, 1] - Xtr[:, 2] > 5.0).astype(int)
Xte = rng.normal(5.0, 2.0, (400, 3))
yte = (Xte[:, 0] + Xte[:, 1] - Xte[:, 2] > 5.0).astype(int)

# 学習時の統計量を固定して学習
mu, sd = Xtr.mean(0), Xtr.std(0)
model = LogisticRegression().fit((Xtr - mu) / sd, ytr)

# (A) 正しい:推論も学習時の mu, sd で標準化(変換を共有)
acc_correct = accuracy_score(yte, model.predict((Xte - mu) / sd))

# (B) スキュー:推論経路で標準化を取りこぼし、生の特徴量を渡す
acc_skew = accuracy_score(yte, model.predict(Xte))

print(f"(A) 学習時の変換を共有(正しい) 精度 = {acc_correct:.3f}")
print(f"(B) 推論で標準化を取りこぼし(スキュー)精度 = {acc_skew:.3f}")
print(f"スキューによる精度低下 = {acc_correct - acc_skew:.3f}")

出力:

(A) 学習時の変換を共有(正しい) 精度 = 0.990
(B) 推論で標準化を取りこぼし(スキュー)精度 = 0.578
スキューによる精度低下 = 0.412

出力の意味:学習データと本番データは完全に同じ分布(ドリフトなし)です。それでも、推論経路が標準化変換を取りこぼしただけで精度が 0.990 → 0.578 へ 約41ポイントも崩落しました。モデルは標準化された尺度(平均0・分散1)を前提に係数を学んでいるのに、生のスケール(平均5付近)の入力を渡されたためです。コードの各部分は「正しく」動いていて、ただ学習経路と推論経路で変換が食い違っただけ。オフライン評価では(A)の経路しか通らないので、この崩落は本番で初めて露見します。

4. 運用の勘所

なぜそうするのか

スキューは「コードは正しいのにシステムが間違う」典型で、テストをすり抜けやすい最危険の事故です。防止策がすべて「変換を1つにして共有する」に集約されるのは、ずれの原因が常に「学習用と推論用で別の実体を使ったこと」だからです。実体を1つに保てば、ずれる物理的余地が消えます。

⚠️ よくある落とし穴

対応 lab

関連ノート