Calcular estatísticas particulares com o PipelineDP

1. Antes de começar

Talvez você acredite que estatísticas agregadas não vazam informações sobre os indivíduos a quem elas pertencem. No entanto, há muitas maneiras de um invasor descobrir informações sensíveis sobre indivíduos com base em estatísticas agregadas.

Neste codelab, você vai aprender a produzir estatísticas particulares com agregações particulares diferenciadas do PipelineDP para proteger a privacidade das pessoas. O PipelineDP é um framework Python que permite aplicar privacidade diferencial a grandes conjuntos de dados com sistemas de processamento em lote, como o Apache Spark e o Apache Beam. Para mais informações sobre como calcular estatísticas com privacidade diferencial em Go, consulte o codelab Privacy on Beam.

Privado significa que a saída é produzida de uma maneira que não vaza nenhuma informação particular sobre os indivíduos nos dados. É possível alcançar esse resultado com a privacidade diferencial, uma forte noção de privacidade para anonimização, que é o processo de agregação de dados de vários usuários para proteger a privacidade deles. Todos os métodos de anonimização usam a agregação, mas nem todos os métodos de agregação alcançam a anonimização. A privacidade diferencial, por outro lado, oferece garantias mensuráveis sobre vazamento de informações e privacidade.

Pré-requisitos

  • Familiaridade com Python
  • Familiaridade com agregação de dados básica
  • Experiência com pandas, Spark e Beam

O que você vai aprender

  • Noções básicas da privacidade diferencial
  • Como calcular estatísticas de resumo diferencialmente particulares com o PipelineDP
  • Como ajustar seus resultados com parâmetros adicionais de privacidade e utilidade

O que é necessário

  • Se você quiser executar o codelab no seu próprio ambiente, instale o Python 3.7 ou uma versão mais recente no computador.
  • Se você quiser seguir o codelab sem um ambiente próprio, precisará de acesso ao Colaboratory.

2. Entender a privacidade diferencial

Para entender melhor a privacidade diferencial, confira este exemplo simples.

Imagine que você trabalha no departamento de marketing de um varejista de moda on-line e quer entender quais dos seus produtos têm mais chances de serem vendidos.

Este gráfico mostra quais produtos os clientes olharam primeiro quando visitaram o site da loja: camisetas, moletons, meias ou jeans. As camisetas são o item mais procurado, enquanto as meias são o menos procurado.

ea813c698889a4c6.png

Isso parece útil, mas há um problema. Quando você quer considerar mais informações, como se os clientes fizeram uma compra ou qual produto eles viram em segundo lugar, corre o risco de revelar indivíduos nos seus dados.

Este gráfico mostra que apenas um cliente olhou primeiro para um jumper e depois fez uma compra:

b7c6f7f891778366.png

Isso não é bom do ponto de vista da privacidade. As estatísticas anônimas não podem revelar contribuições individuais. Então, o que você faz? Você adiciona ruído aleatório aos gráficos de barras para deixá-los um pouco menos precisos.

Este gráfico de barras não é totalmente preciso, mas ainda é útil e não revela contribuições individuais:

b55e8d7f99f6d574.gif

A privacidade diferencial é a adição da quantidade certa de ruído aleatório para mascarar contribuições individuais.

Este exemplo é simplificado demais. A implementação correta da privacidade diferencial é mais complexa e tem várias sutilezas inesperadas. Assim como a criptografia, criar sua própria implementação de privacidade diferencial pode não ser uma boa ideia. Em vez disso, use o PipelineDP.

3. Fazer o download e instalar o PipelineDP

Não é necessário instalar o PipelineDP para seguir este codelab, porque você encontra todos os códigos e gráficos relevantes neste documento.

Para testar o PipelineDP, execute-o por conta própria ou use-o mais tarde:

  • Faça o download e instale o PipelineDP:
pip install pipeline-dp

Se você quiser executar o exemplo usando o Apache Beam:

  • Faça o download e instale o Apache Beam:
pip install apache_beam

O código deste codelab e o conjunto de dados estão no diretório PipelineDP/examples/codelab/.

4. Calcular métricas de conversão por primeiro produto visualizado

