1. 始める前に
集計した統計情報では、統計情報が関連付けられている個人に関する情報が漏洩することはないとお考えかもしれません。しかし、集計した統計情報から攻撃者が個人に関する機密情報を知る方法は、多数存在します。
この Codelab では、PipelineDP の差分プライベート集計を使用してプライベート統計情報を生成し、個人のプライバシーを保護する方法を学びます。PipelineDP は、Apache Spark や Apache Beam などのバッチ処理システムを使用して、大規模なデータセットに差分プライバシーを適用できる Python フレームワークです。Go で差分プライベート統計情報を計算する方法の詳細については、Privacy on Beam Codelab をご覧ください。
「プライベート」とは、データ内の個人に関するいかなる個人情報も漏洩させない方法で出力が生成されることを意味します。この結果は、差分プライバシー(匿名化の強力なプライバシー概念。ユーザーのプライバシーを保護するために複数のユーザー間でデータを集計するプロセス)によって実現できます。すべての匿名化メソッドで集計が使用されますが、すべての集計メソッドで匿名化が達成されるわけではありません。一方、差分プライバシーは情報漏洩とプライバシーに関してある程度の保証を提供します。
前提条件
- Python の基本知識があること
- 基本的なデータ集計の知識
- pandas、Spark、Beam の使用経験
学習内容
- 差分プライバシーの基本
- PipelineDP を使用して差分プライベート要約統計情報を計算する方法
- プライバシーとユーティリティに関する追加のパラメータを使用して結果を調整する方法
必要なもの
- 独自の環境で Codelab を実行する場合は、パソコンに Python 3.7 以降をインストールする必要があります。
- 独自の環境を使用せずにこの Codelab の手順を行う場合は、Colaboratory にアクセスする必要があります。
2. 差分プライバシーについて
差分プライバシーをより良く理解するために、簡単な例を見てみましょう。
オンライン ファッション小売業者のマーケティング部門で働いていて、どの商品が最も売れやすいかを把握したいとします。
このグラフは、顧客がショップのウェブサイトにアクセスしたときに最初に見た商品(T シャツ、ジャンパー、靴下、ジーンズ)を示しています。T シャツが最も人気のあるアイテムで、靴下が最も人気のないアイテムです。

このグラフは便利そうに見えますが、欠点が 1 つあります。顧客が購入したかどうかや、顧客が 2 番目に閲覧した商品など、追加情報を考慮しようとすると、データ内の個人が特定されるリスクがあります。
このグラフを見ると、最初にジャンパーを見てから実際に購入したお客様は 1 人だけであることがわかります。

プライバシーの観点から、これはよくありません。匿名化された統計情報では、個々の寄与が明らかになってはなりません。どうすればよいですか?ランダムノイズを棒グラフに追加して、精度を少し下げます。
この棒グラフは完全に正確というわけではありませんが、それでもまだ有用であり、個々の寄与が明らかになりません。

