Calculer des statistiques privées avec PipelineDP

1. Avant de commencer

Vous pensez peut-être que les statistiques agrégées ne divulguent aucune information sur les personnes auxquelles elles se rapportent. Cependant, un pirate informatique peut obtenir des informations sensibles sur des individus de nombreuses manières à partir de statistiques agrégées.

Dans cet atelier de programmation, vous apprendrez à générer des statistiques privées avec des agrégations à confidentialité différentielle à partir de PipelineDP afin de protéger les données confidentialité. PipelineDP est un framework Python qui vous permet d'appliquer une confidentialité différentielle aux grands ensembles de données à l'aide de systèmes de traitement par lot comme Apache Spark et Apache Beam. Pour en savoir plus sur le calcul de statistiques à confidentialité différentielle dans Go, consultez l'atelier de programmation Privacy on Beam.

Privé signifie que la sortie est produite de manière à ne pas divulguer d'informations privées sur les personnes concernées par les données. Pour ce faire, vous pouvez utiliser la confidentialité différentielle, une notion solide de confidentialité, appelée anonymisation, qui consiste à agréger les données de plusieurs utilisateurs afin de protéger leur vie privée. Toutes les méthodes d'anonymisation utilisent l'agrégation, mais toutes les méthodes d'agrégation n'atteignent pas l'anonymisation. La confidentialité différentielle, quant à elle, offre des garanties mesurables concernant la confidentialité et la fuite d'informations.

Prérequis

  • Connaissance de Python
  • une bonne connaissance des bases de l'agrégation de données ;
  • Connaissance de Pandas, Spark et Beam

Points abordés

  • Principes de base de la confidentialité différentielle
  • Calculer des statistiques récapitulatives à confidentialité différentielle avec PipelineDP
  • Comment affiner vos résultats avec des paramètres supplémentaires de confidentialité et d'utilité

Prérequis

  • Si vous souhaitez exécuter l'atelier de programmation dans votre propre environnement, Python 3.7 ou version ultérieure doit être installé sur votre ordinateur.
  • Si vous souhaitez suivre l'atelier de programmation sans votre propre environnement, vous devez avoir accès à Colaboratory.

2. Comprendre la confidentialité différentielle

Pour mieux comprendre la confidentialité différentielle, prenons cet exemple simple.

Imaginez que vous travaillez dans le service marketing d'un marchand de vêtements en ligne et que vous voulez savoir quels produits sont les plus susceptibles d'être vendus.

Ce graphique indique les produits que les clients ont consultés en premier lorsqu'ils ont visité le site Web du magasin: t-shirts, pulls, chaussettes ou jeans. Le t-shirt est l'article le plus populaire, tandis que les chaussettes sont l'article le moins populaire.

ea813c698889a4c6.png

Cela semble utile, mais il y a un piège. Lorsque vous souhaitez prendre en compte des informations supplémentaires, comme si les clients ont effectué un achat ou quel produit ils ont consulté ensuite, vous risquez de révéler des personnes dans vos données.

Ce graphique vous montre qu'un seul client a d'abord regardé un pull avant d'effectuer un achat:

b7c6f7f891778366.png

Ce n'est pas génial du point de vue de la confidentialité. Les statistiques anonymisées ne doivent pas révéler les contributions individuelles, alors que faites-vous ? Vous ajoutez un bruit aléatoire à vos graphiques à barres pour les rendre un peu moins précis !

Ce graphique à barres n'est pas totalement exact, mais il reste utile et ne révèle pas les contributions individuelles:

b55e8d7f99f6d574.gif

La confidentialité différentielle consiste à ajouter la bonne quantité de bruit aléatoire pour masquer les contributions individuelles.

Cet exemple est trop simpliste. La bonne implémentation de la confidentialité différentielle est plus complexe et s'accompagne d'un certain nombre de subtilités inattendues. Comme pour la cryptographie, il n'est peut-être pas judicieux de créer votre propre implémentation de la confidentialité différentielle. À la place, vous pouvez utiliser PipelineDP.

3. Télécharger et installer PipelineDP