Imagine que você trabalha em uma loja de moda on-line e quer entender quais das suas categorias de produtos geram o maior número e valor de conversões quando são visualizadas primeiro. Você quer compartilhar essas informações com sua agência de marketing e outras equipes internas, mas quer evitar o vazamento de informações sobre clientes individuais.

Para calcular as métricas de conversão por primeiro produto visualizado no site:

  1. Analise o conjunto de dados simulado de visitas ao seu site no diretório PipelineDP/examples/codelab/.

Esta captura de tela é um exemplo do conjunto de dados. Ele contém o ID do usuário, os produtos que um usuário visualizou, se o visitante fez uma conversão e, em caso afirmativo, o valor da conversão.

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

nenhum

nenhum

falso

0,0

1

jeans

t_shirt

jeans

jumper

nenhum

falso

0,0

2

t_shirt

jumper

t_shirt

t_shirt

nenhum

verdadeiro

105,19

3

t_shirt

t_shirt

jeans

nenhum

nenhum

falso

0,0

4

t_shirt

meias

jeans

jeans

nenhum

falso

0,0

Você tem interesse nestas métricas:

  • view_counts: o número de vezes que os visitantes do seu site veem cada produto pela primeira vez.
  • total_conversion_value: o valor total gasto pelos visitantes quando eles fazem uma conversão.
  • conversion_rate: a taxa de conversão dos visitantes.
  1. Gere as métricas de maneira não particular:
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)

Como você aprendeu antes, essas estatísticas podem revelar informações sobre indivíduos no seu conjunto de dados. Por exemplo, apenas uma pessoa fez uma conversão depois de ver um jumper primeiro. Para 22 visualizações, sua taxa de conversão é de aproximadamente 0,05. Agora, você precisa transformar cada gráfico de barras em um particular.

  1. Defina seus parâmetros de privacidade com a classe pipeline_dp.NaiveBudgetAccountant e especifique os argumentos epsilon e delta que você quer usar na sua análise.

A forma de definir esses argumentos depende do seu problema específico. Para saber mais sobre eles, consulte "Opcional: ajustar os parâmetros de privacidade diferencial".

Este snippet de código usa valores de exemplo:

budget_accountant = pipeline_dp.NaiveBudgetAccountant(
     total_epsilon=1, total_delta=1e-5)
  1. Inicialize a instância do LocalBackend:
ops = pipeline_dp.LocalBackend()

Você pode usar a instância LocalBackend porque executa esse programa localmente sem frameworks adicionais, como Beam ou Spark.

  1. Inicialize a instância do DPEngine:
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)

O PipelineDP permite especificar outros parâmetros usando a classe pipeline_dp.AggregateParams, que afeta a geração das suas estatísticas particulares.

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. Especifique que você quer calcular a métrica count e usar a distribuição de ruído LAPLACE.
  2. Defina o argumento max_partitions_contributed como um valor 1.

Esse argumento limita quantas visitas diferentes um usuário pode contribuir. Você espera que os usuários visitem o site uma vez por dia e não se importa se eles o visitam várias vezes ao longo do dia.

  1. Defina o argumento max_contributions_per_partitions como um valor 1.

Esse argumento especifica quantas contribuições um único visitante pode fazer para uma partição individual ou uma categoria dos produtos, neste caso.

  1. Crie uma instância data_extractor que especifique onde encontrar os campos privacy_id, partition e value.

O código vai ser semelhante a este snippet de código:

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. Adicione este código para transformar seu DataFrame do Pandas em uma lista de linhas com base nas quais você pode calcular diretamente estatísticas com privacidade diferencial:
rows = [index_row[1] for index_row in df.iterrows()]
dp_result_local = run_pipeline(rows, ops) # Returns generator
list(dp_result_local)

Parabéns! Você calculou sua primeira estatística particular diferenciada.

Este gráfico mostra o resultado da sua contagem com privacidade diferencial ao lado da contagem sem privacidade que você calculou anteriormente:

a5a25a00858219ab.png

O gráfico de barras mostrado quando você executa o código pode ser diferente desse, o que não é um problema. Devido ao ruído na privacidade diferencial, você terá um gráfico de barras diferente sempre que executar o código, mas é possível ver que eles são parecidos com o gráfico não particular original.

É muito importante que as garantias de privacidade não executem o pipeline várias vezes. Para mais informações, consulte "Calcular várias estatísticas".

