Skip to content

Commit 34ad9db

Browse files
galenmandrewtensorflower-gardener
authored andcommitted
Automated rollback of commit 7e89dad
PiperOrigin-RevId: 441245348
1 parent 7e89dad commit 34ad9db

File tree

2 files changed

+220
-0
lines changed

2 files changed

+220
-0
lines changed

tensorflow_privacy/privacy/analysis/BUILD

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ py_test(
5151
deps = [":compute_noise_from_budget_lib"],
5252
)
5353

54+
py_library(
55+
name = "dp_event",
56+
srcs = ["dp_event.py"],
57+
srcs_version = "PY3",
58+
)
59+
5460
py_library(
5561
name = "gdp_accountant",
5662
srcs = ["gdp_accountant.py"],
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# Copyright 2021, The TensorFlow Authors.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Standard DpEvent classes.
15+
16+
A `DpEvent` represents the (hyper)parameters of a differentially
17+
private query, amplification mechanism, or composition, that are necessary
18+
and sufficient for privacy accounting. Various independent implementations of DP
19+
algorithms that are functionally equivalent from an accounting perspective may
20+
correspond to the same `DpEvent`. Similarly, various independent implementations
21+
of accounting algorithms may consume the same `DpEvent`.
22+
23+
All `DpEvents` processed together are assumed to take place on a single dataset
24+
of records. `DpEvents` fall into roughly three categories:
25+
- `DpEvents` that release an output, and incur a privacy cost,
26+
e.g., `GaussianDpEvent`.
27+
- `DpEvents` that select a subset (or subsets) of the dataset, and run nested
28+
`DpEvents` on those subsets, e.g., `PoissonSampledDpEvent`.
29+
- `DpEvents` that represent (possibly sequentially) applying (multiple)
30+
mechanisms to the dataset (or currently active subset). Currently, this is
31+
only `ComposedDpEvent` and `SelfComposedDpEvent`.
32+
33+
Each `DpEvent` should completely document the mathematical behavior and
34+
assumptions of the mechanism it represents so that the writer of an accountant
35+
class can implement the accounting correctly without knowing any other
36+
implementation details of the algorithm that produced it.
37+
38+
New mechanism types should be given a corresponding `DpEvent` class, although
39+
not all accountants will be required to support them. In general,
40+
`PrivacyAccountant` implementations are not required to be aware of all
41+
`DpEvent` classes, but they should support the following basic events and handle
42+
them appropriately: `NoOpDpEvent`, `NonPrivateDpEvent`, `ComposedDpEvent`, and
43+
`SelfComposedDpEvent`. They should return `supports(event)` is False for
44+
`UnsupportedDpEvent` or any other event type they have not been designed to
45+
handle.
46+
47+
To ensure that a `PrivacyAccountant` does not accidentally start to return
48+
incorrect results, the following should be enforced:
49+
* `DpEvent` classes and their parameters should never be removed, barring some
50+
extended, onerous deprecation process.
51+
* New parameters cannot be added to existing mechanisms unless they are
52+
optional. That is, old composed `DpEvent` objects that do not include them
53+
must remain valid.
54+
* The meaning of existing mechanisms or parameters must not change. That is,
55+
existing mechanisms should not have their implementations change in ways that
56+
alter their privacy properties; new `DpEvent` classes should be added
57+
instead.
58+
* `PrivacyAccountant` implementations are expected to return `supports(event)`
59+
is `False` when processing unknown mechanisms.
60+
"""
61+
62+
from typing import List, Union
63+
64+
import attr
65+
66+
67+
class DpEvent(object):
68+
"""Represents application of a private mechanism.
69+
70+
A `DpEvent` describes a differentially private mechanism sufficiently for
71+
computing the associated privacy losses, both in isolation and in combination
72+
with other `DpEvent`s.
73+
"""
74+
75+
76+
@attr.s(frozen=True)
77+
class NoOpDpEvent(DpEvent):
78+
"""Represents appplication of an operation with no privacy impact.
79+
80+
A `NoOpDpEvent` is generally never required, but it can be useful as a
81+
placeholder where a `DpEvent` is expected, such as in tests or some live
82+
accounting pipelines.
83+
"""
84+
85+
86+
@attr.s(frozen=True)
87+
class NonPrivateDpEvent(DpEvent):
88+
"""Represents application of a non-private operation.
89+
90+
This `DpEvent` should be used when an operation is performed that does not
91+
satisfy (epsilon, delta)-DP. All `PrivacyAccountant`s should return infinite
92+
epsilon/delta when encountering a `NonPrivateDpEvent`.
93+
"""
94+
95+
96+
@attr.s(frozen=True)
97+
class UnsupportedDpEvent(DpEvent):
98+
"""Represents application of an as-yet unsupported operation.
99+
100+
This `DpEvent` should be used when an operation is performed that does not yet
101+
have any associated DP description, or if the description is temporarily
102+
inaccessible, for example, during development. All `PrivacyAccountant`s should
103+
return `supports(event) == False` for `UnsupportedDpEvent`.
104+
"""
105+
106+
107+
@attr.s(frozen=True, slots=True, auto_attribs=True)
108+
class GaussianDpEvent(DpEvent):
109+
"""Represents an application of the Gaussian mechanism.
110+
111+
For values v_i and noise z ~ N(0, s^2I), this mechanism returns sum_i v_i + z.
112+
If the norms of the values are bounded ||v_i|| <= C, the noise_multiplier is
113+
defined as s / C.
114+
"""
115+
noise_multiplier: float
116+
117+
118+
@attr.s(frozen=True, slots=True, auto_attribs=True)
119+
class LaplaceDpEvent(DpEvent):
120+
"""Represents an application of the Laplace mechanism.
121+
122+
For values v_i and noise z sampled coordinate-wise from the Laplace
123+
distribution L(0, s), this mechanism returns sum_i v_i + z.
124+
The probability density function of the Laplace distribution L(0, s) with
125+
parameter s is given as exp(-|x|/s) * (0.5/s) at x for any real value x.
126+
If the L_1 norm of the values are bounded ||v_i||_1 <= C, the noise_multiplier
127+
is defined as s / C.
128+
"""
129+
noise_multiplier: float
130+
131+
132+
@attr.s(frozen=True, slots=True, auto_attribs=True)
133+
class SelfComposedDpEvent(DpEvent):
134+
"""Represents repeated application of a mechanism.
135+
136+
The repeated applications may be adaptive, where the query producing each
137+
event depends on the results of prior queries.
138+
139+
This is equivalent to `ComposedDpEvent` that contains a list of length `count`
140+
of identical copies of `event`.
141+
"""
142+
event: DpEvent
143+
count: int
144+
145+
146+
@attr.s(frozen=True, slots=True, auto_attribs=True)
147+
class ComposedDpEvent(DpEvent):
148+
"""Represents application of a series of composed mechanisms.
149+
150+
The composition may be adaptive, where the query producing each event depends
151+
on the results of prior queries.
152+
"""
153+
events: List[DpEvent]
154+
155+
156+
@attr.s(frozen=True, slots=True, auto_attribs=True)
157+
class PoissonSampledDpEvent(DpEvent):
158+
"""Represents an application of Poisson subsampling.
159+
160+
Each record in the dataset is included in the sample independently with
161+
probability `sampling_probability`. Then the `DpEvent` `event` is applied
162+
to the sample of records.
163+
"""
164+
sampling_probability: float
165+
event: DpEvent
166+
167+
168+
@attr.s(frozen=True, slots=True, auto_attribs=True)
169+
class SampledWithReplacementDpEvent(DpEvent):
170+
"""Represents sampling a fixed sized batch of records with replacement.
171+
172+
A sample of `sample_size` (possibly repeated) records is drawn uniformly at
173+
random from the set of possible samples of a source dataset of size
174+
`source_dataset_size`. Then the `DpEvent` `event` is applied to the sample of
175+
records.
176+
"""
177+
source_dataset_size: int
178+
sample_size: int
179+
event: DpEvent
180+
181+
182+
@attr.s(frozen=True, slots=True, auto_attribs=True)
183+
class SampledWithoutReplacementDpEvent(DpEvent):
184+
"""Represents sampling a fixed sized batch of records without replacement.
185+
186+
A sample of `sample_size` unique records is drawn uniformly at random from the
187+
set of possible samples of a source dataset of size `source_dataset_size`.
188+
Then the `DpEvent` `event` is applied to the sample of records.
189+
"""
190+
source_dataset_size: int
191+
sample_size: int
192+
event: DpEvent
193+
194+
195+
@attr.s(frozen=True, slots=True, auto_attribs=True)
196+
class SingleEpochTreeAggregationDpEvent(DpEvent):
197+
"""Represents aggregation for a single epoch using one or more trees.
198+
199+
Multiple tree-aggregation steps can occur, but it is required that each
200+
record occurs at most once *across all trees*. See appendix D of
201+
"Practical and Private (Deep) Learning without Sampling or Shuffling"
202+
https://arxiv.org/abs/2103.00039.
203+
204+
To represent the common case where the same record can occur in multiple
205+
trees (but still at most once per tree), wrap this with `SelfComposedDpEvent`
206+
or `ComposedDpEvent` and use a scalar for `step_counts`.
207+
208+
Attributes:
209+
noise_multiplier: The ratio of the noise per node to the sensitivity.
210+
step_counts: The number of steps in each tree. May be a scalar for a single
211+
tree.
212+
"""
213+
noise_multiplier: float
214+
step_counts: Union[int, List[int]]

0 commit comments

Comments
 (0)