差分プライバシーとは、個々の寄与をマスクするために適切な量のランダムノイズを加えることです。
この例は簡略化されています。差分プライバシーを適切に実装することは、より複雑であり、まったく予想外な実装上の微妙な点がいくつもあります。暗号と同様に、差分プライバシーの独自の実装を作成することはおすすめできません。代わりに、PipelineDP を使用できます。
3. PipelineDP をダウンロードしてインストールする
この Codelab には関連するコードとグラフがすべて記載されているため、この Codelab に沿って PipelineDP をインストールする必要はありません。
PipelineDP を試す、自分で実行する、後で使用するには:
- PipelineDP をダウンロードしてインストールします。
pip install pipeline-dp
Apache Beam を使用して例を実行する場合は、次の操作を行います。
- Apache Beam をダウンロードしてインストールします。
pip install apache_beam
この Codelab のコードとデータセットは PipelineDP/examples/codelab/ ディレクトリにあります。
4. 最初に閲覧した商品ごとにコンバージョン指標を計算します。
オンライン ファッション小売業者に勤務しているとします。さまざまな商品カテゴリのうち、最初に見たときにコンバージョン数とコンバージョン値が最も高いのはどのカテゴリかを知りたいと考えています。この情報をマーケティング エージェンシーや他の社内チームと共有したいが、個々の顧客に関する情報の漏洩は防ぎたい。
ウェブサイトで最初に閲覧された商品ごとのコンバージョン指標を計算するには:
PipelineDP/examples/codelab/ディレクトリで、ウェブサイトへのアクセスに関するモック データセットを確認します。
このスクリーンショットは、データセットの例です。ユーザーの ID、ユーザーが閲覧した商品、サイト訪問者がコンバージョンに至ったかどうか、コンバージョンに至った場合はその値が含まれます。
user_id | product_view_0 | product_view_1 | product_view_2 | product_view_3 | product_view_4 | has_conversion | conversion_value |
0 | ジーンズ | t_shirt | t_shirt | なし | なし | false | 0.0 |
1 | ジーンズ | t_shirt | ジーンズ | ジャンパー | なし | false | 0.0 |
2 | t_shirt | ジャンパー | t_shirt | t_shirt | なし | true | 105.19 |
3 | t_shirt | t_shirt | ジーンズ | なし | なし | false | 0.0 |
4 | t_shirt | 靴下 | ジーンズ | ジーンズ | なし | false | 0.0 |
次の指標に関心がある場合:
view_counts: ウェブサイトの訪問者が各商品を最初に見た回数。total_conversion_value: サイト訪問者がコンバージョンしたときに費やした合計金額。conversion_rate: サイト訪問者がコンバージョンに至る割合。
- 非プライベートな方法で指標を生成します。
conversion_metrics = df.groupby(['product_view_0'
])[['conversion_value', 'has_conversion']].agg({
'conversion_value': [len, np.sum],
'has_conversion': np.mean
})
conversion_metrics = conversion_metrics.rename(
columns={
'len': 'view_counts',
'sum': 'total_conversion_value',
'mean': 'conversion_rate'
}).droplevel(
0, axis=1)
前述のように、これらの統計情報からデータセット内の個人に関する情報が明らかになる可能性があります。たとえば、ジャンパーを最初に見た後にコンバージョンに至ったのは 1 人だけでした。22 回の視聴に対するコンバージョン率は約 0.05 です。次に、各棒グラフをプライベートなものに変換する必要があります。
pipeline_dp.NaiveBudgetAccountantクラスでプライバシー パラメータを定義し、分析に使用するepsilon引数とdelta引数を指定します。
これらの引数の設定方法は、特定の問題によって異なります。詳細については、省略可: 差分プライバシー パラメータを調整するをご覧ください。
このコード スニペットでは、次の例の値を使用します。
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=1e-5)
LocalBackendインスタンスを初期化します。
ops = pipeline_dp.LocalBackend()
このプログラムは、Beam や Spark などの追加のフレームワークなしでローカルで実行するため、LocalBackend インスタンスを使用できます。
DPEngineインスタンスを初期化します。
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
PipelineDP では、pipeline_dp.AggregateParams クラスを使用して追加のパラメータを指定できます。このパラメータは、プライベート統計の生成に影響します。
params = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT],
max_partitions_contributed=1,
max_contributions_per_partition=1)
count指標を計算し、LAPLACEノイズ分布を使用することを指定します。max_partitions_contributed引数を1値に設定します。
この引数は、ユーザーが寄与できる異なる訪問の数を制限します。ユーザーが 1 日に 1 回ウェブサイトにアクセスすることを想定しており、1 日に複数回アクセスしてもかまわない。
max_contributions_per_partitions引数を1値に設定します。
この引数は、このケースでは、1 人のユーザーが個々のパーティションまたは商品カテゴリに貢献できる回数を指定します。
privacy_id、partition、valueフィールドの検索場所を指定するdata_extractorインスタンスを作成します。
コードは次のようになります。
def run_pipeline(data, ops):
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=1e-5)
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
params = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT],
max_partitions_contributed=1, # A single user can only contribute to one partition.
max_contributions_per_partition=1, # For a single partition, only one contribution per user is used.
)
data_extractors = pipeline_dp.DataExtractors(
privacy_id_extractor=lambda row: row.user_id,
partition_extractor=lambda row: row.product_view_0
value_extractor=lambda row: row.has_conversion)
dp_result = dp_engine.aggregate(data, params, data_extractors)
budget_accountant.compute_budgets()
return dp_result
- このコードを追加して、Pandas DataFrame を差分プライバシー統計情報を直接計算できる行のリストに変換します。
rows = [index_row[1] for index_row in df.iterrows()]
dp_result_local = run_pipeline(rows, ops) # Returns generator
list(dp_result_local)
おめでとうございます!初めての差分プライベート統計情報を計算できました。
このグラフには、差分プライベート カウントの結果と、先ほど計算した非プライベート カウントの結果が並べて表示されます。

