【敏感度,查询,裁剪代码实现】差分隐私代码实现系列(六)
差分隐私代码实现系列(六)
- 写在前面的话
- 回顾
- 敏感性(Sensitivity)
- 距离(Distance)
- 计算灵敏度(Calculating Sensitivity)
- 计算查询数(Counting Queries)
- 求和查询(Summation Queries)
- 平均查询(Average Queries)
- 裁剪(Clipping)
- 总结
写在前面的话
书上学来终觉浅,绝知此事要躬行。
回顾
1、顺序组合给出的隐私成本的界限是一个上限,两个特定的差异隐私机制的实际隐私成本可能小于此,但永远不会比这个更大。
2、实际的隐私损失似乎略低于由顺序组合确定的上限ϵ\epsilonϵ。
3、如果数据集中的每个参与者都向XXX贡献了一行,则此行将恰好出现在块之一x1,...,xkx_1, ..., x_kx1,...,xk中。这意味着FFF只会"看到"这个参与者的数据一次,这意味着ϵ\epsilonϵ的隐私成本适合该个人。由于此属性适用于所有个人,因此每个人的隐私成本为ϵ\epsilonϵ。
4、单个行不可能同时具有属性的两个值,因此以这种方式定义直方图中条柱可以保证它们不相交。
5、对于在构建列联表时考虑的任何一组数据属性,任何单个行都不可能同时具有多个值。因此,在这里使用并行组合也是安全的。
6、执行后处理,这可能会减少噪声或改善机制输出中的信号。
之前谈了一下差分隐私的属性,现在来聊一下差分隐私敏感度的问题~
敏感性(Sensitivity)
正如我们在对拉普拉斯机制进行讨论时所提到的,确保给定查询的差分隐私所需的噪声量取决于查询的敏感性。
粗略地说,函数的灵敏度反映了函数的输出在其输入更改时将更改的量。
回想一下,拉普拉斯机制定义了一个机制F(x)F(x)F(x),如下所示:
F(x)=f(x)+Lap(sϵ)F(x) = f(x) + \textsf{Lap}(\frac{s}{\epsilon}) F(x)=f(x)+Lap(ϵs)
其中f(x)f(x)f(x)是确定性函数(查询),ϵ\epsilonϵ是隐私参数,sss是fff的敏感度。
对于函数f:D→Rf : \mathcal{D} \rightarrow \mathbb{R}f:D→R将数据集(D\mathcal{D}D)映射到实数,fff的全局敏感度定义如下:
GS(f)=maxx,x′:d(x,x′)<=1∣f(x)−f(x′)∣GS(f) = \max_{x, x': d(x,x') <= 1} |f(x) - f(x')| GS(f)=x,x′:d(x,x′)<=1max∣f(x)−f(x′)∣
这里,d(x,x′)d(x, x')d(x,x′)表示两个数据集xxx 和x′x'x′之间的距离,我们说如果两个数据集的距离为 1 或更小,则它们是相邻数据集。
如何定义这个距离对我们获得的隐私定义有很大的影响,稍后我们将详细讨论数据集上的距离指标。
全局敏感度的定义表明,对于任何两个相邻的数据集xxx 和x′x'x′,f(x)f(x)f(x) 和f(x′)f(x')f(x′)之间的差异最多为GS(f)GS(f)GS(f)。
这种敏感度度称为"全局",因为它独立于所查询的实际数据集(它适用于相邻xxx 和x′x'x′的任何选择)。
另一种灵敏度度量,称为局部灵敏度,将其中一个数据集固定为被查询的数据集;我们将在后面的部分中考虑此度量值。大家感兴趣可以去我的博客:全局敏感度,局部敏感度和平滑敏感度到底有什么区别?【差分隐私】看看。
后续,当我们说"敏感性"时,我们指的是全局敏感性。
距离(Distance)
前面描述的距离度量d(x,x′)d(x,x')d(x,x′)可以通过许多不同的方式定义。
直观地说,如果两个数据集的数据恰好在一个人的数据中不同,则两个数据集之间的距离应等于 1(即数据集是相邻数据集)。
这个想法在某些情况下很容易形式化(例如,在美国人口普查中,每个人都提交包含其数据的单个响应),但在其他上下文中(例如位置轨迹,社交网络和时间序列数据)极具挑战性。
包含行的数据集的常见正式定义是考虑两者之间不同的行数。
当每个人的数据都包含在一行中时,此定义通常有意义。
形式上,此距离定义被编码为两个数据集之间的对称差值:
d(x,x′)=∣x−x′∪x′−x∣d(x, x') = | x - x' \cup x' - x | d(x,x′)=∣x−x′∪x′−x∣
这个特定的定义有几个有趣和重要的含义:
如果x′x'x′是通过添加一行从xxx构造的,则d(x,x′)=1d(x,x') = 1d(x,x′)=1
如果x′x'x′是通过删除一行从xxx构造的,则d(x,x′)=1d(x,x') = 1d(x,x′)=1
如果x′x'x′是通过修改一行从xxx构造的,则d(x,x′)=2d(x,x') = 2d(x,x′)=2
换句话说,添加或删除行会导致相邻的数据集;修改行会导致在距离为 2处生成数据集。
这种对距离的特殊定义导致了通常所说的无界差分隐私。
还可以使用许多其他定义,包括一个称为有界差分隐私的定义,其中修改数据集中的单个行确实会产生相邻的数据集。
现在,我们将坚持上面定义的对称差分的形式定义。我们将在后面的部分中讨论替代定义。
计算灵敏度(Calculating Sensitivity)
我们如何确定特定感兴趣函数的灵敏度?对于实数上的一些简单函数,答案是显而易见的。
f(x)=xf(x) = xf(x)=x的全局敏感度为 1,因为将xxx变化 1 会将f(x)f(x)f(x)更改为 1
f(x)=x+xf(x) = x+xf(x)=x+x的全局敏感度为 2,因为将xxx变化 1 会将f(x)f(x)f(x)更改为 2
f(x)=5∗xf(x) = 5*xf(x)=5∗x的全局灵敏度为 5,因为将xxx变化 1 会将f(x)f(x)f(x)更改为 5
f(x)=x∗xf(x) = x*xf(x)=x∗x的全局敏感度是无界的,因为f(x)f(x)f(x)的变化取决于xxx的值
对于将数据集映射到实数的函数,我们可以执行类似的分析。我们将考虑表示常见聚合数据库查询的函数:计数、总和平均值。
计算查询数(Counting Queries)
计数查询(COUNT
在 SQL 中)计算数据集中满足特定属性的行数。
根据经验,计数查询的敏感度始终为 1。
这是因为向数据集添加行最多可以将查询的输出增加 1:新行具有所需的属性,计数增加 1,或者不增加,并且计数保持不变(删除行时计数可能会相应减少)。
"数据集中有多少人?
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')adult = pd.read_csv("adult_with_pii.csv")
adult.shape[0]
“有多少人的教育状况超过 10 岁?”
adult[adult['Education-Num'] > 10].shape[0]
“有多少人的教育状况等于或低于 10 岁?”
adult[adult['Education-Num'] <= 10].shape[0]
“有多少人叫 Joe Near?”
adult[adult['Name'] == 'Joe Near'].shape[0]
求和查询(Summation Queries)
求和查询(SUM
在 SQL 中)对数据集行的属性值求和。
“受教育程度超过 10 岁的人的年龄总和是多少?”
adult[adult['Education-Num'] > 10]['Age'].sum()
这些查询的敏感度并不像计数查询数那样简单。
向数据集添加新行将按新人的年龄增加示例查询的结果。
这意味着查询的敏感度取决于我们添加的行的内容。
我们想提出一个具体的数字来表示查询的敏感性。不幸的是,没有这样数字真正存在。
例如,我们可以声称灵敏度为125,但这样会揭露了,我们添加到数据库中的行对应于超过125岁的人,这将违反我们的声明。对于我们提出的任何数字,添加的行都可能违反我们的声明。
你可能会对这一点持怀疑态度。假设我们声称灵敏度是1000 - 我们不太可能找到一个1000岁的人来违反这一说法。在这个特定的领域 - 年龄 - 对于一个人的年龄有一个非常合理的上限。最年长的人活到122岁,所以125的上限似乎是合理的。
但这并不能证明没有人会活到126岁。在其他领域(例如收入),可能更难提出合理的上限。
根据经验,当被求和属性的值不存在下限和上限时,求和查询具有无限的敏感度。
当存在下限和上限时,求和查询的敏感度等于它们之间的差值。后面会介绍"裁剪"的技术,用于在不存在边界时强制执行边界,以便将具有无界敏感度的求和查询转换为具有有限敏感度的查询。
平均查询(Average Queries)
平均查询(AVG
在 SQL 中)计算特定列中属性值的平均值。
"受教育程度超过 10 岁的人的平均年龄是多少?“
adult[adult['Education-Num'] > 10]['Age'].mean()
使用差分隐私回答平均查询的最简单方法是将其重新表述为两个查询:求和查询除以计数查询。对于上面的例子:
adult[adult['Education-Num'] > 10]['Age'].sum() / adult[adult['Education-Num'] > 10]['Age'].shape[0]
可以根据之前说的方法计算这两个查询的敏感度。从而可以计算每个答案的噪声答案(例如,使用拉普拉斯机制),并且可以对噪声答案进行划分以获得差分隐私均值。两个查询的总隐私成本可以通过顺序组合来计算。
裁剪(Clipping)
具有无限敏感度的查询无法使用拉普拉斯机制使用差分隐私直接回答。
幸运的是,我们通常可以通过称为裁剪的过程将这些查询转换为具有有限敏感性的等效查询。
裁剪的基本思想是对属性值强制实施上限和下限。
例如,125岁以上的年龄可以被"裁剪"到正好125岁。裁剪后,我们保证所有年龄段均为125岁或以下。
因此,对裁剪数据进行求和查询的敏感性等于裁剪中使用的上限和下限之差:upper−lowerupper - lowerupper−lower。
例如,以下查询的敏感度为 125:
adult['Age'].clip(lower=0, upper=125).sum()
执行裁剪的主要挑战是确定上限和下限。
对于年龄,这很简单,没有人的年龄小于0,可能没有人会超过125岁。
如前所述,在其他领域,这要困难得多。
此外,在裁剪中丢失的信息量与确保差分隐私所需的噪声量之间存在权衡。当上下裁剪边界靠得更近时,灵敏度较低,需要的噪声更小,以确保差分隐私。
但是,激进的剪切通常会从数据中删除大量信息。这种信息丢失往往会导致准确性的损失,这超过了灵敏度降低导致的噪声改善的程度。
根据经验,请尝试将剪切边界设置为包含 100% 的数据集,或尽可能接近。在某些领域(例如,图查询,我们稍后将研究)比其他领域更难。
通过查看数据来确定剪切边界,这一点看起来很有道理,但其实里面存在问题。例如,我们可以查看数据集中年龄的直方图,以确定适当的上限:
plt.hist(adult['Age'])
plt.xlabel('Age')
plt.ylabel('Number of Records');
从这个直方图中可以清楚地看出,这个特定数据集中没有人超过90,所以上限90就足够了。
但是,重要的是要注意,此方法不满足差分隐私。
如果我们通过查看数据来选择裁剪边界,则边界本身可能会揭示有关数据的某些信息。
通常,剪切边界是通过使用数据集的属性来决定的,该属性无需查看数据即可知道(例如,数据集包含的年龄可能介于 0 和 125 之间),或者通过执行差分隐私查询来评估剪切边界的不同选择。
要使用第二种方法,我们通常将下限设置为 0,然后慢慢增加上限,直到查询的输出停止更改(这意味着我们没有通过增加边界来包含任何新数据)。
例如,让我们尝试计算从 0 到 100 的剪切边界的年龄总和,对每个边界使用拉普拉斯机制来确保差分隐私:
def laplace_mech(v, sensitivity, epsilon):return v + np.random.laplace(loc=0, scale=sensitivity/epsilon)epsilon_i = .01
plt.plot([laplace_mech(adult['Age'].clip(lower=0, upper=i).sum(), i, epsilon_i) for i in range(100)])
plt.xlabel('Clipping Bound for Age')
plt.ylabel('Total Sum');
按顺序组合构建此图的总隐私成本为ϵ=1\epsilon = 1ϵ=1,因为我们执行了 100 个查询,每个查询ϵi=0.01\epsilon_i = 0.01ϵi=0.01。很明显,结果在upper = 80
值附近趋于一致,因此这对于剪切边界来说是一个不错的选择。
我们可以对来自任何数值域的数据属性使用相同的方法,但它有助于提前了解数据的规模。
例如,尝试在0到100之间修剪年收入的值不会很好,我们甚至无法找到合理的上限。
当数据刻度未知时,可以很好地工作的一种改进是根据对数刻度测试上限。
xs = [2**i for i in range(15)]
plt.plot(xs, [laplace_mech(adult['Age'].clip(lower=0, upper=i).sum(), i, epsilon_i) for i in xs])
plt.xscale('log')
plt.xlabel('Clipping Bound for Age')
plt.ylabel('Total Sum');
这种方法允许我们使用少量查询测试大量可能的边界,但代价是确定完美边界的精度较低。
随着上限变得非常大,噪声将开始淹没信号。
请注意,对于最大的裁剪参数,总和会剧烈波动!关键是要寻找图形中相对平滑(意味着低噪声)且不增加(意味着裁剪边界足够)的区域。
在这里,这大致发生在28=2562^8 = 25628=256处,这是我们之前推导的上限的合理近似值。
总结
1、函数的灵敏度反映了函数的输出在其输入更改时将更改的量。
2、这种敏感度度称为"全局",因为它独立于所查询的实际数据集(它适用于相邻xxx 和x′x'x′的任何选择)。
3、这个想法在某些情况下很容易形式化(例如,在美国人口普查中,每个人都提交包含其数据的单个响应),但在其他上下文中(例如位置轨迹,社交网络和时间序列数据)极具挑战性。
4、根据经验,当被求和属性的值不存在下限和上限时,求和查询具有无限的敏感度。
5、具有无限敏感度的查询无法使用拉普拉斯机制使用差分隐私直接回答。
6、裁剪的基本思想是对属性值强制实施上限和下限。
7、此外,在裁剪中丢失的信息量与确保差分隐私所需的噪声量之间存在权衡。当上下裁剪边界靠得更近时,灵敏度较低,需要的噪声更小,以确保差分隐私。但是,激进的剪切通常会从数据中删除大量信息。这种信息丢失往往会导致准确性的损失,这超过了灵敏度降低导致的噪声改善的程度。根据经验,请尝试将剪切边界设置为包含 100% 的数据集,或尽可能接近。在某些领域(例如,图查询,我们稍后将研究)比其他领域更难。
8、请注意,对于最大的裁剪参数,总和会剧烈波动!关键是要寻找图形中相对平滑(意味着低噪声)且不增加(意味着裁剪边界足够)的区域。
【敏感度,查询,裁剪代码实现】差分隐私代码实现系列(六)相关推荐
- 【局部敏感度的问题代码实现】差分隐私代码实现系列(八)
差分隐私代码实现系列(八) 写在前面的话 回顾 局部敏感度(Local Sensitivity) 均值的局部灵敏度(Local Sensitivity of the Mean) 通过局部灵敏度实现差分 ...
- 【机器学习与差分隐私代码实现】差分隐私代码实现系列(十二)
差分隐私代码实现系列(十二) 写在前面的话 回顾 机器学习与差分隐私 使用 Scikit-Learn 进行逻辑回归 什么是模型? 使用梯度下降训练模型 梯度下降的单一步骤 梯度下降算法 梯度下降与差分 ...
- 【我们为什么用高斯机制?】差分隐私代码实现系列(七)
差分隐私代码实现系列(七) 写在前面的话 回顾 松弛差分隐私(Approximate Differential Privacy) 高斯机制(The Gaussian Mechanism) 矢量值函数及 ...
- 【本地差分隐私与随机响应代码实现】差分隐私代码实现系列(十三)
差分隐私代码实现系列(十三) 写在前面的话 回顾 本地差分隐私 随机响应 一元编码 总结 写在前面的话 书上学来终觉浅,绝知此事要躬行. 回顾 1.梯度下降是一种通过根据损失的梯度更新模型来使损失变小 ...
- 【指数机制代码实现】差分隐私代码实现系列(十)
差分隐私代码实现系列(十) 写在前面的话 回顾 指数机制 发明指数机制的动机 指数机制的描述 日期的例子 指数机制的特点 有限集合的指数机制 报告最大噪声算法 指数机制作为差分隐私的基本机制 总结 写 ...
- 【Rényi差分隐私和零集中差分隐私(差分隐私变体)代码实现】差分隐私代码实现系列(九)
差分隐私代码实现系列(九) 写在前面的话 回顾 差分隐私的变体 发明变体的动机 最大散度和Rényi散度 Rényi差分隐私 零集中差分隐私 差分隐私变体的组合情况 总结 写在前面的话 书上学来终觉浅 ...
- 【拉普拉斯机制代码实现demo】差分隐私代码实现系列(四)
差分隐私代码实现系列(四) 写在前面的话 回顾 差分隐私(Differential Privacy) 拉普拉斯机制(The Laplace Mechanism) 多少噪音就足够了?(How Much ...
- 【k-匿名(k-Anonymity)代码实现】差分隐私代码实现系列(三)
差分隐私代码实现系列(三) 写在前面的话 回顾 kkk-匿名(kkk-Anonymity) 检查kkk-匿名(Checking for kkk-Anonymity) 生成满足kkk-匿名的数据(Gen ...
- 【差分隐私组合定理,直方图,列联表代码实现】差分隐私代码实现系列(五)
差分隐私代码实现系列(五) 写在前面的话 回顾 差分隐私的属性(Properties of Differential Privacy) 顺序组成(Sequential composition) 平行组 ...
最新文章
- Java报表工具技巧--如何在Style Report创建用户自定义报表模板
- python计算向量夹角代码
- SQL:RAND()返回随机数
- java天气app_MVP+RxJava2+Retrofit2 实况天气app
- [vue] 怎么在vue中使用插件?
- 容器映像_构建微小的容器映像
- 关于递归和斐波那契数列
- Percona 成为 MariaDB 基金会铜牌赞助商
- php-mvc模式(2)
- 论文写作课程体会和总结
- 会计专业与计算机专业结合复合型,对会计专业学生学习计算机的建议
- C# 线程安全的单例模式
- Excel 做统计学分析
- python定义一个变量为整型怎么写_python里怎么定义一个变量
- ios视频通话三方_自己实现简易版 多人视频通话 iOS Android
- 小程序开发费用一览表,如果你也想要用低成本制作出自己的小程序,来了解一下!
- matlab设计高通系统,用matlab设计高通滤波器雪比切夫、fir两种方法 课程设计HPF.doc...
- 前端js以application/octet-stream方式上传文件
- 常见sketch简介
- 夏季晚睡早起符合养生原则
热门文章
- vss团队开发工具使用(个人学习心得)
- teched2006会议资料
- 泛型技巧系列:类型字典和Type Traits
- RestAPI的进化之路,后端MVVM模式或许来临,通过观察者模式,后端收集前端的GET类请求,主动推送数据变更到前端
- 面试官系统精讲Java源码及大厂真题 - 42 常用的 Lambda 表达式使用场景解析和应用
- 【C语言】在有序数组中插入一个数,保证它依然有序
- web开发方法_确保进入Web开发的最快方法
- python怎样实现界面的切换_python tkinter实现界面切换的示例代码
- visual foxpro 程序员指南_好程序员云计算培训分享云计算中SOA是什么?
- debian9.8无法切换中文输入法