Vous n'avez pas besoin d'installer PipelineDP pour suivre cet atelier de programmation, car vous trouverez dans ce document l'ensemble du code et des graphiques pertinents.

Pour tester PipelineDP, exécutez-le vous-même ou utilisez-le plus tard:

  • Téléchargez et installez PipelineDP:
pip install pipeline-dp

Si vous souhaitez exécuter l'exemple à l'aide d'Apache Beam:

  • Téléchargez et installez Apache Beam:
pip install apache_beam

Vous trouverez le code de cet atelier de programmation et l'ensemble de données dans le répertoire PipelineDP/examples/codelab/.

4. Calcul des métriques de conversion par premier produit consulté

Imaginez que vous travaillez chez un marchand d'articles de mode en ligne et que vous souhaitez savoir quelles catégories de produits génèrent le plus grand nombre et la plus grande valeur de conversions lorsqu'elles sont vues pour la première fois. Vous souhaitez partager ces informations avec votre agence marketing ainsi qu'avec d'autres équipes internes, tout en évitant la fuite d'informations sur un client particulier.

Pour calculer les métriques de conversion pour le premier produit consulté sur le site Web:

  1. Examinez l'ensemble de données fictif concernant les visites de votre site Web dans le répertoire PipelineDP/examples/codelab/.

Cette capture d'écran est un exemple du jeu de données. Elle contient l'ID de l'utilisateur, les produits qu'il a consultés, si celui-ci a effectué une conversion et, le cas échéant, la valeur de la conversion.

user_id

product_view_0

product_view_1

product_view_2

product_view_3

product_view_4

has_conversion

conversion_value

0

Jeans

t_shirt

t_shirt

aucun

aucun

faux

0,0

1

Jeans

t_shirt

Jeans

pull

aucun

faux

0,0

2

t_shirt

pull

t_shirt

t_shirt

aucun

true

105,19

3

t_shirt

t_shirt

Jeans

aucun

aucun

faux

0,0

4

t_shirt

chaussettes

Jeans

Jeans

aucun

faux

0,0

Ces métriques vous intéressent:

  • view_counts: nombre de fois où les visiteurs de votre site Web voient chaque produit en premier.
  • total_conversion_value: montant total dépensé par les visiteurs lorsqu'ils effectuent une conversion.
  • conversion_rate: taux de conversion des visiteurs.
  1. Générez les métriques de manière non privée:
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)

Comme vous l'avez appris précédemment, ces statistiques peuvent révéler des informations sur les personnes figurant dans votre jeu de données. Par exemple, une seule personne a réalisé une conversion après qu'elle a vu un pull. Pour 22 vues, votre taux de conversion est d'environ 0,05. Vous devez maintenant transformer chaque graphique à barres en un graphique privé.

  1. Définissez vos paramètres de confidentialité avec la classe pipeline_dp.NaiveBudgetAccountant, puis spécifiez les arguments epsilon et delta que vous souhaitez utiliser pour votre analyse.

La manière dont vous définissez ces arguments dépend de votre problème particulier. Pour en savoir plus à leur sujet, consultez "Facultatif: ajuster les paramètres de confidentialité différentielle".

Cet extrait de code utilise des exemples de valeurs:

budget_accountant = pipeline_dp.NaiveBudgetAccountant(
     total_epsilon=1, total_delta=1e-5)
  1. Initialisez l'instance LocalBackend:
ops = pipeline_dp.LocalBackend()

Vous pouvez utiliser l'instance LocalBackend, car vous exécutez ce programme localement sans frameworks supplémentaires, tels que Beam ou Spark.

  1. Initialisez l'instance DPEngine:
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)

PipelineDP vous permet de spécifier d'autres paramètres via la classe pipeline_dp.AggregateParams, ce qui affecte la génération de vos statistiques privées.

params = pipeline_dp.AggregateParams(
     noise_kind=pipeline_dp.NoiseKind.LAPLACE,
     metrics=[pipeline_dp.Metrics.COUNT],
     max_partitions_contributed=1,
     max_contributions_per_partition=1)
  1. Indiquez que vous souhaitez calculer la métrique count et utilisez la distribution du bruit de LAPLACE.
  2. Définissez l'argument max_partitions_contributed sur une valeur 1.

