差异性隐私:比较库



本文是一个实用的应用比较。它没有解释差异隐私的所有细节。如果您想更深入地研究这个问题,请参考文章末尾的链接。

差异隐私(更准确地说是ε-差异隐私的承诺是提供一种可测量的方法,以在公共聚合私有数据集中的数据平衡数据隐私准确性

假设您有一个设置滑块:

  • 将其移到左侧-完全保留数据集中数据集中人员的隐私,但同时给信息增加了很多干扰,降低了汇总统计信息的准确性;
  • 将其移到右边-您可以获得汇总统计信息的最佳准确性,但可以从数据集中揭示有关人员的私人信息。

最重要的是,滑块可以平移到秤的任何位置,可以为特定用例选择天平。

数据如何转换


ε-差分隐私使您可以使用正值ε(ε)在隐私和准确性之间找到平衡。如果ε小,那么我们将保持更多的隐私权,但会损害准确性。如果ε大,则隐私会因为准确性而受损。 ε的值从0到无穷大。

差分隐私库实现了不同的技术,这些技术将epsilon参数作为输入值并将与ε逆的随机噪声添加原始数据集中的值。即,ε越小,添加的噪声越大。

一些库使用其他参数并提供随机噪声控制工具,例如,从中获取随机数的概率密度(拉普拉斯分布,正态分布等)。

一些图书馆也实现了概念隐私的预算(预算隐私):每个函数被调用时,该库由用户使用预分配预算集的量。理论依据如下:每次发布新数据时,攻击者更有可能从数据集中提取有关人员的信息。并且在隐私预算的帮助下,库可能会返回错误而不是值。

差异隐私库的比较


使用相同的方法将三个库及其与给定数据集的工作进行比较:


我们将看到数据集的大小和所需的隐私级别(epsilon)如何影响准确性。在每种情况下,我们将比较在不同库中获得的结果。

测试数据集


我们将随机生成一个数据集,其中包含一列以千克为单位的人的体重。我们会将这些信息视为机密信息,必须对其保密。每个权重均表示为双值实数。

权重是根据正态分布生成的,其中数据集中的平均权重为70 kg,标准差为30。

出于研究目的,我们将可以生成不同大小的数据集。

这是重量生成代码:

import random

def generate_weight_dataset(dataset_size):
    outpath = f"weights_{dataset_size}.csv"
    mu = 70  # mean
    sigma = 30  # standard deviation
    with open(outpath, "w+") as fout:
        for i in range(dataset_size):
            random_weight = random.normalvariate(mu, sigma)  # normal distribution
            random_weight = abs(random_weight)  # make sure weights are positive
            random_weight = round(random_weight, 1)  # round to 1 decimal digit
            line = f"{random_weight}"
            print(line, file=fout)

对于大小为10,600的数据集,生成的数据将如下所示:


实际平均值应为70左右,因为我们使用的正态分布mean=70但是,这不是一个精确值,因为权重是随机生成的。另外,我们的数据集中没有负权重,最终值四舍五入到小数点后一位。在这种情况下,实际平均值为70.34812570579449,标准偏差为29.488380395675765。

请注意,我们所做的所有这些只是为了使数据集看起来像一组真实数据。价值的分布不会影响我们将要讨论的估计。

使用库


让我们看一下使用库的方法。我们将始终使用相同的参数进行比较。例如,在所有情况下,将有相同的输入epsilon值。对于测量,我们将使用数据集的平均值。所有考虑的库都使用随机噪声添加机制实现了平均值,偏差,求和等运算。通常使用拉普拉斯机制。平均值搜索操作是任意选择的,它允许我们使用相同的机制来测试所有操作。

我们使用IBM库(Python)计算差异隐私的平均值:

import diffprivlib.tools.utils

def dp_mean(weights, epsilon, upper):
    dp_mean = diffprivlib.tools.utils.mean(weights, epsilon=epsilon, range=upper)
    return dp_mean

upper = max(weights)
epsilon = 1.0
dpm = dp_mean(weights, epsilon, upper)

与Google库(C ++)相同:

double dp_mean(std::list<double> weights, double epsilon, double lower, double upper) {
    std::unique_ptr<differential_privacy::BoundedMean<double>> mean_algorithm = 
    differential_privacy::BoundedMean<double>::Builder()
    .SetEpsilon(epsilon)
    .SetLower(0.0)
    .SetUpper(upper)
    .Build()
    .ValueOrDie();

    for (auto weight : weights) {
        mean_algorithm->AddEntry(weight);
    }
    double privacy_budget = 1.0;
    auto output = mean_algorithm->PartialResult(privacy_budget).ValueOrDie();
    return differential_privacy::GetValue<double>(output);
}

请注意,每次使用Google图书馆时,我们都会使用1.0的整体隐私权预算。并且IBM库不接受此参数。

现在,我们使用diffpriv(语言R)计算DP的平均值:

library(diffpriv)

dp_mean <- function(xs, epsilon) {
  ## a target function we'd like to run on private data X, releasing the result
  target <- function(X) mean(X)

  ## target seeks to release a numeric, so we'll use the Laplace mechanism---a
  ## standard generic mechanism for privatizing numeric responses
  n <- length(xs)
  mech <- DPMechLaplace(target = target, sensitivity = 1/n, dims = 1)

  r <- releaseResponse(mech, privacyParams = DPParamsEps(epsilon = epsilon), X = xs)
  r$response
}

隐私如何影响准确性


可以通过简单地计算平均值DP和实际平均值之间的差来测量平均值的准确性。

让我们看看当ε改变时平均重量的准确性会发生什么。由于我们要添加随机噪声,因此我们将执行100次运行并计算均方误差,以检查库是否正在生成失真值。

结果应证明误差(实际平均值与平均值DP之差)与ε成反比。如果epsilon大,则误差应该很小,反之亦然。我测试了从e ^ -10到e ^ 10的epsilon值(注意对数刻度)。

该测试使用了10,600行的任意恒定大小的数据集。

标准误差



实际上,误差随着ε的增加而减小。有趣的是,如果epsilon值很小,则Google库具有标准错误限制。在IBM和diffpriv库中,未观察到此情况。

原因在于Google库的源代码片段。在数值机制中:

 //      . 
 //   privacy_budget   .  
  //     (0, 1],        .
  // ,         
  //    ,           0.5 ( 0.4,  0.6  ..).
  virtual double AddNoise(double result, double privacy_budget) {
    if (privacy_budget <= 0) {
      privacy_budget = std::numeric_limits<double>::min();
    }
    //  snapping-,  
    // (2012, "On Significance of the Least Significant Bits For Differential Privacy").
    double noise = distro_->Sample(1.0 / privacy_budget);
    double noised_result =
        Clamp<double>(LowerBound<double>(), UpperBound<double>(), result) +
        noise;
    double nearest_power = GetNextPowerOfTwo(diversity_ / privacy_budget);
    double remainder =
        (nearest_power == 0.0) ? 0.0 : fmod(noised_result, nearest_power);
    double rounded_result = noised_result - remainder;
    return ClampDouble<double>(LowerBound<double>(), UpperBound<double>(),
                               rounded_result);
  }

在bounded-mean.h中:

   //  :    .
    double normalized_sum = sum_mechanism_->AddNoise(
        sum - raw_count_ * midpoint_, remaining_budget);
    double average = normalized_sum / noised_count + midpoint_;
    AddToOutput<double>(&output, Clamp<double>(lower_, upper_, average));
    return output;

当epsilon非常小时(大约小于0.013),差异(等于1 / epsilon)将非常大,并且增加的噪声将为零。因此,该库返回的平均DP等于用于平均值的范围的中间值。图表上红线的起点对此进行了说明。

Diffpriv的均方误差较小,这意味着与使用相同epsilon的其他两个库相比,其准确性更高。为了为diffpriv提供与竞争对手相同的隐私级别,您需要使用较低的epsilon值。

标准偏差


100次运行的误差的标准偏差如下所示:


在epsilon值较小的Google库中,偏差近似恒定,然后迅速赶上IBM库。通常,diffpriv的标准偏差小于其他标准偏差。

数据集大小如何影响准确性


我们正在谈论对DP平均值准确性的影响。

小型数据集的风险之一是个人会对汇总值(即平均值)产生重大影响。因此,如果数据集中只有一个人,则完全准确的平均值将等于该人的确切体重。让我们看看在调整数据集大小时,库如何帮助避免泄露单个信息。

我们将使用epsilon 1.0的任意常数。

标准误差



随着数据集大小的减小,均方误差增加,反之亦然。这是预期的。如果人数很少,那么我想增加一些噪音,以避免泄露私人数据。缺点是对于小型数据集,由于非常低的准确性,聚合值可能变得完全不相关。

对于diffpriv,标准误差更多地取决于数据集大小的变化。但是,这种模式仍然很明显,就像在其他两个库中一样:随着数据集的增长,均方误差减小。但这仅适用于最多约30,000行的数据集。然后错误变化很小。另外,当数据集的大小为17912时,请注意错误大小的异常下降。

标准偏差


您可能会问,对于给定的数据集大小,添加的噪声大小在100次运行中如何变化?为了回答这个问题,让我们为每种数据状态大小绘制100次运行的误差的标准偏差。


对于小型数据集,误差变化较大。但是,Google图书馆的数据集规模为6个峰。IBM库没有观察到这一点,该图更接近线性。

同样,diffpriv通常具有较低的标准偏差。

结论


我们看到,在三个不同的差异性隐私库中采取的措施符合最初的期望。但是,不同的实现方式会导致不同的结果,尤其是在边界情况下,例如epsilon值和Google库很小的情况。实际上,这不会造成干扰,因为用户将不会使用非常大和非常小的数据集以及非常小的epsilon值。但是,在这种情况下,磁带库可能会发出警告。

diffpriv的行为与其他两个库明显不同,因此我们建议您谨慎选择epsilon值。

参考文献



All Articles