5. Usar partições públicas

Na seção anterior, talvez você tenha notado que descartou todos os dados de visitas de uma partição, ou seja, os visitantes que viram meias pela primeira vez no seu site.

Isso acontece devido à seleção ou limitação da partição, uma etapa importante para assegurar garantias de privacidade diferencial quando a existência de partições de saída depende dos dados do usuário. Quando esse é o caso, a simples existência de uma partição de saída pode causar o vazamento da existência de um usuário individual nos dados. Para saber mais sobre por que isso viola a privacidade, consulte esta postagem do blog. Para evitar essa violação de privacidade, o PipelineDP mantém apenas partições com um número suficiente de usuários.

Quando a lista de partições de saída não depende dos dados do usuário particulares, não é necessário fazer essa etapa de seleção de partição. É o caso do seu exemplo, porque você conhece todas as categorias de produtos possíveis que um cliente pode ver primeiro.

Para usar partições:

  1. Crie uma lista das suas possíveis partições:
public_partitions_products = ['jeans', 'jumper', 'socks', 't-shirt']
  1. Transmita a lista para a função run_pipeline(), que a define como uma entrada adicional para a 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)

Se você usar partições públicas e ruído LAPLACE, será possível definir o argumento total_delta como um valor 0.

Agora você vê no resultado que os dados de todas as partições ou produtos são informados.

a4f6302c8efcd5da.png

As partições públicas permitem manter mais partições e também adicionam cerca de metade do ruído, já que não há gasto nenhum do orçamento de privacidade na seleção de partição. Assim, a diferença entre as contagens bruta e particular é um pouco menor em comparação com a execução anterior.

Há duas informações importantes a serem lembradas ao usar partições públicas:

  • Tenha cuidado ao derivar a lista de partições dos dados brutos. Se você não fizer isso de maneira particular diferenciada, seu pipeline não fornecerá mais garantias de privacidade diferencial. Para mais informações, consulte Avançado: derivar partições de dados.
  • Se não houver dados para algumas das partições públicas, aplique ruído a elas para preservar a privacidade diferencial. Por exemplo, se você usou um produto adicional, como calças, que não aparece no seu conjunto de dados ou no seu site, ainda assim é ruído, e os resultados podem mostrar algumas visitas a produtos quando não houve nenhuma.

Avançado: derivar partições de dados

Se você executar várias agregações com a mesma lista de partições de saída não públicas no mesmo pipeline, poderá derivar a lista de partições uma vez com o método dp_engine.select_private_partitions() e fornecer as partições para cada agregação como a entrada public_partitions. Isso é seguro do ponto de vista da privacidade e também permite que você adicione menos ruído, já que o orçamento de privacidade é usado na seleção de partição apenas uma vez para todo o 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. Calcular várias estatísticas

Agora que você sabe como o PipelineDP funciona, confira como usá-lo em alguns casos de uso mais avançados. Como mencionado no início, você tem interesse em três estatísticas. Com o PipelineDP, é possível calcular várias estatísticas ao mesmo tempo, desde que elas compartilhem os mesmos parâmetros na instância AggregateParams, que você vai conhecer mais adiante. Além de ser mais limpo e fácil de calcular várias métricas de uma só vez, também é melhor em termos de privacidade.

Os parâmetros epsilon e delta fornecidos à classe NaiveBudgetAccountant representam algo chamado orçamento de privacidade, que é uma medida da quantidade de privacidade do usuário que você vaza dos dados.

É importante lembrar que o orçamento de privacidade é cumulativo. Se você executar um pipeline com um determinado épsilon ε e delta δ uma única vez, você gastará um orçamento de (ε,δ). Se ele for executado pela segunda vez, você terá gastado um orçamento total de (2ε, 2δ). Da mesma forma, se você calcular várias estatísticas com um método NaiveBudgetAccountant e, consecutivamente, um orçamento de privacidade de ε,δ, você gastará um orçamento total de (2ε, 2δ). Isso significa que você está degradando as garantias de privacidade.

Para contornar isso, use uma única instância NaiveBudgetAccountant com o orçamento total que você quer usar quando precisar calcular várias estatísticas sobre os mesmos dados. Em seguida, especifique os valores epsilon e delta que você quer usar para cada agregação. No final, você terá a mesma garantia geral de privacidade. No entanto, quanto mais altos forem os valores de epsilon e delta de uma agregação específica, maior será a precisão dela.