Cet argument détermine le nombre de visites différentes auxquelles un utilisateur peut contribuer. Vous attendez des utilisateurs qu'ils visitent le site Web une fois par jour et ne vous souciez pas s'ils le visitent plusieurs fois au cours de la journée.

  1. Définissez l'argument max_contributions_per_partitions sur une valeur 1.

Cet argument indique le nombre de contributions qu'un même visiteur peut apporter à une partition individuelle ou à une catégorie de produits, dans ce cas.

  1. Créez une instance data_extractor qui spécifie où trouver les champs privacy_id, partition et value.

Le code doit se présenter comme suit:

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
  1. Ajoutez le code suivant pour transformer votre DataFrame Pandas en une liste de lignes à partir desquelles vous pouvez calculer directement des statistiques à confidentialité différentielle:
rows = [index_row[1] for index_row in df.iterrows()]
dp_result_local = run_pipeline(rows, ops) # Returns generator
list(dp_result_local)

Félicitations ! Vous avez calculé votre première statistique différentiellement privée !

Ce graphique affiche le résultat de votre décompte différentiellement privé à côté du décompte non privé que vous avez calculé précédemment:

a5a25a00858219ab.png

Le graphique à barres que vous obtenez lorsque vous exécutez le code peut être différent de celui-ci, ce qui n'est pas un problème. En raison du bruit lié à la confidentialité différentielle, vous obtenez un graphique à barres différent chaque fois que vous exécutez le code, mais vous pouvez constater qu'ils sont semblables au graphique à barres non privé d'origine.

Veuillez noter qu'il est très important que les garanties de confidentialité ne soient pas exécutées plusieurs fois pour des raisons de confidentialité. Pour en savoir plus, consultez "Calculer plusieurs statistiques".

5. Utiliser des partitions publiques

Dans la section précédente, vous avez peut-être remarqué que vous avez supprimé toutes les données de visites d'une partition, à savoir les visiteurs qui ont d'abord vu des chaussettes sur votre site Web.

Cela est dû à la sélection des partitions ou au seuil, une étape importante pour garantir des garanties de confidentialité différentielle lorsque l'existence de partitions de sortie dépend des données utilisateur elles-mêmes. Dans ce cas, la simple existence d'une partition dans la sortie peut révéler l'existence d'un utilisateur individuel dans les données. Pour en savoir plus sur les raisons pour lesquelles cela porte atteinte à la confidentialité, consultez cet article de blog. Pour éviter cette violation de la confidentialité, PipelineDP ne conserve que les partitions contenant un nombre suffisant d'utilisateurs.

Lorsque la liste des partitions de sortie ne dépend pas de données utilisateur privées, cette étape de sélection de partition est inutile. C'est en fait le cas pour votre exemple, car vous connaissez toutes les catégories de produits possibles qu'un client pourrait voir en premier.

Pour utiliser des partitions:

  1. Créez une liste de vos partitions possibles:
public_partitions_products = ['jeans', 'jumper', 'socks', 't-shirt']
  1. Transmettez la liste à la fonction run_pipeline(), qui la définit comme entrée supplémentaire de la classe 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)

Si vous utilisez des partitions publiques et du bruit LAPLACE, vous pouvez définir l'argument total_delta sur une valeur 0.

Le résultat indique maintenant que les données de toutes les partitions, ou tous les produits, sont consignées.

a4f6302c8efcd5da.png

Non seulement les partitions publiques vous permettent de conserver plus de partitions, mais elles ajoutent également environ la moitié de plus de bruit, car vous ne dépensez aucun budget de confidentialité pour la sélection des partitions. La différence entre les décomptes bruts et privés est donc légèrement inférieure par rapport à l'exécution précédente.

