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: object

Abstract 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 DpEvent can be processed by this accountant.

In general this will require recursively checking the structure of the DpEvent. In particular ComposedDpEvent and SelfComposedDpEvent should be recursively examined.

Parameters:

event (DpEvent) – The DpEvent to check.

Return type:

bool

Returns:

True iff this accountant supports processing event.

class CompositionErrorDetails(invalid_event, error_message)[source]

Bases: object

Describes offending subevent and error in case composition fails.

invalid_event: Optional[DpEvent]
error_message: Optional[str]
compose(event, count=1)[source]

Updates internal state to account for application of a DpEvent.

Calls to get_epsilon or get_delta after calling compose will return values that account for this DpEvent.

Parameters:
  • event (DpEvent) – A DpEvent to 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:
property ledger: DpEvent

Returns the (composed) DpEvent processed so far by this accountant.

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 PrivacyAccountant may choose not to override this, in which case NotImplementedError will 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: PrivacyAccountant

Privacy 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: PrivacyAccountant

Privacy 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 PrivacyAccountant may choose not to override this, in which case NotImplementedError will 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 deltas np.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 FPRs np.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 deltas np.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).

Exceptions

exception dp_accounting.privacy_accountant.UnsupportedEventError[source]

Exception to raise if _compose is called on unsupported event type.