Source code for opacus.accountants.utils

# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Optional

from opacus.accountants import create_accountant


MAX_SIGMA = 1e6


[docs] def get_noise_multiplier( *, target_epsilon: float, target_delta: float, sample_rate: float, epochs: Optional[int] = None, steps: Optional[int] = None, accountant: str = "rdp", epsilon_tolerance: float = 0.01, **kwargs, ) -> float: r""" Computes the noise level sigma to reach a total budget of (target_epsilon, target_delta) at the end of epochs, with a given sample_rate Args: target_epsilon: the privacy budget's epsilon target_delta: the privacy budget's delta sample_rate: the sampling rate (usually batch_size / n_data) epochs: the number of epochs to run steps: number of steps to run accountant: accounting mechanism used to estimate epsilon epsilon_tolerance: precision for the binary search Returns: The noise level sigma to ensure privacy budget of (target_epsilon, target_delta) """ if (steps is None) == (epochs is None): raise ValueError( "get_noise_multiplier takes as input EITHER a number of steps or a number of epochs" ) if steps is None: steps = int(epochs / sample_rate) eps_high = float("inf") accountant = create_accountant(mechanism=accountant) sigma_low, sigma_high = 0, 10 while eps_high > target_epsilon: sigma_high = 2 * sigma_high accountant.history = [(sigma_high, sample_rate, steps)] eps_high = accountant.get_epsilon(delta=target_delta, **kwargs) if sigma_high > MAX_SIGMA: raise ValueError("The privacy budget is too low.") while target_epsilon - eps_high > epsilon_tolerance: sigma = (sigma_low + sigma_high) / 2 accountant.history = [(sigma, sample_rate, steps)] eps = accountant.get_epsilon(delta=target_delta, **kwargs) if eps < target_epsilon: sigma_high = sigma eps_high = eps else: sigma_low = sigma return sigma_high