Add Laplace DpEvent

PiperOrigin-RevId: 432475405
This commit is contained in:
A. Unique TensorFlower 2022-03-04 10:14:13 -08:00
parent 2c65cc7910
commit 42df23eb79
2 changed files with 44 additions and 2 deletions

View file

@ -59,7 +59,7 @@ incorrect results, the following should be enforced:
is `False` when processing unknown mechanisms.
"""
from typing import List
from typing import List, Union
import attr
@ -115,6 +115,20 @@ class GaussianDpEvent(DpEvent):
noise_multiplier: float
@attr.s(frozen=True, slots=True, auto_attribs=True)
class LaplaceDpEvent(DpEvent):
"""Represents an application of the Laplace mechanism.
For values v_i and noise z sampled coordinate-wise from the Laplace
distribution L(0, s), this mechanism returns sum_i v_i + z.
The probability density function of the Laplace distribution L(0, s) with
parameter s is given as exp(-|x|/s) * (0.5/s) at x for any real value x.
If the L_1 norm of the values are bounded ||v_i||_1 <= C, the noise_multiplier
is defined as s / C.
"""
noise_multiplier: float
@attr.s(frozen=True, slots=True, auto_attribs=True)
class SelfComposedDpEvent(DpEvent):
"""Represents repeated application of a mechanism.
@ -176,3 +190,25 @@ class SampledWithoutReplacementDpEvent(DpEvent):
source_dataset_size: int
sample_size: int
event: DpEvent
@attr.s(frozen=True, slots=True, auto_attribs=True)
class SingleEpochTreeAggregationDpEvent(DpEvent):
"""Represents aggregation for a single epoch using one or more trees.
Multiple tree-aggregation steps can occur, but it is required that each
record occurs at most once *across all trees*. See appendix D of
"Practical and Private (Deep) Learning without Sampling or Shuffling"
https://arxiv.org/abs/2103.00039.
To represent the common case where the same record can occur in multiple
trees (but still at most once per tree), wrap this with `SelfComposedDpEvent`
or `ComposedDpEvent` and use a scalar for `step_counts`.
Attributes:
noise_multiplier: The ratio of the noise per node to the sensitivity.
step_counts: The number of steps in each tree. May be a scalar for a single
tree.
"""
noise_multiplier: float
step_counts: Union[int, List[int]]

View file

@ -17,6 +17,7 @@ from tensorflow_privacy.privacy.analysis import dp_event
from tensorflow_privacy.privacy.analysis import dp_event_builder
_gaussian_event = dp_event.GaussianDpEvent(1.0)
_laplace_event = dp_event.LaplaceDpEvent(1.0)
_poisson_event = dp_event.PoissonSampledDpEvent(_gaussian_event, 0.1)
_self_composed_event = dp_event.SelfComposedDpEvent(_gaussian_event, 3)
@ -27,11 +28,16 @@ class DpEventBuilderTest(absltest.TestCase):
builder = dp_event_builder.DpEventBuilder()
self.assertEqual(dp_event.NoOpDpEvent(), builder.build())
def test_single(self):
def test_single_gaussian(self):
builder = dp_event_builder.DpEventBuilder()
builder.compose(_gaussian_event)
self.assertEqual(_gaussian_event, builder.build())
def test_single_laplace(self):
builder = dp_event_builder.DpEventBuilder()
builder.compose(_laplace_event)
self.assertEqual(_laplace_event, builder.build())
def test_compose_no_op(self):
builder = dp_event_builder.DpEventBuilder()
builder.compose(dp_event.NoOpDpEvent())