コードを実行したときに表示される棒グラフは、これとは異なる場合がありますが、問題ありません。差分プライバシーのノイズにより、コードを実行するたびに異なる棒グラフが表示されますが、元の非プライベート棒グラフと似ていることがわかります。
プライバシーを保証するためには、プライバシーを保証する目的でパイプラインを複数回実行しないようにすることが非常に重要です。詳細については、複数の統計情報を計算するをご覧ください。
5. パブリック パーティションを使用する
前のセクションで、パーティション(ウェブサイトで最初に靴下を見たユーザー)のすべての訪問データが省略されていたことにお気づきでしょうか。
これは、出力パーティションの存在がユーザーデータ自体に依存する場合に差分プライバシーを確実に保証するための重要なステップである、パーティション選択またはしきい値設定に起因します。このような場合、出力にパーティションが存在するだけで、データ内に個々のユーザーの存在することが漏洩する可能性があります。プライバシー侵害に該当する理由について詳しくは、こちらのブログ投稿をご覧ください。このプライバシー侵害を防ぐため、PipelineDP では、十分な数のユーザーがいるパーティションのみを保持します。
出力パーティションのリストがプライベート ユーザーデータに依存しない場合、このパーティション選択ステップは必要ありません。この例では、ユーザーが最初に目にする可能性のある商品カテゴリをすべて把握しているため、実際にこのようになります。
パーティションを使用するには:
- 可能なパーティションのリストを作成します。
public_partitions_products = ['jeans', 'jumper', 'socks', 't-shirt']
- リストを
run_pipeline()関数に渡します。この関数は、リストをpipeline_dp.AggregateParamsクラスの追加の入力として設定します。
run_pipeline(
rows, ops, total_delta=0, public_partitions=public_partitions_products)
# Returns generator
params = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT],
max_partitions_contributed=1,
max_contributions_per_partition=1,
public_partitions=public_partitions_products)
パブリック パーティションと LAPLACE ノイズを使用している場合は、total_delta 引数を 0 値に設定できます。
結果には、すべてのパーティション(商品)のデータが報告されていることがわかります。

