Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

PyDP silently truncates and converts `np.float32` into `int64`, leading to sensitivity underestimation

Abierto Apto para principiantes
#499 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
83/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
cpp, python
Área
backend

Línea de trabajo

Empieza por las declaraciones de bindings en src/bindings/PyDP/mechanisms/mechanism.cpp, alrededor de la línea 52, y revisa cómo se registran las sobrecargas para integer y double. Reproduce el comportamiento con el ejemplo proporcionado np.float32 y, después, verifica que los valores np.float32 seleccionen el binding de double y no se trunquen; vuelve a ejecutar las pruebas pertinentes para los bindings de mechanism.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Type: Bug :bug:

In the code that registers the bindings with the C++ building blocks library, the int64 binding is defined before the double binding. This has a surprising consequence: pybind11, after doing a pass that sees if the input type matches the declared type, it then tries overloads in order with an implicit conversion path. The int caster apparently accepts a np.float32 and silently truncates its input, so values of this type automatically use the int64 binding.

Silent truncation predictably negative consequences on the sensitivity analysis: 0.95 becomes 0 and 1.05 becomes 1, so sensitivity increases unexpectedly. This is observable in PyDP:

import numpy as np
from pydp.algorithms.numerical_mechanisms import LaplaceMechanism

mechanism = LaplaceMechanism(epsilon=1.0, sensitivity=0.1)
print("np.float32, D :", [mechanism.add_noise(np.float32(0.95)) for _ in range(10)])
print("np.float32, D':", [mechanism.add_noise(np.float32(1.05)) for _ in range(10)])

and also affects PipelineDP via add_dp_noise, or VECTOR_SUM with float32 values. This happens even though the value is multiplied by 1.0, maybe to try and cast it to float? Sadly this doesn't work, since 1.0 * np.float32(1.7) still has type np.float32.

Here's a repro for add_dp_noise:

import numpy as np
import pipeline_dp

for name, value in (("D ", np.float32(0.95)), ("D'", np.float32(1.05))):
    releases = []
    for _ in range(10):
        accountant = pipeline_dp.NaiveBudgetAccountant(total_epsilon=1, total_delta=0)
        engine = pipeline_dp.DPEngine(accountant, pipeline_dp.LocalBackend())
        params = pipeline_dp.aggregate_params.AddDPNoiseParams(noise_kind=pipeline_dp.NoiseKind.LAPLACE, l0_sensitivity=1,
                                                               linf_sensitivity=0.1)
        result = engine.add_dp_noise([("partition", value)], params)
        accountant.compute_budgets()
        releases.append(list(result)[0][1])
    print(name, releases)

other PipelineDP aggregations (sum, mean, variance) convert to float64 and so aren't vulnerable to this.

This issue doesn't happen with np.float64, because np.float64 is a subclass of Python's native floats (while np.float32 is not). Therefore, the right binding is selected by pybind11 during the first pass.

Registering the double binding first would fix it.

Lenguaje dominante
Python
Estrellas
550
Forks
142
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de OpenMined/PyDP

Todos los issues de OpenMined/PyDP

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.