【Python】Python SDV 〜 HMASynthesizer 〜

◾️はじめに

https://dk521123.hatenablog.com/entry/2025/12/21/000330

の続き。

https://dk521123.hatenablog.com/entry/2025/12/24/001900

を書いている時に気がついたのだが、外部キーがあるようなデータって
SDV (Synthetic Data Vault)はサポートしているのかって気になった。

 AIに聞いたら、
『SDVの最大の強みは「外部キー(リレーションシップ)」を持った
複数テーブルのサポートにあります』って言ってたので、折角なのでメモ。

目次

【1】外部キーを考慮する合成データを作るには
【2】HMA (Hierarchical Modeling Algorithm)
 1)他モデルとの対比
 2)メリット・デメリット
【3】サンプル
 例1:Hello world
【4】Tips
 1)メタデータをJSONで保存する
 2)学習済みモデルを保存する

【1】外部キーを考慮する合成データを作るには

Metadata クラスで「テーブル同士の親子関係」を定義し、
専用の HMASynthesizer を使用

【2】HMA (Hierarchical Modeling Algorithm)

HMAは、リレーショナルデータベースのように
「親テーブル(例:ユーザー)」と「子テーブル(例:注文履歴)」
があるデータを扱うための専用モデル
 => 特徴:テーブルをまたいだ相関(関係性)を壊さないこと

1)他モデルとの対比

特徴 Single Table系 (CTGAN/GaussianCopula) HMA (HMASynthesizer) PAR (PARSynthesizer)
対象構造 1枚の表(CSV 複数の表(親子関係) 1枚の表(時系列)
データの繋がり なし(1行が独立) 1対多のリレーション 前後の時間的つながり
整合性 行内の整合性のみ テーブル間の参照整合性 時間軸の連続性
典型的な例 顧客リスト(名簿) DB(顧客+注文+配送) センサーログ、株価

2)メリット・デメリット

メリット

* 外部キーの不一致(親にいないIDが子にいる)が理論上発生しない
* 「都会のユーザーは注文回数が多い」といった、テーブルをまたぐルールを再現可能
* 統計モデルをベースにしているため、深層学習(GAN)系よりも比較的計算が速く、
 中規模なDBであれば現実的な時間で学習が終わる

デメリット

* 階層が3段階、4段階(親→子→孫→ひ孫...)と深くなると、
 末端の「孫」や「ひ孫」のデータの再現性が落ちる傾向がある
*  「AとBが互いに参照し合っている(循環参照)」ような複雑なリレーションは扱えない

【3】サンプル

例1:Hello world

import pandas as pd
from sdv.metadata import MultiTableMetadata
from sdv.multi_table import HMASynthesizer

# 1. Sample data creation
users_data = pd.DataFrame({
    'user_id': [1, 2, 3],
    'country': ['JP', 'US', 'US']
})

orders_data = pd.DataFrame({
    'order_id': [101, 102, 103, 104, 105],
    'user_id': [1, 1, 2, 3, 3],  # Outer key to users table
    'amount': [1000, 2000, 1500, 3000, 500]
})

# 2. To create metadata for multi-table data
metadata = MultiTableMetadata()

# Important: "detect_table_from_dataframe" must be called before updating columns or setting keys
metadata.detect_table_from_dataframe(table_name='users', data=users_data)
metadata.detect_table_from_dataframe(table_name='orders', data=orders_data)

# 3. Adjust primary keys and types
# After the tables are registered, update_column will work
metadata.update_column(table_name='users', column_name='user_id', sdtype='id')
metadata.set_primary_key(table_name='users', column_name='user_id')

metadata.update_column(table_name='orders', column_name='order_id', sdtype='id')
metadata.set_primary_key(table_name='orders', column_name='order_id')

# Set foreign key relationship ★注目★
metadata.add_relationship(
    parent_table_name='users',
    child_table_name='orders',
    parent_primary_key='user_id',
    child_foreign_key='user_id'
)

# 4. Learning and synthesis
data = {
    'users': users_data,
    'orders': orders_data
}
synthesizer = HMASynthesizer(metadata)
synthesizer.fit(data)

# Generate synthetic data
synthetic_data = synthesizer.sample(scale=1)

print("--- Synthesis successful! ---")
print("\n[Users Table]")
print(synthetic_data['users'])
print("\n[Orders Table]")
print(synthetic_data['orders'])

【4】Tips

1)メタデータJSONで保存する

# 保存
metadata.save_to_json('my_metadata.json')

# 次回からの読み込み
# from sdv.metadata import MultiTableMetadata
# metadata = MultiTableMetadata.load_from_json('my_metadata.json')

2)学習済みモデルを保存する

# 保存
synthesizer.save('my_synthesizer.pkl')

# 次回からの読み込み
# from sdv.multi_table import HMASynthesizer
# synthesizer = HMASynthesizer.load('my_synthesizer.pkl')

関連記事

Python SDV 〜 入門編 〜
https://dk521123.hatenablog.com/entry/2025/12/21/000330