パブリック パーティションを使用すると、より多くのパーティションを保持できるだけでなく、パーティション選択にプライバシー予算を使用しないため、追加されるノイズが約半分になります。そのため、元のカウントとプライベート カウントの差が、以前の実行と比べてわずかに小さくなります。
パブリック パーティションを使用する場合、次の 2 点に注意してください。
- 元データからパーティションのリストを導出する場合は注意が必要です。差分プライベートの方法で行わないと、パイプラインで差分プライバシーが保証されなくなります。詳細については、高度な使用方法: データからパーティションを派生させるをご覧ください。
- 一部のパブリック パーティションにデータがない場合は、差分プライバシーを保持するために、そうしたパーティションにノイズを適用する必要があります。たとえば、データセットやウェブサイトに存在しないズボンなどの商品を追加した場合、それはノイズとなり、実際には商品へのアクセスがないのに、アクセスがあったと結果に表示される可能性があります。
上級: データからパーティションを導出する
同じパイプラインで非公開の出力パーティションの同じリストを使用して複数の集計を行う場合、dp_engine.select_private_partitions() メソッドを使用してパーティションのリストを 1 回導出し、そのパーティションを public_partitions 入力として各集計に提供できます。これはプライバシーの観点から安全であるだけでなく、パイプライン全体でパーティション選択にプライバシー予算を 1 回だけ使用するため、加えるノイズを少なくできます。
def get_private_product_views(data, ops):
"""Obtains the list of product_views in a private manner.
This does not calculate any private metrics; it merely obtains the list of
product_views but does so while making sure the result is differentially private.
"""
# Set the total privacy budget.
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=1e-5)
# Create a DPEngine instance.
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
# Specify how to extract privacy_id, partition_key, and value from a
# single element.
data_extractors = pipeline_dp.DataExtractors(
partition_extractor=lambda row: row.product_view_0,
privacy_id_extractor=lambda row: row.user_id)
# Run aggregation.
dp_result = dp_engine.select_partitions(
data, pipeline_dp.SelectPrivatePartitionsParams(
max_partitions_contributed=1),
data_extractors=data_extractors)
budget_accountant.compute_budgets()
return dp_result
6. 複数の統計情報を計算する
PipelineDP の仕組みを理解したところで、より高度なユースケースで PipelineDP を使用する方法を見ていきましょう。冒頭で述べたように、3 つの統計情報に関心があります。PipelineDP では、AggregateParams インスタンスで同じパラメータを共有する限り、複数の統計情報を同時に計算できます。これについては後で説明します。一度に複数の指標を計算できるため、よりクリーンで簡単であるだけでなく、プライバシーの観点からも優れています。
NaiveBudgetAccountant クラスに指定する epsilon パラメータと delta パラメータは、プライバシー予算という、データから漏洩するユーザーのプライバシーの量を表します。
プライバシー予算について覚えておくべき重要な点は、加法的であるということです。特定のイプシロン(ε)とデルタ(δ)を持つパイプラインを 1 回実行すると、(ε,δ) 予算を使うことになります。2 回実行すると、合計で (2ε, 2δ) の予算を使うことになります。同様に、NaiveBudgetAccountant メソッドで複数の統計情報を計算し、連続してプライバシー予算 ε,δ を使用すると、合計で (2ε, 2δ) の予算を使うことになります。つまり、プライバシーの保証を低下させています。
これを回避するには、同じデータに対して複数の統計情報を計算する必要がある場合は、使用する合計予算で 1 つの NaiveBudgetAccountant インスタンスを使用する必要があります。次に、各集計に使用する epsilon 値と delta 値を指定する必要があります。最終的には、全体的なプライバシー保証は同じになります。ただし、特定の集計の epsilon と delta の値が大きければ大きいほど、精度は高くなります。
これを実際に確認するには、count、mean、sum の統計情報を計算します。
統計情報は、2 つの異なる指標に基づいて計算されます。1 つは conversion_value 指標で、最初に閲覧された商品に基づいて収益額を推測するために使用されます。もう 1 つは has_conversion 指標で、ウェブサイトへの訪問者数と平均コンバージョン率を計算するために使用されます。
指標ごとに、プライベート統計の計算をガイドするパラメータを個別に指定する必要があります。プライバシー予算を 2 つの指標に分割します。has_conversion 指標から 2 つの統計情報を計算するため、初期予算の 3 分の 2 を割り当て、残りの 3 分の 1 を conversion_value 指標に割り当てます。
複数の統計情報を計算するには:
- 3 つの統計情報全体で使用する
epsilonとdeltaの合計値を指定して、プライバシー バジェット アカウンタを設定します。
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=0)
- 指標を計算するように
DPEngineを初期化します。
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
- この指標のパラメータを指定します。
params_conversion_value_metrics = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.SUM],
max_partitions_contributed=1,
max_contributions_per_partition=1,
min_value=0,
max_value=100,
public_partitions=public_partitions,
budget_weight=1/3)
最後の引数では、プライバシー予算の重みを指定します(省略可)。すべてに同じ重みを付けることもできますが、前述のように、この引数を 3 分の 1 に設定します。
また、min_value 引数と max_value 引数を設定して、パーティション内のプライバシー単位によって提供される値に適用される下限と上限を指定します。これらのパラメータは、プライベート合計または平均を計算する場合に必要です。負の値は想定されないため、0 と 100 を妥当な境界と想定できます。
- 関連するデータを抽出し、集計関数に渡します。
data_extractors_conversion_value_metrics = pipeline_dp.DataExtractors(
privacy_id_extractor=lambda row: row.user_id,
partition_extractor=lambda row: row.product_view_0,
value_extractor=lambda row: row.conversion_value)
dp_result_conversion_value_metrics = (
dp_engine.aggregate(data, params_conversion_value_metrics,
data_extractors_conversion_value_metrics))
- 同じ手順で、
has_conversion変数に基づいて 2 つの指標を計算します。
params_conversion_rate_metrics = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT, pipeline_dp.Metrics.MEAN],
max_partitions_contributed=1,
max_contributions_per_partition=1,
min_value=0,
max_value=1,
public_partitions=public_partitions,
budget_weight=2/3)
data_extractors_conversion_rate_metrics = pipeline_dp.DataExtractors(
privacy_id_extractor=lambda row: row.user_id,
partition_extractor=lambda row: row.product_view_0,
value_extractor=lambda row: row.has_conversion)
dp_result_conversion_rate_metrics = (
dp_engine.aggregate(data, params_conversion_rate_metrics,
data_extractors_conversion_rate_metrics))
変更点は pipeline_dp.AggregateParams インスタンスのみです。ここでは、mean と count を集計として定義し、プライバシー バジェットの 3 分の 2 をこの計算に割り当てています。両方の統計情報で同じ貢献度の上限を設定し、同じ has_conversion 変数に基づいて計算する必要があるため、同じ pipeline_dp.AggregateParams インスタンスに結合して同時に計算できます。
budget_accountant.compute_budgets()メソッドを呼び出します。
budget_accountant.compute_budgets()
3 つのプライベート統計情報をすべて、元の統計情報と比較してプロットできます。追加されたノイズによっては、結果が妥当な範囲外になることがあります。この例では、追加されたノイズがゼロを中心に対称であるため、ジャンパーのコンバージョン率と合計コンバージョン値がマイナスになっています。さらなる分析と処理を行う場合は、プライバシー保証に違反することなく、後で最小値を 0 に設定するだけで、これらのプロットをレポートに追加できます。ただし、非公開統計情報を手動で後処理しないことをおすすめします。

