合成データのプライバシー品質評価指標

はじめに

近年、機械学習モデルの訓練やデータ分析のために、元データの特徴を保ちつつプライバシーを保護する「合成データ」の活用が進んでいます。しかし、生成されたデータが本当に安全なのか、どのように評価すればよいのでしょうか。この記事では、合成データのプライバシー品質を評価するために用いられる主要な指標を網羅的に解説し、それぞれの概念から具体的な実装例までを分かりやすく紹介します。

この記事を書いたひと

デジタルリアクタ合同会社 代表
機械学習・統計、数値計算などの領域を軸としたソフトウェアエンジニアリングを専門としています。スタートアップからグローバル企業まで、さまざまなスケールの企業にて、事業価値に直結する計算システムを設計・構築してきました。主に機械学習の応用分野において、出版・発表、特許取得等の実績があり、また、IT戦略やデータベース技術等の情報処理に関する専門領域の国家資格を複数保有しています。九州大学理学部卒業。日本ITストラテジスト協会正会員。

対象読者:

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

記事のポイント:

  • 合成データのプライバシーを評価する4つの主要なアプローチ(識別可能性、メンバーシップ推論、属性開示、差分プライバシー)を理解できる。
  • 各評価指標の直感的な意味と、それを測るための具体的な手法がわかる。
  • Pythonによる実装スニペットを通じて、評価手法を実践的に学べる。

合成データのプライバシー評価:4つのアプローチ

生成された合成データが、元の個人データをどの程度推測されにくいか、その「プライバシー品質」を測ることは非常に重要です。評価のアプローチは多岐にわたりますが、主に以下の4つの観点からリスクを評価します。

  • 識別可能性スコア: 合成データが元のデータに酷似していないか、つまり「コピー」されていないかを評価します。
  • メンバーシップ推論攻撃: ある個人がモデルの学習データに含まれていたかどうかを、攻撃者が推測できるかを評価します。
  • 属性開示リスク: データの一部(例:年齢、性別)から、未知の機密情報(例:病名)を推測されるリスクを評価します。
  • 差分プライバシー: データ生成プロセス自体にプライバシー保護を組み込み、その強度を数学的に保証する考え方です。

この記事では、これらの指標を一つずつ掘り下げ、その概念と実装方法を詳しく見ていきます。

識別可能性スコア:データはコピーされていないか?

まず基本となるのが、合成データから元の実データを再識別できるリスク、すなわち「識別可能性」の評価です。個々の合成データレコードが、元になった実データと近すぎると、それは実質的にデータをコピーしているのと同じで、プライバシー上の大きなリスクとなります。このリスクを測るために、距離ベースの指標がよく用いられます。

距離ベースの評価手法

代表的な指標として「最近傍レコードへの距離(DCR)」と「最近傍距離比(NNDR)」があります。

  • DCR (Distance to Closest Record): 各合成データレコードに対して、最も類似している(距離が最も近い)実データレコードを探し、その距離を測定します。この距離の平均値などが全体的に小さい場合、合成データが実データに酷似しており、プライバシーリスクが高いと判断されます。

  • NNDR (Nearest Neighbor Distance Ratio): DCRをさらに正規化した指標です。合成レコードから最近傍の実レコードへの距離を、その実レコードから“別の”最近傍の実レコードへの距離で割った比率を計算します。この比率が1に近いほど、合成データが実データの分布から孤立して実データに近接していることを示唆し、単純なコピーである可能性が高いと判断されます。

DCRの実装例

ここでは、Pythonを使ってDCRを計算する簡単な例を見てみましょう。sklearnライブラリを使い、各合成データ点から最も近い実データ点までの距離を計算し、その平均値を算出します。

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. この攻撃モデルの精度(攻撃成功率)が高いほど、メンバーシップ情報が漏洩しているリスクが高いと評価できます。

MIAの概念的な実装例

以下のコードは、モデルの損失値を特徴量として攻撃モデルを学習させ、その精度を評価する概念的なスニペットです。

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}")

属性開示リスク:未知の情報を推測されないか?

さらに深刻なリスクとして、攻撃者がターゲットに関する情報の一部(準識別子:年齢、性別、郵便番号など)を知っている場合に、合成データを通じて未知の機密情報(属性:病名、収入など)を推測できてしまう「属性開示」があります。

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

属性開示リスクの評価方法

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

  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の基本要素:ラプラスメカニズム

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}")

まとめ:プライバシーと有用性のバランス

この記事では、合成データのプライバシー品質を評価するための主要な指標を解説しました。しかし、紹介した指標が全てではありません。例えば、古典的なデータ匿名化の概念であるk-匿名性l-多様性などを合成データセットが満たしているか評価することもあります。

重要なのは、プライバシーとデータの有用性(Utility)はトレードオフの関係にあるという点です。プライバシー保護を強化すればするほど、データが元々持っていた統計的な特徴は失われがちになります。したがって、合成データを評価する際は、本記事で紹介したようなプライバシー指標と、機械学習モデルの予測精度やデータ分布の類似性といった有用性指標の両面から、目的に応じた最適なバランスを見極めることが不可欠です。