Mímisbrunnr知恵の泉

← MLOps 一覧

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

📎 前提:再現性とバージョニング | 関連:データエンジニアリング 全体目次(データエンジニアリング)

要点(BLUF)

1. なぜデータを版管理するのか

ML の再現性は再現性とバージョニングで見たとおりコード・データ・環境の三位一体です。このうちデータは最も管理が雑になりがちです。train_v2.csv を上書きしてしまえば、過去のモデルがどのデータで作られたかは永遠に失われます。データバージョニングは「学習に使ったデータの瞬間を凍結保存する」仕組みです。

2. 内容ベースの識別(content-addressable)

ファイル名は嘘をつきます(finalが最終でない)。信頼できるのは中身そのもの。中身のハッシュを ID にすると:

これは Git がファイルをハッシュで管理するのと同じ発想で、DVC・lakeFS などのデータバージョニングツールの基礎です。

3. 図解:データレジストリと学習の紐付け

flowchart LR
  S["生データソース"] --> H["内容ハッシュを計算"]
  H --> R["データレジストリ(ハッシュとメタデータ)"]
  G["コード(Gitコミット)"] --> T["学習実行"]
  R --> T
  T --> M["モデル+出自(コード版とデータ版)"]

学習実行にコード版(Gitハッシュ)とデータ版(内容ハッシュ)の両方を入力として記録すれば、モデルから「いつのコードといつのデータで作られたか」を逆引きできます。

4. 動く最小例:ハッシュベースのデータレジストリ

データを内容ハッシュで登録し、メタデータを添え、同一データの再登録を検知する最小レジストリです。

import hashlib
import numpy as np

class DataRegistry:
    def __init__(self):
        self.store = {}   # hash -> metadata

    @staticmethod
    def _hash(arr):
        return hashlib.sha256(np.ascontiguousarray(arr).tobytes()).hexdigest()[:12]

    def register(self, name, arr):
        h = self._hash(arr)
        if h in self.store:
            return h, "既存(同一内容)"
        self.store[h] = {
            "name": name,
            "shape": arr.shape,
            "mean": round(float(arr.mean()), 4),
            "n_null": int(np.isnan(arr).sum()),
        }
        return h, "新規登録"

rng = np.random.default_rng(0)
v1 = rng.normal(0, 1, (1000, 5))
v1_copy = v1.copy()                 # 同じ中身
v2 = v1.copy(); v2[0, 0] += 0.5     # 1要素だけ変更

reg = DataRegistry()
h1, s1 = reg.register("train", v1)
h1c, s1c = reg.register("train", v1_copy)
h2, s2 = reg.register("train", v2)

print(f"v1      : hash={h1} -> {s1}")
print(f"v1_copy : hash={h1c} -> {s1c}")
print(f"v2      : hash={h2} -> {s2}")
print(f"v1とv2は同一データ? {h1 == h2}")
print(f"レジストリ登録数 : {len(reg.store)}")
print(f"v1のメタデータ   : {reg.store[h1]}")

出力:

v1      : hash=7a82c1a6b301 -> 新規登録
v1_copy : hash=7a82c1a6b301 -> 既存(同一内容)
v2      : hash=d180a6268cd5 -> 新規登録
v1とv2は同一データ? False
レジストリ登録数 : 2
v1のメタデータ   : {'name': 'train', 'shape': (1000, 5), 'mean': -0.0045, 'n_null': 0}

出力の意味:同一内容(v1 と v1_copy)はハッシュが一致して重複登録されず、1要素だけ変えた v2 は別 ID として登録されました。これで「このモデルはハッシュ 7a82… のデータで学習した」と機械的に固定でき、データの取り違えや知らぬ間の改変を検知できます。メタデータ(形状・平均・欠損数)を添えることで、後からデータの素性も追えます。

5. 運用の勘所

なぜそうするのか

データを版管理しない最大の代償は「障害が起きても原因を切り分けられない」ことです。本番モデルが急に劣化したとき、データが変わったのかコードが変わったのか分からなければ復旧できません。データに不変の ID を与えておけば、「直前まで正常だったデータ版」へ即座に戻れ、再学習の比較基準も保てます。

⚠️ よくある落とし穴

対応 lab

関連ノート