Para ver isso em ação, calcule as estatísticas count, mean e sum.

Você calcula estatísticas com base em duas métricas diferentes: uma métrica conversion_value, que você usa para inferir a quantidade de receita gerada com base no produto visualizado primeiro, e uma métrica has_conversion, que você usa para calcular o número de visitantes do seu site e a taxa de conversão média.

Para cada métrica, é necessário especificar separadamente os parâmetros que orientam o cálculo das estatísticas particulares. Você divide seu orçamento de privacidade entre as duas métricas. Você calcula duas estatísticas da métrica has_conversion. Portanto, atribua dois terços do orçamento inicial a ela e o outro terço à métrica conversion_value.

Para calcular várias estatísticas:

  1. Configure seu contador de orçamento de privacidade com os valores totais de epsilon e delta que você quer usar nas três estatísticas:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
     total_epsilon=1, total_delta=0)
  1. Inicialize o DPEngine para calcular suas métricas:
 dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
  1. Especifique os parâmetros dessa métrica.
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)

O último argumento especifica opcionalmente a ponderação do seu orçamento de privacidade. Você pode dar o mesmo peso a todos, mas quer definir esse argumento como um terço, conforme explicado anteriormente.

Você também define um argumento min_value e max_value para especificar os limites inferior e superior aplicados a um valor contribuído por uma unidade de privacidade em uma partição. Esses parâmetros são obrigatórios quando você quer calcular uma soma ou média particular. Como você não espera valores negativos, pode presumir 0 e 100 como limites razoáveis.

  1. Extraia os dados relevantes e transmita-os para a função de agregação:
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. Siga as mesmas etapas para calcular as duas métricas com base na sua variável 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))

A única mudança é na instância pipeline_dp.AggregateParams, em que agora você define mean e count como agregações e atribui dois terços do seu orçamento de privacidade a esse cálculo. Como você quer ter os mesmos limites de contribuição para as duas estatísticas e calculá-los com base na mesma variável has_conversion, é possível combiná-los na mesma instância pipeline_dp.AggregateParams e calcular ao mesmo tempo.

  1. Chame o método budget_accountant.compute_budgets():
budget_accountant.compute_budgets()

É possível representar as três estatísticas privadas em comparação com as originais. Dependendo do ruído adicionado, os resultados podem ficar fora da escala plausível. Nesse caso, você vê uma taxa de conversão e um valor total de conversão negativos para os jumpers porque o ruído adicionado é simétrico em torno de zero. Para outras análises e processamentos, é melhor não pós-processar manualmente as estatísticas particulares. No entanto, se você quiser adicionar esses gráficos a um relatório, basta definir o mínimo como zero depois, sem violar as garantias de privacidade.

cb1fc563f817eaf.png

7. Executar o pipeline com o Beam

O processamento de dados hoje em dia exige que você lide com grandes quantidades de dados, tanto que não é possível processá-los localmente. Em vez disso, muitas pessoas usam frameworks para processamento de dados em grande escala, como Beam ou Spark, e executam os pipelines na nuvem.

O PipelineDP é compatível com Beam e Spark com apenas pequenas mudanças no seu código.

Para executar o pipeline com o Beam usando a API private_beam:

  1. Inicialize uma variável runner e crie um pipeline em que você aplica as operações de privacidade a uma representação do Beam do seu rows:
runner = fn_api_runner.FnApiRunner()  # local runner

with beam.Pipeline(runner=runner) as pipeline:
   beam_data = pipeline | beam.Create(rows)
  1. Crie uma variável budget_accountant com os parâmetros de privacidade necessários:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
               total_epsilon=1, total_delta=0)
  1. Crie uma variável pcol ou de coleção particular, que garante que todas as agregações estejam em conformidade com suas normas de privacidade:
pcol = beam_data | pbeam.MakePrivate(
                                 budget_accountant=budget_accountant,
                                 privacy_id_extractor=lambda 
                                                    row: row.user_id)
  1. Especifique os parâmetros da sua agregação privada na classe apropriada.