Lorsque vous utilisez des partitions publiques, vous devez tenir compte de deux points importants:

  • Soyez prudent lorsque vous extrayez la liste des partitions à partir de données brutes. Si vous ne le faites pas en mode privé différentiel, votre pipeline ne fournit plus de garanties de confidentialité différentielle. Pour en savoir plus, consultez la section "Avancé: Obtenir des partitions à partir de données".
  • S'il n'existe aucune donnée pour certaines des partitions publiques, vous devez leur appliquer du bruit pour préserver la confidentialité différentielle. Par exemple, si vous avez utilisé un produit supplémentaire comme un pantalon, qui ne figure pas dans votre ensemble de données ni sur votre site Web, il y a toujours du bruit. Les résultats peuvent indiquer des visites de produits alors qu'il n'y en a pas eu.

Avancé: extraire des partitions à partir de données

Si vous exécutez plusieurs agrégations avec la même liste de partitions de sortie non publiques dans le même pipeline, vous pouvez obtenir la liste des partitions une fois avec la méthode dp_engine.select_private_partitions() et fournir les partitions à chaque agrégation en tant qu'entrée public_partitions. Non seulement cela est sûr du point de vue de la confidentialité, mais cela vous permet également d'ajouter moins de bruit, car vous n'utilisez le budget de confidentialité lors de la sélection des partitions qu'une seule fois pour l'ensemble du pipeline.

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. Calculer plusieurs statistiques

Maintenant que vous savez comment fonctionne PipelineDP, vous pouvez voir comment l'utiliser pour des cas d'utilisation plus avancés. Comme nous l'avons mentionné au début, vous êtes intéressé par trois statistiques. PipelineDP vous permet de calculer plusieurs statistiques en même temps tant que celles-ci partagent les mêmes paramètres dans l'instance AggregateParams, que vous verrez plus tard. Il est non seulement plus clair et plus facile de calculer plusieurs métriques en une seule fois, mais il offre également de meilleurs résultats en termes de confidentialité.

Souvenez-vous des paramètres epsilon et delta que vous fournissez à la classe NaiveBudgetAccountant. Ils représentent un budget de confidentialité, qui est une mesure du niveau de confidentialité des données que vous dégagez des utilisateurs.

Il est important de se rappeler que le budget pour la confidentialité s'ajoute. Si vous exécutez une seule fois un pipeline avec des valeurs epsilon light et delta fine spécifiques, vous dépensez un budget de (LDAP, ). Si vous l'exécutez une deuxième fois, vous dépensez un budget total de (2£, 2・). De même, si vous calculez plusieurs statistiques avec une méthode NaiveBudgetAccountant et, consécutivement, un budget de confidentialité de β,Ψ, vous dépensez un budget total de (2Ψ, 2 Créez). Cela signifie que vous dégradez les garanties de confidentialité.

Pour contourner ce problème, vous devez utiliser une seule instance NaiveBudgetAccountant avec le budget total à utiliser lorsque vous devez calculer plusieurs statistiques sur les mêmes données. Vous devez ensuite spécifier les valeurs epsilon et delta à utiliser pour chaque agrégation. Au final, vous obtenez la même garantie globale de confidentialité, mais plus les valeurs epsilon et delta sont élevées, plus une agrégation particulière est précise.

Pour voir cela en action, vous pouvez calculer les statistiques count, mean et sum.

Vous calculez des statistiques en plus de deux métriques différentes: une métrique conversion_value, qui vous permet de déduire le montant des revenus générés en fonction du produit consulté en premier, et une métrique has_conversion, qui vous permet de calculer le nombre de visiteurs de votre site Web et le taux de conversion moyen.

Pour chaque métrique, vous devez spécifier séparément les paramètres qui guident le calcul des statistiques privées. Vous répartissez votre budget dédié à la confidentialité entre les deux métriques. Vous calculez deux statistiques à partir de la métrique has_conversion. Vous voulez donc lui attribuer les deux tiers de votre budget initial et l'autre tiers à la métrique conversion_value.

Pour calculer plusieurs statistiques:

  1. Configurez votre comptable responsable de la confidentialité avec les valeurs totales epsilon et delta que vous souhaitez utiliser pour les trois statistiques:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
     total_epsilon=1, total_delta=0)
  1. Initialisez DPEngine pour calculer vos métriques:
 dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
  1. Spécifiez les paramètres de cette métrique.
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)

