1. Antes de comenzar
Podría pensar que las estadísticas agregadas no filtran ninguna información sobre las personas a las que pertenecen. Sin embargo, existen muchas formas en las que un atacante puede obtener información confidencial sobre individuos a partir de estadísticas agregadas.
En este codelab, aprenderás a producir estadísticas privadas con agregaciones privadas diferenciales de PipelineDP para proteger a las personas la privacidad. PipelineDP es un framework de Python que te permite aplicar privacidad diferencial a conjuntos de datos grandes con sistemas de procesamiento por lotes, como Apache Spark y Apache Beam. Si deseas obtener más información para calcular estadísticas privadas diferenciales en Go, consulta el codelab Privacy on Beam.
Privado significa que el resultado se produce de forma tal que no se filtra información privada sobre las personas en los datos. Puedes lograr este resultado a través de la privacidad diferencial, una sólida noción de privacidad de la anonimización, que es el proceso de agregación de datos de varios usuarios para proteger su privacidad. Todos los métodos de anonimización usan la agregación, pero no todos los métodos de agregación logran la anonimización. La privacidad diferencial, por otro lado, proporciona garantías medibles sobre la filtración y privacidad de la información.
Requisitos previos
- Conocimientos de Python
- Conocimientos de agregación de datos básicos
- Experiencia con Pandas, Spark y Beam
Qué aprenderás
- Conceptos básicos de la privacidad diferencial
- Cómo calcular estadísticas de resumen de privacidad diferencial con PipelineDP
- Cómo modificar tus resultados con parámetros adicionales de privacidad y utilidad
Requisitos
- Si deseas ejecutar el codelab en tu propio entorno, debes tener instalado Python 3.7 o una versión posterior en tu computadora.
- Si deseas seguir el codelab sin tu propio entorno, necesitas acceso a Colaboratory.
2. Comprende la privacidad diferencial
Para entender mejor la privacidad diferencial, mira este ejemplo simple.
Imagina que trabajas en el departamento de marketing de un minorista de moda en línea y quieres saber cuáles de tus productos tienen más probabilidades de venderse.
En este gráfico, se muestra qué productos vieron por primera vez los clientes cuando visitaron el sitio web de la tienda: camisetas, suéteres, calcetines o jeans. Las camisetas son el artículo más popular, mientras que los calcetines son el menos popular.
Esto parece útil, pero hay un truco. Cuando quieres tener en cuenta información adicional, como si los clientes realizaron una compra o qué producto vieron en segundo lugar, corres el riesgo de revelar personas en tus datos.
En este gráfico, se muestra que solo un cliente miró un puente y, luego, realmente realizó una compra:
Esto no es muy bueno desde el punto de vista de la privacidad. Las estadísticas anonimizadas no deberían revelar contribuciones individuales, pero ¿qué haces? Agregas ruido aleatorio a tus gráficos de barras para que sean un poco menos precisos.
Este gráfico de barras no es completamente preciso, pero es útil y no revela las contribuciones individuales:
La privacidad diferencial es la adición de la cantidad correcta de ruido aleatorio para enmascarar las contribuciones individuales.
Este ejemplo está demasiado simplificado. La implementación adecuada de la privacidad diferencial es más compleja y conlleva una serie de sutilezas de implementación inesperadas. Al igual que la criptografía, quizás no sea una buena idea crear tu propia implementación de la privacidad diferencial. En su lugar, puedes usar PipelineDP.
3. Descarga e instala PipelineDP
No es necesario que instales PipelineDP siguiendo este codelab porque podrás encontrar todos los gráficos y el código relevantes en este documento.
Para jugar con PipelineDP, ejecútala tú mismo o úsala más tarde:
- Descarga y, luego, instala PipelineDP:
pip install pipeline-dp
Si quieres ejecutar el ejemplo con Apache Beam, sigue estos pasos:
- Descarga y, luego, instala Apache Beam:
pip install apache_beam
Puedes encontrar el código de este codelab y el conjunto de datos en el directorio PipelineDP/examples/codelab/
.
4. Calcula las métricas de conversiones por primer producto visto
Imagina que trabajas en un minorista de moda en línea y deseas saber cuáles de tus diferentes categorías de productos generan la mayor cantidad y valor de conversiones cuando se ven por primera vez. Quieres compartir esta información con tu agencia de marketing y con otros equipos internos, pero quieres evitar que se filtre información sobre un cliente específico.
Para calcular las métricas de conversión por primer producto visto en el sitio web, sigue estos pasos:
- Revisa el conjunto de datos simulado de las visitas a tu sitio web en el directorio
PipelineDP/examples/codelab/
.
Esta captura de pantalla es un ejemplo del conjunto de datos. Contiene el ID del usuario, los productos que vio el usuario, si el visitante generó una conversión y, de ser así, el valor de la conversión.
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 | ninguno | ninguno | falso | 0.0 |
1 | jeans | t_shirt | jeans | puente | ninguno | falso | 0.0 |
2 | t_shirt | puente | t_shirt | t_shirt | ninguno | verdadero | 105,19 |
3 | t_shirt | t_shirt | jeans | ninguno | ninguno | falso | 0.0 |
4 | t_shirt | calcetines | jeans | jeans | ninguno | falso | 0.0 |
Te interesan las siguientes métricas:
view_counts
: Es la cantidad de veces que los visitantes de tu sitio web ven primero cada producto.total_conversion_value
: Es el importe total que los visitantes gastan cuando generan una conversión.conversion_rate
: Es la tasa de conversión de los visitantes.
- Genera las métricas de forma no privada:
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 aprendiste anteriormente, estas estadísticas pueden revelar información sobre individuos en tu conjunto de datos. Por ejemplo, solo una persona generó conversiones después de que vio primero un puente. Para 22 vistas, tu porcentaje de conversiones es de aproximadamente 0.05. Ahora, debes transformar cada gráfico de barras en uno privado.
- Define tus parámetros de privacidad con la clase
pipeline_dp.NaiveBudgetAccountant
y, luego, especifica los argumentosepsilon
ydelta
que quieres usar para tu análisis.
La forma de establecer estos argumentos depende de tu problema específico. Para obtener más información sobre ellos, consulta Opcional: Ajusta los parámetros de privacidad diferencial.
En este fragmento de código, se usan valores de ejemplo:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=1e-5)
- Inicializa la instancia
LocalBackend
:
ops = pipeline_dp.LocalBackend()
Puedes usar la instancia de LocalBackend
porque ejecutas este programa de forma local sin frameworks adicionales, como Beam o Spark.
- Inicializa la instancia
DPEngine
:
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
PipelineDP te permite especificar parámetros adicionales a través de la clase pipeline_dp.AggregateParams
, que afecta la generación de tus estadísticas privadas.
params = pipeline_dp.AggregateParams(
noise_kind=pipeline_dp.NoiseKind.LAPLACE,
metrics=[pipeline_dp.Metrics.COUNT],
max_partitions_contributed=1,
max_contributions_per_partition=1)
- Especifica que deseas calcular la métrica
count
y usar la distribución de ruidoLAPLACE
. - Establece el argumento
max_partitions_contributed
en un valor1
.
Este argumento limita la cantidad de visitas diferentes que un usuario puede contribuir. Esperas que los usuarios visiten el sitio web una vez al día y no importa si lo visitan varias veces durante el día.
- Establece el argumento
max_contributions_per_partitions
en un valor1
.
Este argumento especifica cuántas contribuciones puede hacer un solo visitante a una partición individual o una categoría de producto en este caso.
- Crea una instancia de
data_extractor
que especifique dónde encontrar los camposprivacy_id
,partition
yvalue
.
Tu código debería verse como este fragmento 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
- Agrega este código para transformar tu DataFrame de Pandas en una lista de filas a partir de las cuales puedes calcular directamente estadísticas privadas diferenciales:
rows = [index_row[1] for index_row in df.iterrows()]
dp_result_local = run_pipeline(rows, ops) # Returns generator
list(dp_result_local)
¡Felicitaciones! Calculaste tu primera estadística privada diferencial.
En este gráfico, se muestra el resultado de tu recuento de privacidad diferencial junto al recuento de datos no privados que calculó antes:
El gráfico de barras que obtienes cuando ejecutas el código puede diferir de este, lo cual está bien. Debido al ruido en la privacidad diferencial, obtienes un gráfico de barras diferente cada vez que ejecutas el código, pero puedes ver que son similares al gráfico de barras original no privado.
Ten en cuenta que es muy importante para las garantías de privacidad no ejecutar la canalización varias veces por el bien de las garantías de privacidad. Para obtener más información, consulta Procesamiento de varias estadísticas.
5. Usa particiones públicas
En la sección anterior, es posible que hayas notado que descartaste todos los datos de visitas para una partición, es decir, los visitantes que primero vieron calcetines en tu sitio web.
Esto se debe a la selección de particiones o al umbral, un paso importante para garantizar las garantías de privacidad diferencial cuando la existencia de particiones de salida depende de los propios datos del usuario. Cuando esto sucede, la mera existencia de una partición en el resultado puede filtrar la existencia de un usuario individual en los datos. Para obtener más información sobre los motivos por los que esto infringe la privacidad, consulte esta entrada de blog. Para evitar este incumplimiento de privacidad, PipelineDP solo conserva las particiones con una cantidad suficiente de usuarios.
Cuando la lista de particiones de salida no depende de datos privados del usuario, no necesitas este paso de selección de particiones. En realidad, este es el caso de tu ejemplo porque conoces todas las categorías de productos posibles que un cliente podría ver primero.
Para usar particiones, haz lo siguiente:
- Crea una lista de las particiones posibles:
public_partitions_products = ['jeans', 'jumper', 'socks', 't-shirt']
- Pasa la lista a la función
run_pipeline()
, que la establece como una entrada adicional a la clasepipeline_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 usas particiones públicas y ruido LAPLACE
, es posible establecer el argumento total_delta
en un valor 0
.
Ahora verás en el resultado que se informan los datos de todas las particiones o productos.
Las particiones públicas no solo te permiten conservar más particiones, sino que también agregan aproximadamente la mitad del ruido, ya que no inviertes ningún presupuesto de privacidad en la selección de particiones, por lo que la diferencia entre los recuentos sin procesar y los privados es un poco menor en comparación con la ejecución anterior.
Hay dos aspectos importantes que debes tener en cuenta cuando usas particiones públicas:
- Ten cuidado cuando derives la lista de particiones a partir de datos sin procesar. Si no lo haces de forma diferencial privada, tu canalización ya no proporcionará garantías de privacidad diferenciales. Para obtener más información, consulta Avanzado: Deriva particiones a partir de datos.
- Si no hay datos para algunas de las particiones públicas, debes aplicar ruido a esas particiones para preservar la privacidad diferencial. Por ejemplo, si usaste un producto adicional, como pantalones, que no aparece en tu conjunto de datos ni en tu sitio web, sigue siendo ruido, y es posible que los resultados muestren algunas visitas a los productos cuando no había ninguna.
Avanzado: Deriva particiones a partir de datos
Si ejecutas varias agregaciones con la misma lista de particiones de salida no públicas en la misma canalización, puedes derivar la lista de particiones una vez con el método dp_engine.select_private_partitions()
y proporcionar las particiones a cada agregación como la entrada public_partitions
. Esto no solo es seguro desde el punto de vista de la privacidad, sino que también te permite agregar menos ruido, ya que solo se usa el presupuesto de privacidad en la selección de la partición una vez para toda la canalización.
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. Calcula varias estadísticas
Ahora que sabes cómo funciona PipelineDP, puedes ver cómo puedes usarlo para algunos casos de uso más avanzados. Como se mencionó al principio, te interesan tres estadísticas. PipelineDP te permite calcular varias estadísticas al mismo tiempo, siempre que estas compartan los mismos parámetros en la instancia de AggregateParams
, que verás más adelante. No solo es más claro y fácil calcular varias métricas a la vez, sino que también es mejor en términos de privacidad.
Si recuerdas los parámetros epsilon
y delta
que proporcionas a la clase NaiveBudgetAccountant
, representan lo que se denomina presupuesto de privacidad, que es una medida de la cantidad de privacidad del usuario que filtras de los datos.
Es importante recordar que el presupuesto de privacidad es adicional. Si ejecutas una canalización con un épsilon ε y delta ε en particular una sola vez, gastas un presupuesto de (ε,ε). Si la ejecutas por segunda vez, gastas un presupuesto total de (2ε, 2ε). De manera similar, si calculas varias estadísticas con un método NaiveBudgetAccountant
y, de forma consecutiva, un presupuesto de privacidad de ε,ε, usarás un presupuesto total de (2ε, 2ε). Esto significa que se degradan las garantías de privacidad.
Para evitar esto, debes usar una sola instancia de NaiveBudgetAccountant
con el presupuesto total que deseas utilizar cuando necesites calcular varias estadísticas a partir de los mismos datos. Luego, debes especificar los valores epsilon
y delta
que deseas usar para cada agregación. Al final, obtendrás la misma garantía de privacidad general, pero cuantos más altos los valores de epsilon
y delta
tengan una agregación en particular, mayor será su precisión.
Para ver esto en acción, puedes calcular las estadísticas de count
, mean
y sum
.
Calculas estadísticas a partir de dos métricas diferentes: una métrica de conversion_value
, que se usa para inferir la cantidad de ingresos generados según el producto que se vio primero, y una métrica de has_conversion
, que se usa para calcular la cantidad de visitantes de tu sitio web y el porcentaje de conversiones promedio.
Para cada métrica, debes especificar por separado los parámetros que guían el cálculo de las estadísticas privadas. Divides tu presupuesto de privacidad en las dos métricas. Calculas dos estadísticas a partir de la métrica has_conversion
, por lo que quieres asignarle dos tercios de tu presupuesto inicial y asignar el otro tercio a la métrica conversion_value
.
Para calcular varias estadísticas, haz lo siguiente:
- Configura tu contador del presupuesto de privacidad con los valores totales de
epsilon
ydelta
que quieres usar en las tres estadísticas:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=0)
- Inicializa
DPEngine
para calcular tus métricas:
dp_engine = pipeline_dp.DPEngine(budget_accountant, ops)
- Especifica los parámetros para esta 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)
De manera opcional, el último argumento especifica el peso de tu presupuesto de privacidad. Podrías darle la misma ponderación a todos, pero deseas establecer este argumento en un tercio, como se explicó anteriormente.
También estableces un argumento min_value
y max_value
para especificar los límites inferior y superior aplicados a un valor aportado por una unidad de privacidad en una partición. Estos parámetros son obligatorios cuando deseas calcular una suma o media privada. No esperas valores negativos, por lo que puedes suponer que 0
y 100
son límites razonables.
- Extrae los datos relevantes y, luego, pásalos a la función de agregación:
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))
- Sigue los mismos pasos para calcular las dos métricas según la 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))
El único cambio es en la instancia de pipeline_dp.AggregateParams
, en la que ahora defines mean
y count
como agregaciones, y asignas dos tercios de tu presupuesto de privacidad a este cálculo. Como deseas tener los mismos límites de contribución para ambas estadísticas y calcularlos sobre la misma variable has_conversion
, puedes combinarlos en la misma instancia de pipeline_dp.AggregateParams
y calcularlos al mismo tiempo.
- Llama al método
budget_accountant.compute_budgets()
:
budget_accountant.compute_budgets()
Puedes trazar las tres estadísticas privadas en comparación con sus estadísticas originales. Según el ruido agregado, ves que los resultados realmente pueden estar fuera de la escala creíble. En este caso, ves un porcentaje de conversiones negativo y un valor de conversión total para los puentes porque el ruido agregado es simétrico alrededor de cero. Para análisis y procesamientos adicionales, es mejor no realizar un posprocesamiento manual de las estadísticas privadas, pero si quisieras agregar esos diagramas a un informe, podrías simplemente establecer el mínimo en cero posteriormente sin infringir las garantías de privacidad.
7. Ejecuta la canalización con Beam
En la actualidad, el procesamiento de datos requiere que trates grandes cantidades de datos, tanto que no puedes procesarlos de forma local. En cambio, muchas personas usan frameworks para el procesamiento de datos a gran escala, como Beam o Spark, y ejecutan sus canalizaciones en la nube.
PipelineDP admite Beam y Spark con solo pequeños cambios en el código.
Para ejecutar la canalización con Beam con la API de private_beam
, haz lo siguiente:
- Inicializa una variable
runner
y, luego, crea una canalización en la que apliques tus operaciones de privacidad a una representación de Beam de turows
:
runner = fn_api_runner.FnApiRunner() # local runner
with beam.Pipeline(runner=runner) as pipeline:
beam_data = pipeline | beam.Create(rows)
- Crea una variable
budget_accountant
con los parámetros de privacidad requeridos:
budget_accountant = pipeline_dp.NaiveBudgetAccountant(
total_epsilon=1, total_delta=0)
- Crea una
pcol
, o variable de colección privada, que garantice que cualquier agregación cumpla con tus requisitos de privacidad:
pcol = beam_data | pbeam.MakePrivate(
budget_accountant=budget_accountant,
privacy_id_extractor=lambda
row: row.user_id)
- Especifica los parámetros de tu agregación privada en la clase adecuada.
Aquí, usarás la clase pipeline_dp.aggregate_params.SumParams()
porque calculas la suma de las vistas de productos.
- Pasa tus parámetros de agregación al método
pbeam.Sum
para calcular tu estadística:
dp_result = pcol | pbeam.Sum(params)
- Al final, tu código debería verse como este fragmento de código:
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: Ajusta los parámetros de privacidad y utilidad
Viste varios parámetros mencionados en este codelab, como epsilon
, delta
y max_partitions_contributed
. Puedes dividirlos en dos categorías: parámetros de privacidad y parámetros de utilidad.
Parámetros de privacidad
Los parámetros epsilon
y delta
cuantifican la privacidad que proporcionas con la privacidad diferencial. Más precisamente, son una medida de cuánta información puede obtener un posible atacante sobre los datos a partir del resultado anonimizado. Cuanto mayor sea el valor de los parámetros, más información obtendrá el atacante sobre los datos, lo que supone un riesgo de privacidad. Por otro lado, cuanto más bajo sea el valor de los parámetros epsilon
y delta
, más ruido deberás agregar al resultado para que sea anónimo y mayor será la cantidad de usuarios únicos que necesitarás en cada partición para mantenerlos en el resultado anonimizado. En este caso, existe un equilibrio entre utilidad y privacidad.
En PipelineDP, debes especificar las garantías de privacidad que deseas para el resultado anonimizado cuando establezcas el presupuesto de privacidad total en la instancia NaiveBudgetAccountant
. La salvedad es que, si deseas que se mantengan tus garantías de privacidad, debes usar con cuidado una instancia de NaiveBudgetAccountant
separada para cada agregación o ejecutar la canalización varias veces para evitar el uso excesivo de tu presupuesto.
Para obtener más información sobre la privacidad diferencial y el significado de los parámetros de privacidad, consulta Una lista de lectura sobre la privacidad diferencial.
Parámetros de utilidad
Los parámetros de utilidad no afectan las garantías de privacidad, sino la exactitud y, en consecuencia, la utilidad del resultado. Se proporcionan en la instancia AggregateParams
y se usan para escalar el ruido agregado.
Un parámetro de utilidad proporcionado en la instancia AggregateParams
y aplicable a todas las agregaciones es el parámetro max_partitions_contributed
. Una partición corresponde a una clave de los datos que muestra la operación de agregación PipelineDP, por lo que el parámetro max_partitions_contributed
limita la cantidad de valores clave distintos que un usuario puede contribuir al resultado. Si un usuario contribuye con una cantidad de claves que supera el valor del parámetro max_partitions_contributed
, se descartan algunas contribuciones para que contribuyan al valor exacto del parámetro max_partitions_contributed
.
De manera similar, la mayoría de las agregaciones tienen un parámetro max_contributions_per_partition
. También se proporcionan en la instancia de AggregateParams
y cada agregación podría tener valores separados. Vinculaban la contribución de un usuario para cada clave.
El ruido agregado al resultado se escala con los parámetros max_partitions_contributed
y max_contributions_per_partition
, por lo que hay una compensación aquí: valores más altos asignados a cada parámetro significan que conservas más datos, pero obtienes un resultado más ruidoso.
Algunas agregaciones requieren los parámetros min_value
y max_value
, que especifican los límites de las contribuciones de cada usuario. Si un usuario aporta un valor inferior al valor asignado al parámetro min_value
, el valor aumenta al valor del parámetro. De manera similar, si un usuario aporta un valor superior al del parámetro max_value
, el valor se reduce al valor del parámetro. Para conservar más valores originales, debes especificar límites más grandes. El ruido se escala según el tamaño de los límites, de manera que los límites más grandes te permiten conservar más datos, pero el resultado es más ruidoso.
Por último, el parámetro noise_kind
admite dos mecanismos de ruido diferentes en PipelineDP: ruido GAUSSIAN
y LAPLACE
. La distribución de LAPLACE
ofrece una mejor utilidad con límites de contribución bajos, por lo que PipelineDP la usa de forma predeterminada. Sin embargo, si deseas usar un ruido de distribución GAUSSIAN
, puedes especificarlo en la instancia AggregateParams
.
9. Felicitaciones
¡Bien hecho! Terminaste el codelab de PipelineDP y aprendiste mucho sobre la privacidad diferencial y PipelineDP.