Aqui, você usa a classe pipeline_dp.aggregate_params.SumParams() porque calcula a soma das visualizações de produtos.

  1. Transmita os parâmetros de agregação ao método pbeam.Sum para calcular a estatística:
dp_result = pcol | pbeam.Sum(params)
  1. No final, seu snippet de código deve ficar assim:
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. Opcional: ajuste os parâmetros de privacidade e utilidade

Você viu alguns parâmetros mencionados neste codelab, como epsilon, delta e max_partitions_contributed. Podemos dividi-los em duas categorias: parâmetros de privacidade e parâmetros de utilidade.

Parâmetros de privacidade

Os parâmetros epsilon e delta quantificam a privacidade que você oferece com a privacidade diferencial. Mais precisamente, eles são uma medida da quantidade de informações que um possível invasor conseguiria sobre os dados analisando a saída anonimizada. Quanto maior o valor dos parâmetros, mais informações o invasor consegue sobre os dados, o que é um risco de privacidade. Por outro lado, quanto menor o valor dos parâmetros epsilon e delta, mais ruído você precisa adicionar à saída para torná-la anônima e maior o número de usuários únicos necessários em cada partição para mantê-las na saída anonimizada. Nesse caso, há uma compensação entre utilidade e privacidade.

No PipelineDP, é preciso especificar as garantias de privacidade desejadas da saída anonimizada ao definir o orçamento de privacidade total na instância NaiveBudgetAccountant. A ressalva é que, se você quiser que as garantias de privacidade sejam mantidas, será necessário usar com cuidado uma instância NaiveBudgetAccountant separada para cada agregação ou executar o pipeline várias vezes para evitar o uso excessivo do orçamento.

Para saber mais sobre privacidade diferencial e o significado dos parâmetros de privacidade, consulte Uma lista de leitura sobre privacidade diferencial.

Parâmetros de utilidade

Os parâmetros de utilidade não afetam as garantias de privacidade, mas afetam a precisão e, consequentemente, a utilidade da saída. Eles são fornecidos na instância AggregateParams e usados para escalonar o ruído adicionado.

Um parâmetro de utilidade fornecido na instância AggregateParams e aplicável a todas as agregações é o parâmetro max_partitions_contributed. Uma partição corresponde a uma chave dos dados retornados pela operação de agregação do PipelineDP. Assim, o parâmetro max_partitions_contributed limita o número de valores de chave distintos com que um usuário pode contribuir para a saída. Se um usuário contribuir com um número de chaves que exceda o valor do parâmetro max_partitions_contributed, algumas contribuições serão descartadas para que contribuam com o valor exato do parâmetro max_partitions_contributed.

Da mesma forma, a maioria das agregações tem um parâmetro max_contributions_per_partition. Eles também são fornecidos na instância AggregateParams, e cada agregação pode ter valores separados para eles. Eles limitam a contribuição de um usuário para cada chave.

O ruído adicionado à saída é escalonado pelos parâmetros max_partitions_contributed e max_contributions_per_partition. Por isso, há uma compensação aqui: valores maiores atribuídos a cada parâmetro significam que você mantém mais dados, mas recebe um resultado com mais ruído.

Algumas agregações exigem um parâmetro min_value e max_value, que especificam os limites para as contribuições de cada usuário. Se um usuário contribuir com um valor menor que o atribuído ao parâmetro min_value, o valor será aumentado para o valor do parâmetro. Da mesma forma, se um usuário contribuir com um valor maior que o do parâmetro max_value, ele será reduzido para o valor do parâmetro. Para manter mais valores originais, é necessário especificar limites maiores. O ruído é escalonado pelo tamanho dos limites. Assim, limites maiores permitem manter mais dados, mas o resultado é mais ruidoso.

Por fim, o parâmetro noise_kind oferece suporte a dois mecanismos de ruído diferentes no PipelineDP: ruído GAUSSIAN e LAPLACE. A distribuição LAPLACE oferece uma utilidade melhor com limites de contribuição baixos, e é por isso que o PipelineDP a usa como padrão. No entanto, se você quiser usar um ruído de distribuição GAUSSIAN, especifique-o na instância AggregateParams.

9. Parabéns

Muito bem! Você concluiu o codelab do PipelineDP e aprendeu muito sobre privacidade diferencial e PipelineDP.

Saiba mais