Package: d3p
d3p - Differentially Private Probabilistic Programmingd3p is an implementation of the differentially private variational inference (DP-VI) algorithm [2] forNumPyro, usingJAXfor auto-differentiation and fast execution on CPU and GPU.It is designed to provide differential privacy guarantees for tabular data, where each individual contributed a single sensitive record (/ data point / example).Current StatusThe software is under ongoing development and specific interfaces may change suddenly.Since both NumPyro and JAX are evolving rapdily, some convenience features implemented in d3p are made obsolete by being introduced in these upstream packages. In that case, they will be gradually replaced but there might be some lag time.UsageThe main component ofd3pis the implementation of DP-VI in thed3p.svi.DPSVIclass.
It is intended to work as a drop-in replacement of NumPyro'snumpyro.svi.SVIand works
with models specified using NumPyro distributions and modelling features.For a general introduction on writing models for NumPyro, please refer to theNumPyro documentation.Then instead ofnumpyro.svi.SVI, you can simply used3p.svi.DPSVI.Main Differences inDPSVISince it provides differential privacy, there are additional parameters to theDPSVIclass compared tonumpyro.svi.SVI:clipping_thresholdDifferential privacy requires gradients of individual data points (examples) in your data set
to be clipped to a maximum norm, to limit the contribution any single example can have. The parameterclipping_thresholdsets the threshold over which these gradient norms are clipped.dp_scaleThis is the scale of the noise σ for the Gaussian mechanism that is used to perturb gradients in DP-VI update steps
to turn it into a differentially-private inference algorithm. The largerdp_scaleis, the greater the privacy
guarantees (expressed by parameters (ε,δ)) are.Note: The final scale of the noise applied by the Gaussian mechanism isdp_scale·clipping_threshold, to properly
account for the maximum size of the gradient norm.How to select:d3poffers thed3p.dputil.approximate_sigmafunction to find thedp_scaleparameter for
a choice of ε and δ (and the minibatch size) using the Fourier accountant. Unfortunately, research on appropriate values for ε and δ is still ongoing, but common practice is to select δ to be much smaller than 1/N, where N is the size of your data set, and ε not larger than one.rng_suiteJAX's default pseudo-random number generator is not known to be cryptographically secure, which is required for meaningful
privacy in practice.d3ptherefore relies on ourjax-chacha-prngcryptographically secure PRNG package throughd3p.randomas the default PRNG forDPSVIto sample noise related to privacy.However, you if you want to use JAX's default PRNG, which is a bit faster, during debugging, you can use
therng_suiteparameter to pass thed3p.random.debugmodule, which is a slim wrapper around JAX's PRNG.Note: The choice forrng_suitedoes not affect definition of the model (or variational guide)
or any purely modelling and sampling related functionality of NumPyro/JAX. These still all use JAX's default PRNG.Minibatch samplingDP-VI relies on uniform sampling of random minibatches for each update step to guarantee privacy. This is different
from simply shuffling the data set and taking consecutive batches from it, as is often done in machine learning.d3pimplements a high-performant GPU-optimised minibatch sampling routine ind3p.minibatch.subsample_batchify_data.
It accepts the data set and a minibatch size (or, equivalently, a subsampling ratio) and returns functionsbatchify_initandbatchify_samplewhich initialise a batchifier state from arng_keyand sample a random minibatch given the batchifier state respectively.Requirements for Model Implementationd3p.svi.DPSVIonly requires themodelfunction to be properly setup for minibatches of independent data. This
means users must use theplateprimitive of NumPyro in their model implementation to properly annotate individual
data points as stochastically independent. If this is not properly done, the relative contribution of the prior
distributions for parameters will be overemphasized during the inference.Short ExampleAs a very brief example, we consider logistic regression and define the model as:importjax.numpyasjnpimportjaxfromnumpyro.inferimportTrace_ELBOfromnumpyro.optimimportAdamfromnumpyro.primitivesimportsample,platefromnumpyro.distributionsimportNormal,Bernoullifromnumpyro.infer.autoguideimportAutoDiagonalNormalfromd3p.minibatchimportsubsample_batchify_datafromd3p.sviimportDPSVIfromd3p.dputilimportapproximate_sigmaimportd3p.randomdefsigmoid(x):return1./(1+jnp.exp(-x))# specifies the model p(ys, w | xs) using NumPyro featuresdefmodel(xs,ys,N):# obtain data dimensionsbatch_size,d=xs.shape# the prior for ww=sample('w',Normal(0,4),sample_shape=(d,))# distribution of label y for each record xwithplate('batch',N,batch_size):theta=sigmoid(xs.dot(w))sample('ys',Bernoulli(theta),obs=ys)guide=AutoDiagonalNormal(model)# variational guide approximates posterior of theta and w with independent Gaussiansdefinfer(data,labels,batch_size,num_iter,epsilon,delta,seed):rng_key=d3p.random.PRNGKey(seed)# set up minibatch samplingbatchifier_init,get_batch=subsample_batchify_data((data,labels),batch_size)_,batchifier_state=batchifier_init(rng_key)# set up DP-VI algorithmq=batch_size/len(data)dp_scale,_,_=approximate_sigma(epsilon,delta,q,num_iter)loss=Trace_ELBO()optimiser=Adam(1e-3)clipping_threshold=10.dpsvi=DPSVI(model,guide,optimiser,loss,clipping_threshold,dp_scale,N=len(data))svi_state=dpsvi.init(rng_key,*get_batch(0,batchifier_state))# run inferencedefstep_function(i,svi_state):data_batch,label_batch=get_batch(i,batchifier_state)svi_state,loss=dpsvi.update(svi_state,data_batch,label_batch)returnsvi_statesvi_state=jax.lax.fori_loop(0,num_iter,step_function,svi_state)returndpsvi.get_params(svi_state)See theexamples/for more examples.Installingd3p is pure Python software. You can install it via the pip command line toolpip install d3pThis will install d3p with all required dependencies (NumPyro, JAX, ..) for CPU usage.You can also install the latest development version
via pip with the following command:pip install git+https://github.com/DPBayes/d3p.git@master#egg=d3pAlternatively, you can clone this git repository and install with pip locally:git clone https://github.com/DPBayes/d3p
cd d3p
pip install .If you want to run the included examples, use theexamplesinstallation target:pip install .[examples]Note about dependency versionsNumPyro and JAX are still under ongoing development and its developers currently give no
guarantee that the API remains stable between releases. In order to allow for users
of d3p to benefit from latest features of NumPyro, we did not put a strict upper bound
on the NumPyro dependency version. This may lead to problems if newer NumPyro versions
introduce breaking API changes.If you encounter such issues at some point,
you can use thecompatible-dependenciesinstallation target of d3p to force usage of the latest
known set of dependency versions known to be compatible with d3p:pip install git+https://github.com/DPBayes/d3p.git@master#egg=d3p[compatible-dependencies]GPU installationd3p supports hardware acceleration on CUDA devices. You will need to make sure that
you have the CUDA libraries set up on your system as well as a working compiler for C++.You can then install d3p usingpip install d3p[cuda] -f https://storage.googleapis.com/jax-releases/jax_cuda_releases.htmlUnfortunately, thejax-chacha-prngpackage which provides the secure randomness
generator d3p relies on does not provide prebuilt packages for CUDA, so will need to
reinstall it from sources. To do so, issue the following command after the previous one:pip install --force-reinstall --no-binary jax-chacha-prng "jax-chacha-prng<2"TPU installationTPUs are currently not supported.Versioning PolicyThemasterbranch contains the latest development version of d3p which may introduce breaking changes.Version numbers adhere toSemantic Versioning. Changes between releases are tracked inChangeLog.txt.Licensed3p is licensed under the Apache 2.0 License. The full license text is available
inLICENSES/Apache-2.0.txt. Copyright holder of each contribution are the respective
contributing developer or his or her assignee (i.e., universities or companies
owning the copyright of software contributed by their employees).AcknowledgementsWe thank the NVIDIA AI Technology Center Finland for their contribution of GPU performance benchmarking and optimisation.References and CitingWhen using d3p, please cite the following papers:L. Prediger, N. Loppi, S. Kaski, A. Honkela.
d3p - A Python Package for Differentially-Private Probabilistic Programming
InProceedings on Privacy Enhancing Technologies, 2022(2).
Link:https://doi.org/10.2478/popets-2022-0052J. Jälkö, O. Dikmen, A. Honkela. Differentially Private Variational Inference for Non-conjugate Models
InUncertainty in Artificial Intelligence 2017 Proceedings of the 33rd Conference, UAI 2017.
Link:http://auai.org/uai2017/proceedings/papers/152.pdf