7. Beam でパイプラインを実行する
今日のデータ処理では、ローカルで処理できないほど大量のデータを扱う必要があります。代わりに、多くのユーザーは Beam や Spark などの大規模なデータ処理用のフレームワークを使用して、クラウドでパイプラインを実行しています。
PipelineDP は、コードを少し変更するだけで Beam と Spark をサポートします。
private_beam API を使用して Beam でパイプラインを実行するには:
runner変数を初期化し、プライバシー オペレーションをrowsの Beam 表現に適用するパイプラインを作成します。
runner = fn_api_runner.FnApiRunner() # local runner
with beam.Pipeline(runner=runner) as pipeline:
beam_data = pipeline | beam.Create(rows)
- 必要なプライバシー パラメータを使用して
budget_accountant変数を作成します。
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=0)
pcol(非公開コレクション)変数を作成します。これにより、集計がプライバシー要件に準拠することが保証されます。
pcol = beam_data | pbeam.MakePrivate(
budget_accountant=budget_accountant,
privacy_id_extractor=lambda
row: row.user_id)
- 適切なクラスでプライベート集計のパラメータを指定します。
ここでは、商品ビューの合計を計算するため、pipeline_dp.aggregate_params.SumParams() クラスを使用します。
- 集計パラメータを
pbeam.Sumメソッドに渡して、統計情報を計算します。
dp_result = pcol | pbeam.Sum(params)
- 最終的に、コードは次のようになります。
import pipeline_dp.private_beam as pbeam
runner = fn_api_runner.FnApiRunner() # local runner
with beam.Pipeline(runner=runner) as pipeline:
beam_data = pipeline | beam.Create(rows)
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=0)
# Create private collection.
pcol = beam_data | pbeam.MakePrivate(
budget_accountant=budget_accountant,
privacy_id_extractor=lambda row:
row.user_id)
# Specify parameters.
params = pipeline_dp.aggregate_params.SumParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
max_partitions_contributed=1,
max_contributions_per_partition=1,
min_value=0,
max_value=100,
public_partitions=public_partitions_product_views,
partition_extractor=lambda row: row.product_view_0,
value_extractor=lambda row:row.conversion_value)
dp_result = pcol | pbeam.Sum(params)
budget_accountant.compute_budgets()
dp_result | beam.Map(print)
8. 省略可: プライバシー パラメータとユーティリティ パラメータを調整する
この Codelab では、epsilon、delta、max_partitions_contributed パラメータなど、非常に多くのパラメータについて説明しました。これらは、プライバシー パラメータとユーティリティ パラメータという、2 つのカテゴリに大別できます。
プライバシー パラメータ
epsilon パラメータと delta パラメータは、差分プライバシーで提供するプライバシーを定量化します。より正確に言えば、匿名化された出力から潜在的な攻撃者がデータについてどの程度の情報を得られるかを示す指標です。パラメータの値が大きいほど、攻撃者がデータについて得る情報が多くなり、プライバシーのリスクとなります。一方、epsilon パラメータと delta パラメータの値が小さいほど、匿名化するために出力に加える必要のあるノイズが多くなり、匿名化した出力にパーティションを保持するために各パーティションに必要なユニーク ユーザーの数が多くなります。この場合、ユーティリティとプライバシーはトレードオフの関係にあります。
PipelineDP では、NaiveBudgetAccountant インスタンスで合計プライバシー予算を設定するときに、匿名化された出力に必要なプライバシー保証を指定する必要があります。プライバシー保証を維持する場合、集計ごとに別々の NaiveBudgetAccountant インスタンスを慎重に使用するか、パイプラインを複数回実行して、予算を使いすぎないようにする必要があります。
差分プライバシーとプライバシー パラメータの意味について詳しくは、差分プライバシーに関する読書リストをご覧ください。
ユーティリティ パラメータ
ユーティリティ パラメータはプライバシー保証には影響しませんが、精度に影響し、結果として出力の実用性にも影響します。AggregateParams インスタンスで提供され、追加されるノイズをスケーリングするために使用されます。
AggregateParams インスタンスで提供され、すべての集計に適用可能なユーティリティ パラメータは max_partitions_contributed パラメータです。パーティションは、PipelineDP 集計オペレーションによって返されるデータのキーに対応します。そのため、max_partitions_contributed パラメータは、出力でユーザーが寄与する可能性のある個別のキー値の数を制限します。ユーザーの寄与が max_partitions_contributed パラメータの値を超える数のキーに及ぶ場合、寄与の一部が省略され、寄与は max_partitions_contributed パラメータの値どおりになります。
同様に、ほとんどの集計には max_contributions_per_partition パラメータがあります。これらは AggregateParams インスタンスでも提供され、集計ごとに別々の値を設定できます。キーごとにユーザーの寄与を制限します。
出力に追加されるノイズは max_partitions_contributed パラメータと max_contributions_per_partition パラメータでスケーリングされるため、ここではトレードオフの関係にあります。各パラメータに割り当てる値を大きくすると、保持できるデータが多くなりますが、結果的にノイズが多くなります。
一部の集計には、各ユーザーの寄与の限界を指定する min_value パラメータと max_value パラメータが必要です。ユーザーの寄与が min_value パラメータに割り当てられた値よりも低い場合、その値はパラメータの値まで引き上げられます。同様に、ユーザーの寄与が max_value パラメータの値より大きい場合、その値はパラメータの値まで減らされます。元の値をより多く保持するには、より大きな限界を指定する必要があります。ノイズは限界のサイズに合わせてスケーリングされるため、限界を大きくすると保持できるデータが多くなりますが、結果的にノイズが多くなります。
最後に、noise_kind パラメータは、PipelineDP の 2 種類のノイズ メカニズム(GAUSSIAN ノイズと LAPLACE ノイズ)をサポートしています。LAPLACE 分布の方が、小さな寄与限界で優れた実用性が得られます。そのため、PipelineDP ではこれがデフォルトで使用されます。ただし、GAUSSIAN 分布ノイズを使用する場合は、AggregateParams インスタンスで指定できます。
9. 完了
パフォーマンスは良好です。PipelineDP の Codelab を修了し、差分プライバシーと PipelineDP について多くのことを学びました。