Privacy Accountant
A PrivacyAccountant allows for converting a DpEvent or sequence of
DpEvents into privacy parameters. One can call accountant.compose on each
DpEvent we wish to compose, and then use methods like get_epsilon and
get_delta to get the privacy parameters for the mechanism captured by all
DpEvents composed so far.
dp_accounting currently supports two types of PrivacyAccountants.
PLDAccountant uses privacy loss distribution (PLD)
accounting, which is generally
tight up to some numerical precision, but can be slow (see the
supplementary material
for technical details on PLD accounting). RdpAccountant uses
Renyi DP (RDP) accounting, which is faster but not tight in general. Note that not all
DpEvents are supported by both accountants, and there may be DpEvents
supported by one accountant but not the other.
When initializing a PrivacyAccountant, one also specifies the
NeighboringRelation which defines how neighboring databases are related.
The default NeighboringRelation for both accountants is ADD_OR_REMOVE_ONE,
which corresponds to the standard add-or-remove-one definition of DP.
Both accountants have a parameter which allows one to trade off accuracy for
speed. For RdpAccountant, this is orders, the set of RDP orders which are
tracked and used to compute epsilon. For PLDAccountant, this is
value_discretization_interval, the precision of the discretization of
continuous random variables used in PLD accounting. The default values for these
parameters are fine for most use cases, but one can consider using a denser grid
of orders or smaller value_discretization_interval if higher accuracy is
needed, or a sparser grid or larger interval if speed is more important.
Classes
- class dp_accounting.privacy_accountant.PrivacyAccountant(neighboring_relation)[source]
Bases:
objectAbstract base class for privacy accountants.
- property neighboring_relation: NeighboringRelation
The neighboring relation used by the accountant.
The neighboring relation is expected to remain constant after initialization. Subclasses should not override this property or change the value of the private attribute.
- supports(event)[source]
Checks whether the
DpEventcan be processed by this accountant.In general this will require recursively checking the structure of the
DpEvent. In particularComposedDpEventandSelfComposedDpEventshould be recursively examined.- Parameters:
event (
DpEvent) – TheDpEventto check.- Return type:
bool- Returns:
True iff this accountant supports processing
event.
- class CompositionErrorDetails(invalid_event, error_message)[source]
Bases:
objectDescribes offending subevent and error in case composition fails.
-
error_message:
Optional[str]
-
error_message:
- compose(event, count=1)[source]
Updates internal state to account for application of a
DpEvent.Calls to
get_epsilonorget_deltaafter callingcomposewill return values that account for thisDpEvent.- Parameters:
event (
DpEvent) – ADpEventto process.count (
int) – The number of times to compose the event.
- Return type:
Any- Returns:
Reference to this privacy accountant. This allows one to write, e.g.,
eps = Accountant().compose(event1).compose(event2).get_epsilon(delta).- Raises:
UnsupportedEventError –
eventis not supported by this
- abstractmethod get_epsilon(target_delta)[source]
Gets the current epsilon.
- Parameters:
target_delta (
float) – The target delta.- Return type:
float- Returns:
The current epsilon, accounting for all composed
DpEvents.
- get_delta(target_epsilon)[source]
Gets the current delta.
An implementer of
PrivacyAccountantmay choose not to override this, in which caseNotImplementedErrorwill be raised.- Parameters:
target_epsilon (
float) – The target epsilon.- Return type:
float- Returns:
The current delta, accounting for all composed
DpEvents.
- class dp_accounting.privacy_accountant.NeighboringRelation(value)[source]
- ADD_OR_REMOVE_ONE = 1
- REPLACE_ONE = 2
- REPLACE_SPECIAL = 3
- class dp_accounting.rdp.RdpAccountant(orders=None, neighboring_relation=NeighboringRelation.ADD_OR_REMOVE_ONE)[source]
Bases:
PrivacyAccountantPrivacy accountant that uses Renyi differential privacy.
Initializes the RDP accountant.
- Parameters:
orders (
Optional[Sequence[float]]) – The set of RDP orders.neighboring_relation (
NeighboringRelation) – The neighboring relation.
- get_epsilon_and_optimal_order(target_delta)[source]
Returns the current epsilon and the optimal RDP order.
- Parameters:
target_delta (
float) – The target delta.- Return type:
Tuple[float,float]- Returns:
A tuple containing the current epsilon, accounting for all composed
DpEvents, and the optimal order.
- get_epsilon(target_delta)[source]
Returns the current epsilon.
- Parameters:
target_delta (
float) – The target delta.- Return type:
float- Returns:
The current epsilon, accounting for all composed
DpEvents.
- get_delta_and_optimal_order(target_epsilon)[source]
Returns the current delta and the optimal RDP order.
- Parameters:
target_epsilon (
float) – The target epsilon.- Return type:
Tuple[float,float]- Returns:
A tuple containing the current delta, accounting for all composed
DpEvents, and the optimal order.
- get_delta(target_epsilon)[source]
Returns the current delta.
- Parameters:
target_epsilon (
float) – The target epsilon.- Return type:
float- Returns:
The current delta, accounting for all composed
DpEvents.
- property rdp: ndarray
Returns the current RDP values at each order.
- property orders: ndarray
Returns the set of RDP orders.
- class dp_accounting.pld.PLDAccountant(neighboring_relation=NeighboringRelation.ADD_OR_REMOVE_ONE, value_discretization_interval=0.0001)[source]
Bases:
PrivacyAccountantPrivacy accountant that uses Privacy Loss Distributions.
- get_epsilon(target_delta)[source]
Gets the current epsilon.
- Parameters:
target_delta (
float) – The target delta.- Return type:
float- Returns:
The current epsilon, accounting for all composed
DpEvents.
- get_delta(target_epsilon)[source]
Gets the current delta.
An implementer of
PrivacyAccountantmay choose not to override this, in which caseNotImplementedErrorwill be raised.- Parameters:
target_epsilon (
float) – The target epsilon.- Return type:
float- Returns:
The current delta, accounting for all composed
DpEvents.
- get_true_positive_rates(false_positive_rates, deltas=None)[source]
Computes an upper bound on the true positive rate (TPR).
In particular, each (epsilon, delta) pair implied by the PLD also implies an upper bound on the TPR for a given false positive rate (FPR). This function computes this upper bound for a range of deltas (either user-specified, or a default range) and then returns the minimum TPR across all deltas. See Section 3.1 of the supplementary material for details.
Note that this implementation reports a TPR-FPR curve which is symmetric with respect to the line y=1-x, which is not true for the true TPR-FPR curve for asymmetric mechanisms (e.g., subsampled Gaussian under add-remove). In this case the curve is still a valid upper bound on the true TPR-FPR curve, but perhaps overly pessimistic.
- Parameters:
false_positive_rates (
Union[float,ndarray]) – the FPR or list of FPRs at which to compute the TPR.deltas (
Optional[ndarray]) – the list of deltas to use for the computation. If None, the default deltasnp.logspace(np.log10(1e-13), np.log10(1), num=3000)and 0 will be used. A denser and wider range of deltas will yield a more accurate estimate, at the cost of increased run-time.
- Return type:
Union[float,ndarray]- Returns:
A float or array of floats representing the upper bound on the TPR at the given FPR or list of FPRs.
- get_gdp_parameter_estimate(false_positive_rates=None, deltas=None)[source]
Computes an estimate of the mu-GDP parameter implied by the PLD.
Specifically, we upper bound the true positive rate (TPR) at a given range of false positive rates (FPRs), and then find the minimum mu-GDP value that upper bounds all of the TPR upper bounds. This is pessimistic in that we are using upper bounds on the TPRs, but optimistic in that we are using a finite grid of TPRs, which is not guaranteed to contain the point at which the true mu-GDP parameter is tight. See Section 3.2 of the supplementary material for details.
If the privacy loss is infinite with probability greater than min(false_positive_rates), then this function will return infinity. This is so that (i) when a PLD has large infinity mass, we correctly report infinite mu-GDP, but simultaneously (ii) the small infinity masses introduced by truncating a PLD to finite support do not result in infinite mu-GDP. We recommend reporting the minimum FPR used when reporting mu-GDP values computed using this function.
- Parameters:
false_positive_rates (
Optional[ndarray]) – The list of FPRs to use for the computation. If None, the default FPRsnp.logspace(np.log10(1e-12), np.log10(0.5), num=500)will be used. A denser and wider range of FPRs will reduce optimism of the estimate, at the cost of increased run-time.deltas (
Optional[ndarray]) – The list of deltas to use for the computation. If None, the default deltasnp.logspace(np.log10(1e-13), np.log10(1), num=3000)and 0 will be used. A denser and wider range of deltas will reduce pessimism of the estimate, at the cost of increased run-time.
- Return type:
float- Returns:
The estimated mu-GDP parameter. Note that this is not guaranteed to be an upper or lower bound on the true mu-GDP parameter (but can be made arbitrarily close to the true mu-GDP parameter by increasing the precision of the PLD, deltas, and FPRs).