𝑘 -Anonymity
在大数据的时代,很多机构需要面向公众或研究者发布其收集的数据,例如医疗数据,地区政务数据等。这些数据中往往包含了个人用户或企业用户的隐私数据,这要求发布机构在发布前对数据进行脱敏处理。K匿名算法是比较通用的一种数据脱敏方法。
为解决链接攻击所导致的隐私泄露问题,引入k-匿名 (k-anonymity) 方法。k-匿名通过概括(对数据进行更加概括、抽象的描述)和隐匿(不发布某些数据项)技术,发布精度较低的数据,使得同一个准标识符至少有k条记录,使观察者无法通过准标识符连接记录。
概括(Generalization):指对数据进行更加概括、抽象的描述,使得无法区分具体数值,例如年龄这个数据组,概括成一个年龄段(例如上表中的>=40岁)。
隐匿(Suppression):指不发布某些信息,例如上表中的用*号替换邮编的末三位。通过降低发布数据的精度,使得每条记录至少与数据表中其他的K-1条记录具有完全相同的准标识符属性值,从而降低链接攻击所导致的隐私泄露风险。
𝑘 -匿名sweeney2002是一个正式的隐私定义。定义𝑘-匿名是为了规范我们的直觉,即一条辅助信息不应“过多”缩小个人可能的记录集,𝑘-匿名旨在确保每个人都能“融入人群”
应该学会:
1.定义
2.如何检查
3.生成数据实施k-匿名
4.局限性
3.1检查𝑘 -Anonymity
开始小数据集看是否满足𝑘 -Anonymity,数据包含年龄外加两个分数。
显然如果k>1不满足𝑘 -Anonymity,每个数据集当k=1时候满足,因为每行可以形成其大小为1的组。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
raw_data = {
'first_name': ['Jason', 'Molly', 'Tina', 'Jake', 'Amy'],
'last_name': ['Miller', 'Jacobson', 'Ali', 'Milner', 'Cooze'],
'age': [42, 52, 36, 24, 73],
'preTestScore': [4, 24, 31, 2, 3],
'postTestScore': [25, 94, 57, 62, 70]}
#df = pd.DataFrame(raw_data, columns = ['first_name', 'last_name', 'age', 'preTestScore', 'postTestScore'])
df = pd.DataFrame(raw_data, columns = ['age', 'preTestScore', 'postTestScore'])
df
age preTestScore postTestScore
0 42 4 25
1 52 24 94
2 36 31 57
3 24 2 62
4 73 3 70
def isKAnonymized(df, k):
for index, row in df.iterrows():
query = ' & '.join([f'{col} == {row[col]}' for col in df.columns])
print(query)
rows = df.query(query)
print(rows)
if rows.shape[0] < k:
return False
return True
isKAnonymized(df, 1)
age == 42 & preTestScore == 4 & postTestScore == 25
age preTestScore postTestScore
0 42 4 25
age == 52 & preTestScore == 24 & postTestScore == 94
age preTestScore postTestScore
1 52 24 94
age == 36 & preTestScore == 31 & postTestScore == 57
age preTestScore postTestScore
2 36 31 57
age == 24 & preTestScore == 2 & postTestScore == 62
age preTestScore postTestScore
3 24 2 62
age == 73 & preTestScore == 3 & postTestScore == 70
age preTestScore postTestScore
4 73 3 70
True
isKAnonymized(df, 2)
False
3.2Generalizing Data to Satisfy 𝑘 -Anonymity
𝑘 -所需的匿名𝑘 通常是通过将数据修改值泛化为不太具体的值来实现的,因此更可能匹配数据集中其他个体的值。例如,精确到一年的年龄可以四舍五入到最接近的10年,或者邮政编码的最右边的数字可能被零替换。对于数值,这很容易实现。我们将使用数据帧的apply方法,并传入一个名为depth的字典,该字典指定每列要用零替换多少位数字。这使我们能够灵活地对不同列进行不同级别的泛化实验。
def generalize(df, depths):
return df.apply(
lambda x: x.apply( # x是获取每一列
lambda y: int( # # y是获取每一行
int(
y / (10 ** depths[x.name])) * (10 ** depths[x.name] # 获取表格每个单位的数据,将其向下取为10的整数倍数
)
)
)
)
# 如果参数变为2 获取表格每个单位的数据,将其向下取为100的整数倍数
depths = {
'age': 1,
'preTestScore': 1,
'postTestScore': 1
}
age preTestScore postTestScore
0 40 0 20
1 50 20 90
2 30 30 50
3 20 0 60
4 70 0 70
Process finished with exit code 0
这个例子说明了实现𝑘 -匿名
3.3更多的数据会改进泛化吗?
因为数据集中只有5个人,所以很难建立由2个或更多共享相同属性的个人组成的组。这个问题的解决方案是使用更多的数据:在包含更多个体的数据集中,通常需要较少的泛化来满足𝑘 -所需的匿名𝑘 .
我们将把每个人的邮政编码、年龄和教育成就视为准标识符。我们将仅投射这些列,并尝试实现𝑘 -匿名𝑘=2。数据已经是𝑘 -匿名用户𝑘=1.
注意,我们只取数据集中的前100行进行此检查-尝试在较大的数据子集上运行isKAnonymized,您会发现它需要很长的时间(例如,运行𝑘=在我的笔记本电脑上检查5000行大约需要20秒)。对于𝑘=2,我们的算法快速找到失败行并快速完成。
adult_data = pd.read_csv("adult_with_pii.csv")
adult_data.head()
df = adult_data[['Age', 'Education-Num']]
df.columns = ['age', 'edu']
isKAnonymized(df.head(100), 1)
True
isKAnonymized(df.head(100), 2)
False
Now, we’ll try to generalize to achieve 𝑘 -Anonymity for 𝑘=2 . We’ll start with generalizing both age and educational attainment to the nearest 10.
# outliers are a real problem!
depths = {
'age': 1,
'edu': 1
}
df2 = generalize(df.head(1000), depths)
isKAnonymized(df2, 2)
df2['age'].hist();
广义结果仍不满足𝑘 -匿名𝑘=2.事实上,我们可以对所有32000行执行此泛化,但仍然无法满足要求𝑘 -匿名𝑘=2-因此,添加更多数据并不一定像我们预期的那样有帮助。
原因是数据集包含异常值,这些异常值与其他人群非常不同。这些人不容易融入任何群体,即使是在泛化之后。即使只考虑年龄,我们也可以看到,添加更多数据不太可能有帮助,因为数据集中很难表示非常低和非常高的年龄。
实现最佳泛化𝑘 -在这种情况下,匿名是非常具有挑战性的。对于年龄在20-40岁之间的代表性较好的人来说,将每一行归纳得更多是过分的,会损害效用。然而,对于年龄范围上限和下限的个体,显然需要更多的概括。这是实践中经常发生的挑战,很难自动解决。事实上𝑘 -匿名性被证明是NP难的。
3.4删除异常值
这个问题的一个解决方案是简单地将数据集中每个个体的年龄限制在特定范围内,从而完全消除异常值。这也会损害效用,因为它会用假年龄代替真实年龄,但这可能比将每一行更多地概括要好。我们可以使用Numpy的剪辑方法来执行此剪辑。我们将年龄限制在60岁或以下,而不考虑教育水平(通过将其限制在一个非常大的值)。
个人理解,使得数据更加泛化,更集中化,从而适配k-Anonymity
dfp = df.clip(upper=np.array([60, 10000000000000]), axis='columns')
depths = {
'age': 1,
'edu': 1
}
df2 = generalize(dfp.head(500), depths)
isKAnonymized(df2, 7)
True
isKAnonymized(df2, 8)
False
3.5总结
𝑘-匿名性是数据的一种属性,它确保每个个体“融入”至少一组𝑘 个人视频。
• 𝑘-匿名性的检查计算成本也很高:朴素的算法是𝑂(𝑛2) ,更快的算法需要
相当大的空间。
• 𝑘-匿名性可以通过泛化数据集来修改数据集,从而使特定值变得更多
公共和团体更容易形成。
• 优化概括极其困难,异常值可能会使其更具挑战性。解决此问题
自动是NP难的。