Digital Reactor
合成データ・プライバシー

合成データから個人は特定できてしまわないか:プライバシー品質の4つの測り方

合成データから個人は特定できてしまわないか:プライバシー品質の4つの測り方

はじめに

合成データを生成しても、それが本当に個人を守れているかは、生成しただけでは分かりません。元データの特徴を保ちながらプライバシーを守るという目的は、裏を返せば「どこまで元データに似せてよいか」という線引きの問題です。線を引くには、似すぎていないかを測る物差しが要ります。その物差しにあたる指標を、識別可能性・メンバーシップ推論・属性開示・差分プライバシーの4つに整理して、それぞれの考え方とPythonでの計算例を示します。

対象読者:

  • 合成データの生成や活用に携わるデータサイエンティスト、機械学習エンジニア
  • プライバシー保護技術(PET)やデータ匿名化に関心のある研究者、開発者
  • 企業のデータガバナンスやコンプライアンスを担当する方

記事のポイント:

  • 合成データのプライバシーを評価する4つの主要なアプローチ(識別可能性、メンバーシップ推論、属性開示、差分プライバシー)を理解できる。
  • 各評価指標の直感的な意味と、それを測るための具体的な手法がわかる。
  • 各指標をPythonの短いコードでどう計算するかがわかる。

プライバシー品質を測る4つの観点

合成データから元の個人がどの程度推測されうるか、その測り方は一つではありません。攻撃者が何を知っていて何を狙うかによって、見るべきリスクが変わるためです。ここでは次の観点で評価します。

観点何を評価するか
識別可能性スコア合成レコードが実データの実質的なコピーになっていないか
メンバーシップ推論攻撃ある個人が学習データに含まれていたと当てられないか
属性開示リスク年齢や性別など一部の情報から、病名など未知の機密属性を推測されないか
差分プライバシー生成プロセス自体がどれだけ強い保護を保証しているか

最初の3つは生成後のデータやモデルを事後的に測る指標で、最後の差分プライバシーだけは生成の仕組みに組み込む保証です。以下、一つずつ確認します。

識別可能性スコア:実データのコピーになっていないか

まず基本となるのが、合成データから元の実データを再識別できるリスク、識別可能性(identifiability)の評価です。個々の合成レコードが元の実レコードと近すぎるなら、それは実質的にデータをコピーして配っているのと変わりません。近さを測るので、距離ベースの指標がよく使われます。

代表的な指標は2つあります。最近傍レコードへの距離(DCR: Distance to Closest Record)は、各合成レコードに対して最も近い実レコードを探し、その距離を測ります。距離の平均値などが全体的に小さければ、合成データが実データに酷似しており、リスクが高いと判断します。

最近傍距離比(NNDR: Nearest Neighbor Distance Ratio)はDCRを正規化した指標で、合成レコードから最近傍の実レコードへの距離を、その実レコードから別の最近傍の実レコードへの距離で割ります。この比率が1に近い合成レコードは、実データの分布から離れて特定の実レコードのそばにだけ寄っている、つまり単純なコピーの可能性が高いと読めます。

DCRをscikit-learnで計算する

DCRの計算は数行で書けます。実データで最近傍探索モデルを作り、各合成データ点から最も近い実データ点までの距離を求めて、その平均を取ります。

import numpy as np
from sklearn.neighbors import NearestNeighbors

# 実データと合成データを準備
real_data = np.random.rand(1000, 10)
synthetic_data = np.random.rand(500, 10)

# 実データを学習させ、最近傍探索モデルを構築
nn_model = NearestNeighbors(n_neighbors=1).fit(real_data)

# 各合成データ点から最も近い実データ点までの距離を計算
distances, _ = nn_model.kneighbors(synthetic_data)

# DCRスコア (例: 距離の平均値)
dcr_score = np.mean(distances)
print(f"Distance to Closest Record (平均): {dcr_score}")

メンバーシップ推論攻撃:学習に使われた個人を当てられるか

個々のデータがそのままコピーされていなくても、生成モデルが学習データを過剰に「記憶」している場合があります。このリスクを測るのがメンバーシップ推論攻撃(membership inference attack, MIA)です。

考え方は単純で、あるデータがモデルの学習に使われたかどうかを当てる攻撃を自分でシミュレートし、その成功率をリスクの目安にします。攻撃が簡単に成功するなら、モデルは「誰が学習データにいたか」という情報を出力から漏らしていることになります。例えば医療データなら、あるレコードが学習に含まれていたと分かるだけで「この人はこの病院の患者だった」ことが露見します。

攻撃モデルは次の手順で作ります。

  1. 合成モデルの学習に使われたデータ(member)と、使われなかったデータ(non-member)を用意します。
  2. これらのデータを合成モデルに入力し、その際の出力(損失値や予測確率など)を取得します。一般的に、学習に使われたデータは損失が小さくなる傾向があります。
  3. membernon-memberかを正解ラベルとし、モデルの出力を特徴量として、別の分類器(攻撃モデル)を学習させます。
  4. この攻撃モデルの精度(攻撃成功率)が高いほど、メンバーシップ情報が漏洩しているリスクが高いと評価できます。

損失値を手がかりに攻撃モデルを学習させる

以下は、モデルの損失値を特徴量として攻撃モデルを学習させ、その精度を評価する骨組みです。実際に使うときは、手元の生成モデルに対して損失を計算する部分を差し替えます。

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

# 1. 攻撃用データセットを準備 (ここではモデルの損失値を特徴量とする)
# 実際には、データを与えたときの合成モデルの損失を計算する関数が必要
# member_losses = get_loss(member_data, synthetic_generator)
# non_member_losses = get_loss(non_member_data, synthetic_generator)

