| Title: | Data Augmentation for Private Posterior Estimation |
|---|---|
| Description: | A data augmentation based sampler for conducting privacy-aware Bayesian inference. The dapper_sample() function takes an existing sampler as input and automatically constructs a privacy-aware sampler. The process of constructing a sampler is simplified through the specification of four independent modules, allowing for easy comparison between different privacy mechanisms by only swapping out the relevant modules. Probability mass functions for the discrete Gaussian and discrete Laplacian are provided to facilitate analyses dealing with privatized count data. The output of dapper_sample() can be analyzed using many of the same tools from the 'rstan' ecosystem. For methodological details on the sampler see Ju et al. (2022) <doi:10.48550/arXiv.2206.00710>, and for details on the discrete Gaussian and discrete Laplacian distributions see Canonne et al. (2020) <doi:10.48550/arXiv.2004.00010>. |
| Authors: | Kevin Eng [aut, cre, cph] |
| Maintainer: | Kevin Eng <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 1.1.0 |
| Built: | 2026-10-06 08:47:20 UTC |
| Source: | https://github.com/mango-empire/dapper |
Generates samples from the private posterior using a data augmentation framework.
dapper_sample( data_model = NULL, sdp = NULL, init_par = NULL, seed = NULL, niter = 2000, warmup = floor(niter/2), chains = 1 )dapper_sample( data_model = NULL, sdp = NULL, init_par = NULL, seed = NULL, niter = 2000, warmup = floor(niter/2), chains = 1 )
data_model |
a data model represented by a |
sdp |
the observed privatized data. Must be a vector or matrix. |
init_par |
initial starting point of the chain. |
seed |
set random seed. |
niter |
number of draws. |
warmup |
number of iterations to discard as warmup. Default is half of niter. |
chains |
number of MCMC chains to run. Can be done in parallel or sequentially. |
Generates samples from the private posterior implied by data_model. The
data_model input must be an object of class privacy which is created
using the new_privacy() constructor. MCMC chains can be run in parallel
using furrr::future_map(). See the furrr package documentation for specifics.
Long computations can be monitored with the progressr package.
A dpout object which contains:
chain: a draws_matrix object containing chains * (niter - warmup) draws from the private posterior.
mean_accept: a (niter - warmup) row matrix containing the average acceptance rate over all latent records for each iteration.
Each column corresponds to a chain.
comp_accept: An n-by-chains matrix, where n is the number of latent records.
Each entry is the mean acceptance rate for one record in one chain over the retained post-warmup iterations.
Ju, N., Awan, J. A., Gong, R., & Rao, V. A. (2022). Data Augmentation MCMC for Bayesian Inference from Privatized Data. arXiv. doi:10.48550/ARXIV.2206.00710
#simulate confidential data # The privacy mechanism adds Gaussian noise to the sample mean. set.seed(1) n <- 100 eps <- 3 y <- rnorm(n, mean = -2, sd = 1) sdp <- mean(y) + rnorm(1, 0, 1/eps) posterior_f <- function(dmat, theta) { x <- c(dmat) xbar <- mean(x) n <- length(x) pr_m <- 0 pr_s2 <- 4 ps_s2 <- 1/(1/pr_s2 + n) ps_m <- ps_s2 * ((1/pr_s2)*pr_m + n * xbar) rnorm(1, mean = ps_m, sd = sqrt(ps_s2)) } latent_f <- function(theta) { matrix(rnorm(100, mean = theta, sd = 1), ncol = 1) } statistic_f <- function(xi, sdp, i) { xi } mechanism_f <- function(sdp, sx) { sum(dnorm(sdp - sx/n, 0, 1/eps, TRUE)) } dmod <- new_privacy(posterior_f = posterior_f, latent_f = latent_f, mechanism_f = mechanism_f, statistic_f = statistic_f, npar = 1) out <- dapper_sample(dmod, sdp = sdp, init_par = -2, niter = 500) summary(out) plot(out) # for parallel computing we 'plan' a session # the code below uses 2 CPU cores for parallel computing library(furrr) plan(multisession, workers = 2) out <- dapper_sample(dmod, sdp = sdp, init_par = -2, niter = 500, chains = 2) # to go back to sequential computing we use plan(sequential)#simulate confidential data # The privacy mechanism adds Gaussian noise to the sample mean. set.seed(1) n <- 100 eps <- 3 y <- rnorm(n, mean = -2, sd = 1) sdp <- mean(y) + rnorm(1, 0, 1/eps) posterior_f <- function(dmat, theta) { x <- c(dmat) xbar <- mean(x) n <- length(x) pr_m <- 0 pr_s2 <- 4 ps_s2 <- 1/(1/pr_s2 + n) ps_m <- ps_s2 * ((1/pr_s2)*pr_m + n * xbar) rnorm(1, mean = ps_m, sd = sqrt(ps_s2)) } latent_f <- function(theta) { matrix(rnorm(100, mean = theta, sd = 1), ncol = 1) } statistic_f <- function(xi, sdp, i) { xi } mechanism_f <- function(sdp, sx) { sum(dnorm(sdp - sx/n, 0, 1/eps, TRUE)) } dmod <- new_privacy(posterior_f = posterior_f, latent_f = latent_f, mechanism_f = mechanism_f, statistic_f = statistic_f, npar = 1) out <- dapper_sample(dmod, sdp = sdp, init_par = -2, niter = 500) summary(out) plot(out) # for parallel computing we 'plan' a session # the code below uses 2 CPU cores for parallel computing library(furrr) plan(multisession, workers = 2) out <- dapper_sample(dmod, sdp = sdp, init_par = -2, niter = 500, chains = 2) # to go back to sequential computing we use plan(sequential)
The probability mass function and random number generator for the discrete Laplacian distribution.
ddlaplace(x, scale = 1, log = FALSE) rdlaplace(n, scale = 1)ddlaplace(x, scale = 1, log = FALSE) rdlaplace(n, scale = 1)
x |
a vector of quantiles. |
scale |
the scale parameter. A positive number for |
log |
logical; if |
n |
number of random deviates. |
Probability mass function
ddlaplace() returns a numeric vector representing the probability mass function of the discrete Laplace distribution.
rdlaplace() returns a numeric vector of random samples from the discrete Laplace distribution.
Canonne, C. L., Kamath, G., & Steinke, T. (2020). The Discrete Gaussian for Differential Privacy. arXiv. doi:10.48550/ARXIV.2004.00010
# mass function ddlaplace(0) # mass function is vectorized ddlaplace(0:10, scale = 5) # generate random samples rdlaplace(10)# mass function ddlaplace(0) # mass function is vectorized ddlaplace(0:10, scale = 5) # generate random samples rdlaplace(10)
The probability mass function and random number generator for the
discrete Gaussian distribution with mean mu and scale parameter sigma.
ddnorm(x, mu = 0, sigma = 1, log = FALSE) rdnorm(n, mu = 0, sigma = 1)ddnorm(x, mu = 0, sigma = 1, log = FALSE) rdnorm(n, mu = 0, sigma = 1)
x |
vector of quantiles. |
mu |
location parameter. Must be an integer for both |
sigma |
scale parameter. |
log |
logical; if |
n |
number of random deviates. |
Probability mass function
ddnorm() returns a numeric vector representing the probability mass function of the discrete Gaussian distribution.
rdnorm() returns a numeric vector of random samples from the discrete Gaussian distribution.
Canonne, C. L., Kamath, G., & Steinke, T. (2020). The Discrete Gaussian for Differential Privacy. arXiv. doi:10.48550/ARXIV.2004.00010
# mass function ddnorm(0) # mass function is also vectorized ddnorm(0:10, mu = 0, sigma = 5) # generate random samples rdnorm(10)# mass function ddnorm(0) # mass function is also vectorized ddnorm(0:10, mu = 0, sigma = 5) # generate random samples rdnorm(10)
privacy Object Constructor.Creates a privacy object to be used as input into dapper_sample().
new_privacy( posterior_f = NULL, latent_f = NULL, mechanism_f = NULL, statistic_f = NULL, npar = NULL, varnames = NULL )new_privacy( posterior_f = NULL, latent_f = NULL, mechanism_f = NULL, statistic_f = NULL, npar = NULL, varnames = NULL )
posterior_f |
a function that draws posterior samples given the confidential data. |
latent_f |
A function with signature |
mechanism_f |
a function that represents the log likelihood of the privacy mechanism. |
statistic_f |
a function that calculates the statistic to be released. |
npar |
dimension of the parameter being estimated. |
varnames |
an optional character vector of parameter names. Used to label summary outputs. |
posterior_f() is a function which makes draws from the posterior sampler. It has
the syntax posterior_f(dmat, theta). Here dmat is a numeric matrix representing the confidential database
and theta is a numeric vector which serves as the initialization point for a one sample draw.
The easiest, bug-free way to construct posterior_f() is to use a conjugate prior. However,
this function can also be constructed by wrapping a MCMC sampler generated from other R packages
(e.g. rstan, fmcmc, adaptMCMC).
latent_f(theta) must take exactly one argument named theta,
a numeric vector of length npar. It must return a matrix with
one confidential record per row and one data variable per column.
The records (rows) must be independent and identically distributed
conditional on theta. Variables within a record may be dependent.
The returned matrix must have the same dimensions on every call.
For univariate data, return a one-column matrix.
mechanism_f() is a function that represents the log of the privacy mechanism density.
This function has the form mechanism_f(sdp, sx) where sdp and sx are both either
a numeric vector or matrix. The arguments must appear in the exact stated order with the same variables names as mentioned.
Finally, the return value of mechanism_f() must be a numeric vector of length one.
statistic_f(xi, sdp, i) computes one record's contribution to the
statistic used by the privacy mechanism. xi is row i of the latent
confidential dataset, supplied as a vector. sdp is the observed
privatized release, and i is the row index. Argument names and order
must match this signature.
The sampler sums these contributions over all records and passes the
result as sx to mechanism_f(sdp, sx). Return a numeric vector when
sdp is a numeric vector, or a matrix when sdp is a matrix.
Contributions must have consistent lengths or dimensions across records.
npar is an integer equal to the dimension of theta.
A S3 object of class privacy.
Plot dpout object.
## S3 method for class 'dpout' plot(x, ...)## S3 method for class 'dpout' plot(x, ...)
x |
dp_out object. |
... |
optional arguments to |
trace plots.
Summarise dpout object.
## S3 method for class 'dpout' summary(object, ...)## S3 method for class 'dpout' summary(object, ...)
object |
dp_out object |
... |
optional arguments to |
A draws_summary tibble containing
summary statistics (such as mean, sd, ess_bulk, and rhat).
See posterior::summarise_draws() for
details on how these statistics are calculated.