Le dernier argument spécifie éventuellement la pondération de votre budget Privacy Budget. Vous pouvez attribuer la même pondération à tous les éléments, mais vous devez définir cet argument sur un tiers, comme expliqué précédemment.

Vous définissez également des arguments min_value et max_value pour spécifier les limites inférieure et supérieure appliquées à une valeur fournie par une unité de confidentialité dans une partition. Ces paramètres sont obligatoires lorsque vous souhaitez calculer une somme ou une moyenne privée. Vous ne vous attendez pas à des valeurs négatives. Vous pouvez donc supposer que 0 et 100 sont des limites raisonnables.

  1. Extrayez les données pertinentes, puis transmettez-les à la fonction d'agrégation:
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))
  1. Suivez la même procédure pour calculer les deux métriques en fonction de votre variable has_conversion:
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))

La seule modification concerne l'instance pipeline_dp.AggregateParams, dans laquelle vous définissez maintenant mean et count comme agrégations, et vous affectez deux tiers de votre budget Privacy Budget à ce calcul. Comme vous souhaitez définir les mêmes limites de contribution pour les deux statistiques et les calculer au-dessus de la même variable has_conversion, vous pouvez les combiner dans la même instance pipeline_dp.AggregateParams et les calculer en même temps.

  1. Appelez la méthode budget_accountant.compute_budgets():
budget_accountant.compute_budgets()

Vous pouvez comparer les trois statistiques privées avec leurs statistiques d'origine. En fonction du bruit ajouté, vous constatez que les résultats peuvent en fait se trouver en dehors de l'échelle plausible. Dans ce cas, vous constatez un taux de conversion et une valeur de conversion total négatifs pour les jumpers, car le bruit ajouté est symétrique autour de zéro. Pour les analyses et le traitement plus poussés, il est préférable de ne pas traiter manuellement les statistiques privées. Toutefois, si vous souhaitez ajouter ces graphiques à un rapport, il vous suffit de définir le minimum sur zéro par la suite, sans porter atteinte aux garanties de confidentialité.

cb1fc563f817eaf.png

7. Exécuter le pipeline avec Beam

De nos jours, le traitement des données nécessite de traiter d'énormes quantités de données, à tel point que vous ne pouvez pas les traiter localement. À la place, de nombreuses personnes utilisent des frameworks pour le traitement de données à grande échelle, tels que Beam ou Spark, et exécutent leurs pipelines dans le cloud.

PipelineDP est compatible avec Beam et Spark en apportant de légères modifications à votre code.

Pour exécuter le pipeline avec Beam avec l'API private_beam:

  1. Initialisez une variable runner, puis créez un pipeline dans lequel vous appliquez vos opérations de confidentialité à une représentation Beam de votre rows:
runner = fn_api_runner.FnApiRunner()  # local runner

with beam.Pipeline(runner=runner) as pipeline:
   beam_data = pipeline | beam.Create(rows)
  1. Créez une variable budget_accountant avec les paramètres de confidentialité requis:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
               total_epsilon=1, total_delta=0)
  1. Créez une variable pcol, ou collection privée, qui garantit que toutes les agrégations sont conformes à vos exigences de confidentialité:
pcol = beam_data | pbeam.MakePrivate(
                                 budget_accountant=budget_accountant,
                                 privacy_id_extractor=lambda 
                                                    row: row.user_id)
  1. Spécifiez les paramètres de votre agrégation privée dans la classe appropriée.

Ici, vous utilisez la classe pipeline_dp.aggregate_params.SumParams(), car vous calculez la somme des vues du produit.

  1. Transmettez vos paramètres d'agrégation à la méthode pbeam.Sum pour calculer votre statistique:
dp_result = pcol | pbeam.Sum(params)
  1. Au final, votre code doit se présenter comme suit:
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. Facultatif: Ajuster les paramètres de confidentialité et d'utilitaire

Vous avez vu un certain nombre de paramètres mentionnés dans cet atelier de programmation, tels que epsilon, delta et max_partitions_contributed. Vous pouvez les diviser en deux catégories approximatives: les paramètres de confidentialité et les paramètres utilitaires.