# ダミーデータで代用
member_losses = np.random.rand(500, 1) * 0.5       # 学習データは損失が小さいと仮定
non_member_losses = np.random.rand(500, 1) * 0.5 + 0.5 # 未学習データは損失が大きいと仮定

# ラベルを作成 (1: member, 0: non-member)
X_attack = np.vstack([member_losses, non_member_losses])
y_attack = np.hstack([np.ones(500), np.zeros(500)])

# 2. 攻撃モデルを学習・評価
X_train, X_test, y_train, y_test = train_test_split(X_attack, y_attack, test_size=0.3)
attack_model = LogisticRegression().fit(X_train, y_train)
accuracy = attack_model.score(X_test, y_test)

print(f"メンバーシップ推論攻撃の成功率: {accuracy:.2f}")

属性開示リスク:一部の情報から機密属性をたどれるか

攻撃者がターゲットについて一部の情報(準識別子と呼ばれる年齢、性別、郵便番号など)をすでに知っている場合、合成データを手がかりに未知の機密情報(病名、収入など)を推測できてしまうことがあります。これが属性開示(attribute disclosure)で、当人にとっての実害はコピーの検出より直接的です。

測り方としては、合成データを使って準識別子から機密属性を予測するモデルを学習させ、そのモデルが実データの機密属性をどの程度の精度で当てられるかを見ます。予測精度が高いほど、属性開示のリスクが高いことになります。

評価は次の流れで行います。

  1. 合成データ全体を使い、準識別子から機密属性を予測する推論モデル(例:ランダムフォレスト)を学習させます。
  2. 実データから、推論モデルの学習に使っていないテスト用のデータを用意します。
  3. テスト用の実データの準識別子を推論モデルに入力し、機密属性を予測させます。
  4. モデルの予測と、実際の機密属性がどの程度一致するか(正解率など)を評価します。この値がリスクスコアとなります。

準識別子から病名を予測するモデルで測る

pandas DataFrameを想定した、属性開示リスクを評価するコードの例です。

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

# real_data, synthetic_data はDataFrameを想定
# columns: ['age', 'gender', 'zip_code', 'sensitive_disease']

# 準識別子と機密属性を定義
quasi_identifiers = ['age', 'gender', 'zip_code']
sensitive_attribute = 'sensitive_disease'

# 1. 合成データで推論モデルを学習
X_train_syn = synthetic_data[quasi_identifiers]
y_train_syn = synthetic_data[sensitive_attribute]
inference_model = RandomForestClassifier().fit(X_train_syn, y_train_syn)

# 2. 実データで評価
X_test_real = real_data[quasi_identifiers]
y_test_real = real_data[sensitive_attribute]
predictions = inference_model.predict(X_test_real)

# 属性開示リスク (推論モデルの正解率)
risk_score = accuracy_score(y_test_real, predictions)
print(f"属性開示リスク(推論モデルの正解率): {risk_score:.2f}")

差分プライバシー:生成プロセスで保証する

ここまでの指標が生成されたデータを事後的に評価するのに対し、差分プライバシー(differential privacy, DP)はデータ生成プロセスそのものにプライバシー保護を組み込む理論的枠組みです。

DPが保証するのは、データセットに特定の1人のデータが含まれていてもいなくても、アルゴリズムの出力(この場合は合成データ)が統計的にほとんど変わらない、という性質です。出力が変わらないなら、出力を見ても「その人がいたかどうか」は判別できません。

保護の強度はプライバシーバジェット(ε: イプシロン)というパラメータで定量化します。εが小さいほど保護は強くなりますが、その分データの有用性は下がる傾向にあります。DPを実装したモデル(DP-GAN、DP-SGDなど)で生成すれば、「この合成データはε-DPを満たす」と宣言でき、事後評価の指標とは違って数学的な保証としてプライバシー品質を裏付けられます。

ラプラスメカニズムでノイズを加える

DPを実現する最も基本的な手法の一つが、クエリ結果にラプラス分布からサンプリングしたノイズを加えるラプラスメカニズムです。個人のデータが1件変動しても、出力の変動がノイズに紛れる程度に抑えられます。

import numpy as np

# データベースクエリの結果 (例: 平均年齢) にノイズを加えてDPを保証する
def laplace_mechanism(query_result, sensitivity, epsilon):
    scale = sensitivity / epsilon
    noise = np.random.laplace(0, scale, 1)
    return query_result + noise

# 例: 年齢データの平均値クエリ
ages = np.array([25, 30, 40, 50, 60])
true_mean = np.mean(ages)

# 感度: 1人のデータが変化した時のクエリ結果の最大変動幅
# 年齢が0-100歳の場合、1人が抜けると平均値は最大 100/len(ages) 変化する
sensitivity = 100 / len(ages)
epsilon = 0.1  # プライバシーバジェット (小さいほど強力)

dp_mean = laplace_mechanism(true_mean, sensitivity, epsilon)
print(f"真の平均値: {true_mean}")
print(f"DPを適用した平均値 (ε={epsilon}): {dp_mean[0]:.2f}")

まとめ

紹介した4つがプライバシー指標のすべてではありません。古典的なデータ匿名化の概念であるk-匿名性やl-多様性を合成データセットが満たしているか、という確認を求められる場面もあります。ただ、どの指標を使うにしても突き当たるのは、プライバシーと有用性(utility)のトレードオフです。保護を強めるほど、データが元々持っていた統計的な特徴は失われていきます。

だからプライバシー指標だけで合否は決められません。機械学習モデルの予測精度や分布の類似性といった有用性指標と並べて、その用途で許容できる線を決めることになります。手元に評価したい合成データがあるなら、まずDCRとメンバーシップ推論の2つから測ってみてください。どちらも実装が軽く、コピーと過剰な記憶という分かりやすいリスクを先に確認できます。

関連記事

← 技術ブログ一覧へ