benovamurat/dp-analytics-toolkit
GitHub: benovamurat/dp-analytics-toolkit
一个轻量级 Python 差分隐私工具包,为产品分析场景提供可审计的噪声机制、隐私预算组合与评估工具。
Stars: 0 | Forks: 0
# DP Analytics Toolkit
[](https://www.python.org/)
[](./LICENSE)
[](https://numpy.org/)
[](https://scipy.org/)
## 这是什么
`dp-analytics-toolkit` 是一个小巧、依赖轻量的 Python 包,它实现了产品分析团队实际使用的核心差分隐私原语:用于计数、总和与均值的 Laplace 机制;带有 Renyi-DP 统计的 Gaussian 机制;用于限制单个用户对查询贡献度的敏感度助手;用于跟踪跨查询累积隐私预算的基础、高级和 Renyi-DP 组合;用于中央服务器不在信任边界内的遥测场景的 local-DP 原语(随机响应和基于 Bloom filter 的简化版 RAPPOR);通过 report-noisy-max 实现的 DP 直方图和 top-k;以及用于校准和验证部署的 accuracy-vs-epsilon 与经验泄露审计工具。
它不硬依赖 `openddp` 或 `diffprivlib`。这里提供的机制和统计器是完全根据标准的公开文献从零编写的,因此可以在一个地方对数学逻辑进行审计。依赖项包括 `numpy`、`scipy`、`pandas` 和 `matplotlib`。
## 为什么会有这个项目
差分隐私是一种正式的数学保证,具有精确的实际影响:注入到聚合数据中的噪声、随每次查询而消耗的隐私预算,以及随着群体规模变小而下降的准确性。是否采用 DP 很少是因为数学原因,而在于该保证是否能映射到威胁模型,以及准确性的损失是否可恢复。此工具包是长篇文章 [产品分析中的差分隐私](https://productphilosophy.com/articles/privacy-preserving-analytics-differential-privacy) 的配套代码,该文章详细介绍了形式化体系、生产环境部署(美国人口普查局、Apple、Google 的 RAPPOR)以及失败模式。这些代码可让你重现文章中的 accuracy-vs-epsilon 曲线,根据已发表的边界对机制进行审计,并在无需引入重型生产库的情况下对内部部署进行原型设计。
## 安装
```
pip install -e .
```
若要同时安装测试依赖项:
```
pip install -e ".[test]"
```
本包支持 Python 3.10 及更新版本。
## 快速入门
针对合成产品分析事件,在 epsilon = 1.0 的条件下分别发布带有噪声的计数和均值,并跟踪累积预算:
```
import numpy as np
from dp_analytics import (
BasicComposition,
generate_synthetic_events,
laplace_count,
laplace_mean,
)
rng = np.random.default_rng(2024)
events = generate_synthetic_events(n_users=5000, avg_sessions_per_user=4.0, seed=42)
budget = BasicComposition()
# 查询 1:premium-feature 打开次数的 noisy count。
true_count = int(events["opened_premium_feature"].sum())
noisy_count = laplace_count(true_count, epsilon=1.0, rng=rng)
budget.spend(1.0, label="count_premium_opens")
# 查询 2:noisy mean session 时长,每个 session 截断至 [0, 60]。
noisy_mean = laplace_mean(
events["duration_minutes"].values,
epsilon=1.0,
lower=0.0,
upper=60.0,
n_known=len(events),
rng=rng,
)
budget.spend(1.0, label="mean_duration")
print(f"true count : {true_count}")
print(f"noisy count: {noisy_count:.2f}")
print(f"noisy mean : {noisy_mean:.4f} (true {events['duration_minutes'].mean():.4f})")
print(budget)
```
端到端运行:
```
python examples/quickstart.py
python examples/accuracy_eps_curve.py
python examples/local_dp_demo.py
```
## 方法
### Epsilon-差分隐私
如果对于每一对仅相差一条记录的数据集 `D` 和 `D'`,以及每一个事件 `S`,随机化算法 `M` 满足:
```
P(M(D) in S) <= exp(epsilon) * P(M(D') in S)
```
则其满足 `epsilon`-DP。`epsilon` 越小,保证越强。`(epsilon, delta)`-DP 允许该边界以 `delta` 的概率失效,通常将其设置为最多 `1/n`。这种放宽正是使得 Gaussian 噪声(以及更紧凑的组合)在实践中可行的原因。
### Laplace 机制
对于 L1 敏感度为 `Delta_1` 的实值查询,释放:
```
M(D) = q(D) + Lap(0, Delta_1 / epsilon)
```
满足 `epsilon`-DP。对于 `epsilon = 1` 时的计数查询(敏感度为 1),噪声标准差为 `sqrt(2) approx 1.41`。
### Gaussian 机制
对于 L2 敏感度为 `Delta_2` 的向量值查询,释放:
```
M(D) = q(D) + N(0, sigma^2 * I)
```
且满足:
```
sigma >= Delta_2 * sqrt(2 * ln(1.25 / delta)) / epsilon
```
对于 `(0, 1]` 内的 `epsilon`,满足 `(epsilon, delta)`-DP。在重复查询下,Gaussian 机制的组合效果远好于 Laplace 机制;合适的统计器是 Renyi DP。
### 组合
提供了三种统计器:
| 统计器 | 使用场景 |
|---|---|
| `BasicComposition` | 少量独立查询;epsilon 相加。 |
| `advanced_composition` | 具有较小单次查询 epsilon 的多次查询;epsilon 以 `O(sqrt(k))` 增长。 |
| `RDPAccountant` | 多次 Gaussian 查询;跟踪各阶的 Renyi 散度并在发布时转换为 `(epsilon, delta)`-DP。 |
### 随机响应
对于二元属性,随机响应 (Warner 1965) 满足 `epsilon`-local-DP:每个用户以 `p = e^epsilon / (e^epsilon + 1)` 的概率报告真实比特位,否则报告翻转的比特位。总体比例的无偏估计量为:
```
pi_hat = (y_bar + p - 1) / (2 * p - 1)
```
### 简化版 RAPPOR
对于分类属性,单次 RAPPOR (Erlingsson et al. 2014) 将每个用户的值哈希到 Bloom filter 中,应用基于比特位的随机响应,并对大量用户进行聚合。提供的实现使用普通最小二乘法结合对候选词汇表的非负性投影;它是用于教学级别的,并非部署的多轮系统。
## 示例:eps=2 与 eps=0.1 下的 DP 直方图
重尾分类分布(例如 30,000 名用户的表情符号频率遥测)在 `epsilon = 2` 时是可恢复的,此时每个桶的噪声标准差为 `1 / 2 = 0.5`;而在 `epsilon = 0.1` 时会出现明显退化,此时每个桶的噪声标准差为 `1 / 0.1 = 10`。
```
import numpy as np
import pandas as pd
from dp_analytics import dp_histogram
from dp_analytics.data import generate_categorical_telemetry
values, true_counts = generate_categorical_telemetry(n_users=30000, seed=3)
rng = np.random.default_rng(0)
for eps in [2.0, 0.1]:
out = dp_histogram(values, epsilon=eps, rng=rng)
out["rel_err_pct"] = (
(out["released_count"] - out["true_count"]).abs()
/ out["true_count"].clip(lower=1) * 100.0
)
print(f"\nepsilon = {eps}")
print(out.to_string(index=False))
```
在 `epsilon = 2` 时,分布头部的相对误差通常在 1% 以下。在 `epsilon = 0.1` 时,前几项的排名顺序通常会被保留,但长尾部分会被噪声主导;这就是文章中描述的小样本(small-`n`)崩溃现象。
## API
```
from dp_analytics import (
# Mechanisms.
laplace_count, laplace_sum, laplace_mean, laplace_scale,
gaussian_mechanism, gaussian_sigma_classic,
# Sensitivity.
clip_contributions, bounded_sensitivity,
# Accounting.
BasicComposition, advanced_composition, RDPAccountant,
# Local DP.
randomize_binary, estimate_proportion_rr, RAPPOR,
# Queries.
dp_histogram, dp_topk,
# Evaluation.
accuracy_vs_epsilon, empirical_leakage_audit,
# Data.
generate_synthetic_events, generate_binary_telemetry,
)
```
每个公共函数都带有包含正式定义和参数约束的 docstring。
## 测试
```
pytest -q
```
测试套件涵盖:基于 `n = 50,000` 个样本的 Laplace 和 Gaussian 噪声分布的均值与方差;裁剪边界;基础组合(epsilon 相加);与 Gaussian 机制匹配 `rho = alpha / (2 sigma^2)` 的 RDP 闭式解;大样本上的随机响应估计量无偏性;可忽略噪声下的 DP 直方图质量守恒;以及大 epsilon 下恢复真实排名的 DP top-k。
## 局限性
从头开始编写的目的是为了确保数学逻辑可被审计,而不是为了发布生产级库。对于任何实际部署,以下几点非常重要:
1. **效用损失与特定工作负载有关。** 准确性与隐私的前沿取决于群体规模、查询和后处理。对于规模在几千以下的群体,任何合理的 epsilon 设置下的 DP 产生的噪声都会掩盖信号;请进行聚合或选择不同的模型。
2. **侧信道风险。** 朴素的浮点数 Laplace 和 Gaussian 分布实现会通过浮点表示的低位发生泄露 (Mironov 2012)。该工具包依赖于 NumPy 的 PRNG,它适用于原型设计和审计,但不适用于对抗性生产环境的正确 RNG。
3. **组合的正确性取决于统计器是否与部署相匹配。** `BasicComposition` 的计算结果适用于独立的 `(epsilon, delta)`-DP 发布。如果在查询中使用了相同的含噪中间结果,则不属于标准的组合设定,提供的统计器将不再适用。
4. **简化版 RAPPOR 没有纵向防御能力。** 已部署的 Google 系统添加了“永久随机响应”层,以防止对同一用户的重复观察;本工具包仅实现了单次机制。
5. **敏感度校准由用户负责。** 错误的敏感度参数会悄无声息地导致隐私保证失效。提供的 `bounded_sensitivity` 助手仅作为基础脚手架,但单条记录贡献度的边界属于领域问题。
## 参考文献
- Dwork, C., McSherry, F., Nissim, K., Smith, A. (2006).
Calibrating Noise to Sensitivity in Private Data Analysis. TCC.
- Dwork, C., Roth, A. (2014). The Algorithmic Foundations of
Differential Privacy. Foundations and Trends in Theoretical
Computer Science.
- Mironov, I. (2017). Renyi Differential Privacy. CSF.
- Mironov, I. (2012). On Significance of the Least Significant Bits for
Differential Privacy. CCS.
- Erlingsson, U., Pihur, V., Korolova, A. (2014). RAPPOR:
Randomized Aggregatable Privacy-Preserving Ordinal Response. CCS.
- Abadi, M., Chu, A., Goodfellow, I., McMahan, H. B., Mironov, I.,
Talwar, K., Zhang, L. (2016). Deep Learning with Differential
Privacy. CCS.
- Warner, S. L. (1965). Randomized Response: A Survey Technique for
Eliminating Evasive Answer Bias. JASA.
- Dwork, C., Rothblum, G., Vadhan, S. (2010). Boosting and
Differential Privacy. FOCS.
- Jagielski, M., Ullman, J., Oprea, A. (2020). Auditing Differentially
Private Machine Learning: How Private is Private SGD? NeurIPS.
## BibTeX
```
@inproceedings{dwork2006calibrating,
title = {Calibrating Noise to Sensitivity in Private Data Analysis},
author = {Dwork, Cynthia and McSherry, Frank and Nissim, Kobbi and Smith, Adam},
booktitle = {Theory of Cryptography Conference (TCC)},
year = {2006}
}
@book{dwork2014algorithmic,
title = {The Algorithmic Foundations of Differential Privacy},
author = {Dwork, Cynthia and Roth, Aaron},
publisher = {Foundations and Trends in Theoretical Computer Science},
year = {2014}
}
@inproceedings{mironov2017renyi,
title = {Renyi Differential Privacy},
author = {Mironov, Ilya},
booktitle = {Computer Security Foundations Symposium (CSF)},
year = {2017}
}
@inproceedings{erlingsson2014rappor,
title = {RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response},
author = {Erlingsson, Ulfar and Pihur, Vasyl and Korolova, Aleksandra},
booktitle = {ACM Conference on Computer and Communications Security (CCS)},
year = {2014}
}
@inproceedings{abadi2016dpsgd,
title = {Deep Learning with Differential Privacy},
author = {Abadi, Martin and Chu, Andy and Goodfellow, Ian and McMahan,
H. Brendan and Mironov, Ilya and Talwar, Kunal and Zhang, Li},
booktitle = {ACM Conference on Computer and Communications Security (CCS)},
year = {2016}
}
```
## 许可证
MIT,版权所有 2026 Murat Ova。详见 [LICENSE](./LICENSE)。
标签:Python, 代码示例, 差分隐私, 数据分析, 数据隐私, 无后门, 网络安全, 逆向工具, 隐私保护