公開された集計値だけを使って、個人単位のデータベースを再構築するデモの結果です。攻撃側は元データを一度も読みません。使用しているデータはすべて人工的に生成したもので、実在の人物の情報は含みません。
回答者 20 人(属性の組み合わせは 288 通り)の人工データから 483 個の集計値を公開したところ、元のデータベースは候補 1 通りに確定し、全員の回答が復元されました。
全校児童 40 人の小規模校です。こういう学校は各地に実在し、 大規模校と同じ種類の表を同じように公表します。ここで使うのは学校要覧・安全計画・ 就学支援状況報告に載る種類の2 属性クロス集計 10 枚 (120 セル)だけ。加工は一切なく、就学援助と掛けるのは学年・地区までです。
| 表 | 出典 | |
|---|---|---|
| 表1 | 学年 × 性別 | 学校要覧「学年別児童数(男女別)」 |
| 表2 | 学年 × 地区 | 学校要覧「通学区域別の在籍者数」 |
| 表3 | 地区 × 通学方法 | 安全計画「地区別の通学手段」 |
| 表4 | 学年 × 通学方法 | 安全計画「学年別の通学手段」 |
| 表5 | 学年 × きょうだい | 学校評価資料「在校生にきょうだいがいる児童数」 |
| 表6 | 性別 × 通学方法 | 安全計画「男女別の通学手段」 |
| 表7 | 性別 × 地区 | 学校要覧「男女・地区別」 |
| 表8 | 地区 × きょうだい | 学校評価資料「地区別のきょうだい在籍」 |
| 表9 | 学年 × 就学援助 | 就学支援状況報告「学年別の対象者数」 |
| 表10 | 地区 × 就学援助 | 就学支援状況報告「地区別の対象者数」 |
絞り込む値は「学年=5年・性別=男・地区=港」の就学援助受給者数です。 該当する児童は 1 人。 この値はどの表にも載っていません。 0 人から順に仮定して、ありえないものを潰していきます。
| 仮定 | 判定 | 根拠にした公表統計 |
|---|---|---|
| 0 人 | 矛盾 | 「学年 × 地区」より 学年=4年・地区=港 = 1 人 「学年 × 地区」より 学年=5年・地区=港 = 1 人 「学年 × 地区」より 学年=6年・地区=港 = 2 人 「性別 × 地区」より 性別=女・地区=港 = 0 人 ほか 3 件 |
| 1 人 | 矛盾しない | 唯一残る候補 |
→ 受給者数は 1 人に確定。 つまり全員が受給です。 この条件に当てはまる児童は校内でただ 1 人なので、「その 1 人が誰か」を知っている人にとって、本人の就学援助の状況がそのまま分かったことになります。
ここでいう「矛盾」は比喩ではありません。 ある値を仮定して制約を全部並べ、それを満たす児童の配置が 1 つも存在しないこと (INFEASIBLE)をソルバが証明しています。さらに、その矛盾を導くのに実際に要った統計だけを 残すよう削り込んでいるので、上の表の「根拠」は名指しできる最小の集合です。
同じやり方で洗い出すと、この学校では 86 通りの組み合わせについて値が確定します。 組み合わせは互いに重なるので、実際に状況が割れたのは 29 / 40 人 (72%)です。 うち受給していることが割れた児童は 1 人 (2 通りの組み合わせが同じ児童を指しています)。 公表セルそのものと、単一の公表セルから自明に導けるものは除いた数です。
のべ人数で数えると 134 人になりますが、これは 全校人数を超えます。同じ児童が複数の組み合わせで確定するためで、実人数ではありません。
下の「手数」は、矛盾で潰した候補の数です。人数の多いグループほど候補が多く、 何段階も場合分けして絞り込むことになります。
| 条件 | 人数 | 結果 | 手数 | 使った表 |
|---|---|---|---|---|
| 学年=5年・性別=男・地区=港 | 1 | 全員が受給 | 1 | 地区 × 就学援助、学年 × 地区、学年 × 就学援助、性別 × 地区 |
| 学年=5年・地区=港・きょうだい=なし | 1 | 全員が受給 | 1 | 地区 × きょうだい、地区 × 就学援助、学年 × 地区、学年 × 就学援助 |
| 学年=2年・地区=中央・きょうだい=あり | 4 | 全員が非受給 | 4 | 地区 × 就学援助、学年 × 地区、学年 × 就学援助 |
| 学年=2年・性別=男・地区=中央 | 3 | 全員が非受給 | 3 | 地区 × 就学援助、学年 × 地区、学年 × 就学援助 |
| 学年=2年・地区=中央・通学方法=徒歩 | 3 | 全員が非受給 | 3 | 地区 × 就学援助、学年 × 地区、学年 × 就学援助 |
| 学年=5年・地区=中央・通学方法=徒歩 | 3 | 全員が非受給 | 3 | 地区 × 就学援助、学年 × 地区、学年 × 就学援助 |
| 学年=4年・性別=男・地区=中央 | 3 | 全員が非受給 | 3 | 地区 × 就学援助、学年 × 就学援助 |
| 学年=4年・地区=中央・通学方法=徒歩 | 3 | 全員が非受給 | 3 | 地区 × 就学援助、学年 × 就学援助 |
| 学年=3年・地区=東・きょうだい=なし | 3 | 全員が非受給 | 3 | 地区 × 就学援助、学年 × 就学援助 |
| 学年=4年・地区=中央・きょうだい=なし | 3 | 全員が非受給 | 3 | 地区 × 就学援助、学年 × 就学援助 |
| 学年=4年・性別=男・きょうだい=なし | 3 | 全員が非受給 | 3 | 学年 × 就学援助 |
| 学年=3年・通学方法=徒歩・きょうだい=あり | 3 | 全員が非受給 | 3 | 学年 × 就学援助 |
データ生成の seed は選んでいます。受給側が割れる例のほうが実害が伝わりやすいためです。複数の seed で同じことが起きるかは uv run python experiments/deduction.py --sweep 3,5,7,11,13,16,18,19,20,21,22,23,24 で確かめられます(時間がかかるので CI では回していません)。
生徒 400 人の中学校です。 統計への加工は一切ありません— 丸めもノイズも入れず、正確な人数を そのまま公表します。公表するのは学校要覧・部活動報告・就学支援状況報告などに実際に 載っていそうな表だけです。センシティブな属性は就学援助の受給有無としました。
| # | 表 | 出典 |
|---|---|---|
| 1 | 学年 × クラス | 学校要覧「学級編制」 |
| 2 | 学年 × クラス × 性別 | 学校要覧「学級編制(男女別)」 |
| 3 | 学年 × 出身小学校 | 学校要覧「入学者の状況」 |
| 4 | 学年 × クラス × 出身小学校 | 学級編成資料 |
| 5 | 学年 × 通学方法 | 安全指導計画「通学手段の状況」 |
| 6 | 出身小学校 × 通学方法 | 安全指導計画「校区別の通学手段」 |
| 7 | 学年 × クラス × 通学方法 | 安全指導計画「学級別の通学手段」 |
| 8 | 学年 × 部活動 | 部活動報告「加入状況」 |
| 9 | 性別 × 部活動 | 部活動報告「男女別加入状況」 |
| 10 | 学年 × クラス × 部活動 | 部活動報告「学級別加入状況」 |
| 11 | 学年 × 性別 × 部活動 | 部活動報告「学年・男女別加入状況」 |
| 12 | 学年 × 就学援助 | 就学支援状況報告「学年別」 |
| 13 | 性別 × 就学援助 | 就学支援状況報告「男女別」 |
| 14 | 出身小学校 × 就学援助 | 就学支援状況報告「地域別」 |
| 15 | 通学方法 × 就学援助 | 就学支援状況報告「通学手段別」 |
就学援助が出てくるのは、学年別・男女別・地域別・通学手段別という粗い表だけ です。個人名も、個人を指す欄もありません。
4 属性以内で校内に 1 人しかいない生徒——つまり周囲の人が個人を言い当てられる 生徒——は 121 人います。それでも 検査した 121 人の受給状況は 1 人も確定しません (反例で棄却 94 人 / 上下限を解いて証明 27 人 / 判断できなかった 0 人)。
「これなら安全そう」という直感は、この粒度では正しい のです。
同じ学校の 3年B組(33 人)について、担任や 学年団が実際に作りそうな表を 12 枚 (77 セル)集めます。就学援助は人数だけで、他の属性と 掛けた表は入れません—そんな表は作らないし、作れば問題になるからです。
結果は候補 >200 通り、 正解率 0.22。 復元できません。
同じ 33 人に対して、属性の組み合わせを 3 個まで網羅的に 公表した場合(41 枚 / 771 セル)、 候補 1 通り・ 正解率 100% となり、全員の回答が 就学援助の受給状況まで含めて確定します。
ただし学校がこんな集計を作ることはありません。効いている表を調べると 「通学方法 × 委員会」「部活動 × 委員会 × 就学援助」といったものが並びます。誰も作らない表です。 (771 セルのうち実際に効いているのは 71 セル・26 枚でした。)
では現実にどこが危ないのか。統計機関の小地域集計です。 国勢調査の町丁字別集計や米国センサスのブロック別集計は、数百人規模の地域に対して属性の 組み合わせを網羅的に公表します。2020 年の米国センサスで再構築攻撃が現実の問題になったのは、 まさにこの「網羅的な公表」が実際に行われているためでした。
| 公表の仕方 | 人数 | 表 | セル | 結果 |
|---|---|---|---|---|
| 全校(学校要覧など) | 400 | 15 | 267 | 誰も特定できず |
| 3年B組(学級資料) | 33 | 12 | 77 | 復元できず |
| 3年B組(網羅的な集計) | 33 | 41 | 771 | 全員の回答が確定 |
危険なのは「小さい集団」そのものではなく、 小さい集団に対して網羅的な集計を出すことです。学校が出す程度の枚数なら、 粒度を細かくしても復元されません。一方、統計機関の小地域集計は網羅性の側で危険域に 入ります。
公開されているのは「〜な人が何人」という集計値だけです。それがなぜ 個人単位のデータに戻ってしまうのか、手順は 3 つしかありません。
n1, …, n288 と置きます。人を 1 人ずつ変数に
すると、並び替えただけの同じ答えが大量に出てしまうためです。= 3 と書きます。公開された集計値の数だけ式ができ
(このページでは 483 本)、さらに「全員で 20 人」という式が 1 本
加わります。ポイントは、集計値を 1 つ公開することは、方程式を 1 本渡すことと同じ だということです。式が変数の数に追いついてくると、解は一気に絞られます。
4 人・2 属性まで縮めて手計算で追える最小例を
uv run python -m src.tutorial で実行できます。
| 項目 | 値 |
|---|---|
| 回答者数 | 20 |
| スキーマ | demo6 |
| データ生成の seed | 20240501 |
| 統計生成の seed | 7 |
| 公開したクロス集計の次数 | 1 属性、2 属性、3 属性 |
| 公開した集計値の数 | 483 |
| クロス集計表の数 | 41 |
| うち人数 0 のセル | 142 個(29%) |
| 統計への加工 | 加工なし(正確な集計値) |
| ソルバ | ortools-cpsat |
同じデータを、公開するクロス集計の深さだけ変えて 3 通り試した結果です(実験 E1〜E3)。確定した人数は、どのレコード型に属するかがソルバによって証明された人の割合です。
| 実験 | 公開範囲 | 集計値の数 | 候補DB数 | 確定した人数 | 正解率 | 一意か |
|---|---|---|---|---|---|---|
| E1 | 1 属性のみ | 16 | >100 | 0% | 0.032 | いいえ |
| E2 | 1〜2 属性 | 121 | >100 | 5% | 0.451 | いいえ |
| E3 | 1〜3 属性 | 483 | 1 | 100% | 1.000 | はい |
1 属性の集計(いわゆる単純集計)だけならまだ安全に見えますが、3 属性のクロス集計まで出した時点で候補は 1 通りになり、全員の回答が復元されます。
「候補DB数」は、公開されたすべての集計値と矛盾しないデータの作り方の数です。これが 1 になった時点で元データが確定します。数え尽くせた場合は厳密な数、そうでない場合は証明済みの下限(>N)だけを載せています— 推測値は一切出していません。
1 属性 → 2 属性 → 3 属性の順に公開していく、いちばん自然な出し方です。
| 公開した集計値の数 | 候補DB数 | 復元の進み方 | 正解率 |
|---|---|---|---|
| 0 | >100 | 0% | 0.000* |
| 9 | >100 | 0% | 0.078* |
| 27 | >100 | 0% | 0.072* |
| 53 | >100 | 0% | 0.190* |
| 83 | >100 | 0% | 0.307* |
| 119 | >100 | 5% | 0.422* |
| 159 | >100 | 5% | 0.431* |
| 204 | 76 | 5% | 0.536 |
| 252 | 10 | 50% | 0.740 |
| 305 | 8 | 55% | 0.750 |
| 361 | 6 | 70% | 0.800 |
| 420 | 1 | 100% | 1.000 |
| 483 | 1 | 100% | 1.000 |
集計値 420 個の時点で一意に確定
同じ集計値を、順番だけランダムにしたものです。
| 公開した集計値の数 | 候補DB数 | 復元の進み方 | 正解率 |
|---|---|---|---|
| 0 | >100 | 0% | 0.000* |
| 9 | >100 | 0% | 0.025* |
| 27 | >100 | 0% | 0.086* |
| 53 | >100 | 10% | 0.522* |
| 83 | 18 | 55% | 0.783 |
| 119 | 1 | 100% | 1.000 |
| 159 | 1 | 100% | 1.000 |
| 204 | 1 | 100% | 1.000 |
| 252 | 1 | 100% | 1.000 |
| 305 | 1 | 100% | 1.000 |
| 361 | 1 | 100% | 1.000 |
| 420 | 1 | 100% | 1.000 |
| 483 | 1 | 100% | 1.000 |
集計値 119 個の時点で一意に確定
候補が複数残っているとき、「複数あります」で終わらせません。どの候補でも一致する事実と、候補によって変わる事実を機械的に切り分けます。候補データベース 1 通りすべてにわたる範囲。レコード型まで確定した人数は 20 人(100%)。
| 条件 | 人数 | 出どころ |
|---|---|---|
| disease_b=0 | 13 | 公開済み |
| gender=F | 13 | 公開済み |
| age_group=30s | 10 | 公開済み |
| disease_a=0 | 10 | 公開済み |
| disease_a=1 | 10 | 公開済み |
| occupation=Admin | 8 | 公開済み |
| occupation=Sales | 8 | 公開済み |
| disease_b=1 | 7 | 公開済み |
曖昧さは残っていません。公開統計だけでデータベースが完全に確定します。
「統計をたくさん出しすぎたから」なのか、「特定の組み合わせが効いたから」なのかを切り分けます。
公開統計から 1 つずつ取り除いて解き直しました(483 個を検証)。結果: 単独で決定的な統計は 1 つもありません。どれか 1 つを外しても、残りだけで一意に再構築できてしまいます。つまり「この 1 表さえ出さなければ安全だった」という表は存在しません。
逆に、貪欲に削れるだけ削ると、483 個の統計は 46 個(1 属性の表 9 個、2 属性の表 33 個、3 属性の表 4 個)まで減らせて、それでも一意に再構築できます(検証済み: はい)。この部分集合はどれ 1 つ外しても成立しなくなります。
つまり原因は「数が多かったこと」でも「特定の 1 表」でもなく、ある特定の組み合わせです。公開する表の数を数えているだけでは気づけません。
公開する数値を丸めたり、ノイズを載せたり、人数の少ないセルを伏せたりする定番の対策を、同じ攻撃にかけて比べました。平均誤差は公開値が真の値からどれだけずれたか(=利用者が被る不便さ)、正解率は攻撃者が復元できた割合です。
正解率は、ソルバが列挙した候補の平均です。候補を数え尽くせた行に限り、攻撃者が残った候補から 1 つを無作為に選んだときの期待値にあたります。数え尽くせなかった行(* 印)は、ソルバが先に出した候補だけの平均であり、候補空間上の期待値ではありません。最良は最も当たっている候補ですが、元データを持たない攻撃者にはどれが最良かを見分ける手段がありません。
| 公開方式 | 平均誤差 | 候補DB数 | 正解率 | 最良 | 完全一致 | 備考 |
|---|---|---|---|---|---|---|
| 加工なし | 0.00 | 1 | 1.000 | 1.000 | はい | |
| 2 の倍数に丸め | 0.45 | 1 | 1.000 | 1.000 | はい | |
| 3 の倍数に丸め | 0.58 | 4 | 0.613 | 0.650 | いいえ | |
| 5 の倍数に丸め | 1.00 | 1 | 0.150 | 0.150 | いいえ | 一意だが不正解 |
| 10 の倍数に丸め | 1.47 | >50 | 0.093* | 0.150 | いいえ |
| 公開方式 | 平均誤差 | 候補DB数 | 正解率 | 最良 | 完全一致 | 備考 |
|---|---|---|---|---|---|---|
| 加工なし | 0.00 | 1 | 1.000 | 1.000 | はい | |
| ガウスノイズ σ=0.5 | 0.30 | 1 | 1.000 | 1.000 | はい | |
| ガウスノイズ σ=1 | 0.71 | 1 | 0.500 | 0.500 | いいえ | 一意だが不正解 |
| ガウスノイズ σ=2 | 1.45 | 3 | 0.317 | 0.350 | いいえ | |
| ガウスノイズ σ=4 | 2.92 | 6 | 0.300 | 0.300 | いいえ |
| 公開方式 | 平均誤差 | 候補DB数 | 正解率 | 最良 | 完全一致 | 備考 |
|---|---|---|---|---|---|---|
| 加工なし(ε = ∞) | 0.00 | 1 | 1.000 | 1.000 | はい | |
| Laplace ε=0.1 | 392.33 | 1 | 0.000 | 0.000 | いいえ | 一意だが不正解 |
| Laplace ε=0.5 | 78.45 | 10 | 0.045 | 0.050 | いいえ | |
| Laplace ε=1 | 39.24 | >50 | 0.078* | 0.100 | いいえ | |
| Laplace ε=5 | 7.85 | >50 | 0.162* | 0.200 | いいえ | |
| Laplace ε=20 | 1.95 | 4 | 0.450 | 0.450 | いいえ | |
| Laplace ε=100 | 0.30 | 1 | 1.000 | 1.000 | はい |
プライバシーモデル: 隣接関係は「add/remove one record (unbounded DP)」、1 つの表の L1 感度は 1、予算は 41 個の表へ逐次合成で均等配分。注意: 回答者数 N は正確に公開しており、この ε の保証には含まれません。再構築攻撃の研究では標準的な設定ですが、前提であることに変わりはありません。
| 公開方式 | 平均誤差 | 候補DB数 | 正解率 | 最良 | 完全一致 | 備考 |
|---|---|---|---|---|---|---|
| 秘匿なし | 0.00 | 1 | 1.000 | 1.000 | はい | |
| 1 人以下を秘匿(ルール非公表) | 0.00 | 1 | 1.000 | 1.000 | はい | |
| 1 人以下を秘匿(ルール公表) | 0.00 | 1 | 1.000 | 1.000 | はい | |
| 2 人以下を秘匿(ルール非公表) | 0.00 | 9 | 0.856 | 1.000 | はい | |
| 2 人以下を秘匿(ルール公表) | 0.00 | 2 | 0.950 | 1.000 | はい | |
| 3 人以下を秘匿(ルール非公表) | 0.00 | >50 | 0.326* | 0.550 | いいえ | |
| 3 人以下を秘匿(ルール公表) | 0.00 | >50 | 0.512* | 0.800 | いいえ | |
| 5 人以下を秘匿(ルール非公表) | 0.00 | >50 | 0.125* | 0.200 | いいえ | |
| 5 人以下を秘匿(ルール公表) | 0.00 | >50 | 0.135* | 0.250 | いいえ |
秘匿は数値を歪めないので平均誤差は 0 のままです。代償は誤差ではなく、公表できるセルが減ること自体にあります。また「ルール公表」の行のほうが候補が少ない点に注目してください。秘匿ルールが公表されていると、あるセルが伏せられている事実そのものが「そのセルは k 人以下」という情報になり、伏せたセルの数だけ上限の制約が増えるためです。秘匿は情報を消しきれていません。
読み取れることが 3 つあります。小さな加工はほとんど効きません(丸め幅 2 や σ=0.5 のノイズでは、完全な復元がそのまま成立します)。効く強さまで上げると、公開値そのものが使い物にならなくなります(この表が平均誤差と正解率を並べているのは、その二者択一を同時に見るためです)。そして数値を歪める対策より、セルを伏せる対策のほうがよく効きます— ただし伏せたこと自体が情報になるので、消えてはいません。
どの行も同じ公開統計の集合から、同じ 16 個を出発点にして、1 回に 1 個ずつ足していきます(最大 140 回)。回数を使い切った場合は、確定した数ではなく下限として書いています。
| 統計の選び方 | 一意になるまでに必要な数 | 最終的な候補DB数 | 正解率 |
|---|---|---|---|
| ランダムな順に足す | 126 | 1 | 1.000 |
| 低い次数から順に足す | >156 | >30 | 0.500 |
| 情報利得が最大の統計を選ぶ | 53 | 1 | 1.000 |
同じ集計値の集合でも、賢く選べば必要な数は数分の 1 になります。「公開した集計値は数百個だけだから安全」という理屈が成り立たないのはこのためです。
自分の主張を壊しにいって見つかった限界です。都合の悪い結果も含めて載せます。
このページの数値はすべて以下のファイルから来ています。なお、元の個票データは意図的に公開していません。
| ファイル | 内容 |
|---|---|
| exact.json | ケース A: 全実行結果(1 つずつ外した検証を含む) |
| rounding.json | ケース B: 丸めの比較 |
| noise.json | ケース C: ランダムノイズの比較 |
| differential_privacy.json | ケース D: 差分プライバシーの比較とプライバシーモデル |
| suppression.json | ケース E: 小セル秘匿の比較 |
| school.json | 学校シナリオ: 全校集計と学級別集計の比較 |
| deduction.json | 小規模校: 確定してしまう値の一覧と絞り込みの筋道 |
| strategies.json | 統計の選び方の比較 |
| progression.csv | 候補の縮小過程(1 ステップ 1 行) |
| strategies.csv | 選び方ごとの各ラウンド(1 ラウンド 1 行) |
| reconstructed.csv | 再構築された個票 |
| statistics.json | 攻撃者に渡した公開統計そのもの |
| schema.json | 攻撃者に渡したスキーマ |
このページの各実行に使った seed・データ設定・クエリ集合・ソルバ設定です。同じ設定なら同じ結果になります。
{
"exact": {
"config": {
"schema_preset": "demo6",
"n_records": 20,
"dataset_seed": 20240501,
"correlation": 0.6,
"levels": [
1,
2,
3
],
"include_zeros": true,
"max_statistics": null,
"statistics_seed": 7,
"noise": {
"kind": "none",
"base": 5,
"sigma": 1.0,
"epsilon": 1.0,
"clamp_negative": false
},
"noise_label": "加工なし(正確な集計値)",
"suppress_at_or_below": null,
"disclose_suppression_rule": false
},
"solver_config": {
"solver": "ortools-cpsat",
"mode": "auto",
"max_solutions": 100,
"time_limit": 60.0,
"random_seed": 0,
"representation": "record-type frequency"
}
},
"rounding": {
"config": {
"schema_preset": "demo6",
"n_records": 20,
"dataset_seed": 20240501,
"correlation": 0.6,
"levels": [
1,
2,
3
],
"include_zeros": true,
"max_statistics": null,
"statistics_seed": 7,
"noise": {
"kind": "none",
"base": 5,
"sigma": 1.0,
"epsilon": 1.0,
"clamp_negative": false
},
"noise_label": "加工なし(正確な集計値)",
"suppress_at_or_below": null,
"disclose_suppression_rule": false
},
"solver_config": {
"solver": "ortools-cpsat",
"mode": "auto",
"max_solutions": 50,
"time_limit": 60.0,
"random_seed": 0,
"representation": "record-type frequency"
}
},
"noise": {
"config": {
"schema_preset": "demo6",
"n_records": 20,
"dataset_seed": 20240501,
"correlation": 0.6,
"levels": [
1,
2,
3
],
"include_zeros": true,
"max_statistics": null,
"statistics_seed": 7,
"noise": {
"kind": "none",
"base": 5,
"sigma": 1.0,
"epsilon": 1.0,
"clamp_negative": false
},
"noise_label": "加工なし(正確な集計値)",
"suppress_at_or_below": null,
"disclose_suppression_rule": false
},
"solver_config": {
"solver": "ortools-cpsat",
"mode": "auto",
"max_solutions": 50,
"time_limit": 60.0,
"random_seed": 0,
"representation": "record-type frequency"
}
},
"differential_privacy": {
"config": {
"schema_preset": "demo6",
"n_records": 20,
"dataset_seed": 20240501,
"correlation": 0.6,
"levels": [
1,
2,
3
],
"include_zeros": true,
"max_statistics": null,
"statistics_seed": 7,
"noise": {
"kind": "none",
"base": 5,
"sigma": 1.0,
"epsilon": 1.0,
"clamp_negative": false
},
"noise_label": "加工なし(正確な集計値)",
"suppress_at_or_below": null,
"disclose_suppression_rule": false
},
"solver_config": {
"solver": "ortools-cpsat",
"mode": "auto",
"max_solutions": 50,
"time_limit": 60.0,
"random_seed": 0,
"representation": "record-type frequency"
}
},
"suppression": {
"config": {
"schema_preset": "demo6",
"n_records": 20,
"dataset_seed": 20240501,
"correlation": 0.6,
"levels": [
1,
2,
3
],
"include_zeros": true,
"max_statistics": null,
"statistics_seed": 7,
"noise": {
"kind": "none",
"base": 5,
"sigma": 1.0,
"epsilon": 1.0,
"clamp_negative": false
},
"noise_label": "加工なし(正確な集計値)",
"suppress_at_or_below": null,
"disclose_suppression_rule": false
},
"solver_config": {
"solver": "ortools-cpsat",
"mode": "auto",
"max_solutions": 50,
"time_limit": 60.0,
"random_seed": 0,
"representation": "record-type frequency"
}
},
"school": {
"config": {
"n_students": 400,
"dataset_seed": 20260401,
"attributes": [
"学年",
"クラス",
"性別",
"出身小学校",
"通学方法",
"部活動",
"委員会",
"就学援助"
],
"sensitive": "就学援助",
"noise": "なし(正確な集計値)",
"class": "3年B組"
},
"solver_config": {
"solver": "ortools-cpsat",
"mode": "auto",
"max_solutions": 100,
"time_limit": 25.0,
"random_seed": 0,
"representation": "record-type frequency"
}
},
"deduction": {
"config": {
"n_students": 40,
"dataset_seed": 20,
"attributes": [
"学年",
"性別",
"地区",
"通学方法",
"きょうだい",
"就学援助"
],
"sensitive": "就学援助",
"noise": "なし(正確な集計値)",
"n_record_types": 576,
"aid_recipients": 6,
"seed_was_chosen": true
},
"solver_config": {
"solver": "ortools-cpsat",
"mode": "auto",
"max_solutions": 100,
"time_limit": 10.0,
"random_seed": 0,
"representation": "record-type frequency"
}
},
"strategies": {
"config": {
"schema_preset": "demo6",
"n_records": 20,
"dataset_seed": 20240501,
"correlation": 0.6,
"levels": [
1,
2,
3
],
"include_zeros": true,
"max_statistics": null,
"statistics_seed": 7,
"noise": {
"kind": "none",
"base": 5,
"sigma": 1.0,
"epsilon": 1.0,
"clamp_negative": false
},
"noise_label": "加工なし(正確な集計値)",
"suppress_at_or_below": null,
"disclose_suppression_rule": false
},
"solver_config": {
"solver": "ortools-cpsat",
"mode": "auto",
"max_solutions": 30,
"time_limit": 60.0,
"random_seed": 0,
"representation": "record-type frequency"
}
}
}攻撃者が使ったのは、すべて「〜な人が何人」という集計値です。どれ 1 つとして、単体では個人を指していません。それでも十分な数を重ねて公開すれば、個人単位の回答はそのまま復元されます。
集計値であることと、個人が守られていることは同じではありません。公開する統計を評価するときは、1 つ 1 つが匿名かどうかではなく、公開済みのものと組み合わさったときに何が決まってしまうかを見る必要があります。