Paramètres de confidentialité

Les paramètres epsilon et delta quantifient le niveau de confidentialité que vous offrez avec la confidentialité différentielle. Plus précisément, il s’agit d’une mesure de la quantité d’informations qu’un pirate informatique potentiel peut obtenir sur les données des résultats anonymisés. Plus la valeur des paramètres est élevée, plus le pirate informatique obtient d'informations sur les données, ce qui représente un risque pour la confidentialité. En revanche, plus la valeur des paramètres epsilon et delta est faible, plus vous devez ajouter de bruit à la sortie pour la rendre anonyme, et plus le nombre d'utilisateurs uniques dont vous avez besoin dans chaque partition est élevé pour les conserver dans la sortie anonymisée. Dans ce cas, il faut trouver un compromis entre utilité et confidentialité.

Dans PipelineDP, vous devez spécifier les garanties de confidentialité souhaitées pour la sortie anonymisée lorsque vous définissez le budget de confidentialité total dans l'instance NaiveBudgetAccountant. L'inconvénient, c'est que si vous souhaitez conserver vos garanties de confidentialité, vous devez soigneusement utiliser une instance NaiveBudgetAccountant distincte pour chaque agrégation ou exécuter le pipeline plusieurs fois afin d'éviter une utilisation excessive de votre budget.

Pour en savoir plus sur la confidentialité différentielle et la signification des paramètres de confidentialité, consultez Une liste de lecture sur la confidentialité différentielle.

Paramètres utilitaires

Les paramètres utilitaires n'affectent pas les garanties de confidentialité, mais affectent la précision et, par conséquent, l'utilité du résultat. Elles sont fournies dans l'instance AggregateParams et permettent de mettre à l'échelle le bruit ajouté.

max_partitions_contributed est un paramètre utilitaire fourni dans l'instance AggregateParams et applicable à toutes les agrégations. Une partition correspond à une clé des données renvoyées par l'opération d'agrégation PipelineDP. Par conséquent, le paramètre max_partitions_contributed limite le nombre de valeurs de clé distinctes qu'un utilisateur peut contribuer à la sortie. Si un utilisateur contribue à un nombre de clés qui dépasse la valeur du paramètre max_partitions_contributed, certaines contributions sont supprimées afin qu'elles contribuent à la valeur exacte du paramètre max_partitions_contributed.

De même, la plupart des agrégations comportent un paramètre max_contributions_per_partition. Elles sont également fournies dans l'instance AggregateParams, et chaque agrégation peut avoir des valeurs distinctes. Ils ont lié la contribution d'un utilisateur à chaque clé.

Le bruit ajouté à la sortie est ajusté par les paramètres max_partitions_contributed et max_contributions_per_partition. Il y a donc un compromis ici: plus la valeur attribuée à chaque paramètre est élevée, plus vous conservez de données, mais le résultat est plus bruyant.

Certaines agrégations nécessitent un paramètre min_value et max_value, qui spécifient les limites des contributions de chaque utilisateur. Si un utilisateur contribue à une valeur inférieure à celle attribuée au paramètre min_value, cette valeur augmente. De même, si un utilisateur contribue à une valeur supérieure à celle du paramètre max_value, celle-ci est réduite à celle du paramètre. Pour conserver davantage de valeurs d'origine, vous devez définir des limites plus importantes. Le bruit est ajusté en fonction de la taille des limites. Des limites plus importantes vous permettent de conserver plus de données, mais vous obtenez un résultat plus bruyant.

Enfin, le paramètre noise_kind accepte deux mécanismes de bruit différents dans PipelineDP: le bruit GAUSSIAN et LAPLACE. La distribution LAPLACE offre un meilleur service avec des limites de contribution faibles. C'est pourquoi PipelineDP l'utilise par défaut. Toutefois, si vous souhaitez utiliser un bruit de distribution GAUSSIAN, vous pouvez le spécifier dans l'instance AggregateParams.

9. Félicitations

Bravo ! Vous avez terminé l'atelier de programmation PipelineDP et appris beaucoup de choses sur la confidentialité différentielle et le PipelineDP.

En savoir plus