def test_bad_query(self):
    non_quantile_estimator_query = tfp.GaussianSumQuery(
        l2_norm_clip=1.0, stddev=1.0)

    with self.assertRaises(TypeError):
      quantile_estimation.PrivateQuantileEstimationProcess(
          non_quantile_estimator_query)
  def test_adaptation(self, geometric_update):
    initial_estimate = 3.14159
    target_quantile = 0.61803
    learning_rate = 2.71828

    quantile_estimator_query = tfp.NoPrivacyQuantileEstimatorQuery(
        initial_estimate=initial_estimate,
        target_quantile=target_quantile,
        learning_rate=learning_rate,
        geometric_update=geometric_update)

    process = quantile_estimation.PrivateQuantileEstimationProcess(
        quantile_estimator_query)

    state = process.initialize()
    self.assertAllClose(process.report(state), initial_estimate)

    # Run on two records greater than estimate.
    state = process.next(state, [initial_estimate + 1, initial_estimate + 2])

    if geometric_update:
      expected_estimate = (
          initial_estimate * np.exp(learning_rate * target_quantile))
    else:
      expected_estimate = initial_estimate + learning_rate * target_quantile

    self.assertAllClose(process.report(state), expected_estimate)
def _build_quantile_estimation_process(initial_estimate, target_quantile,
                                       learning_rate):
    return quantile_estimation.PrivateQuantileEstimationProcess(
        tfp.NoPrivacyQuantileEstimatorQuery(initial_estimate=initial_estimate,
                                            target_quantile=target_quantile,
                                            learning_rate=learning_rate,
                                            geometric_update=True))
 def to_quantile_estimation_process(
     self) -> quantile_estimation.PrivateQuantileEstimationProcess:
   return quantile_estimation.PrivateQuantileEstimationProcess(
       tfp.NoPrivacyQuantileEstimatorQuery(
           initial_estimate=self._initial_estimate,
           target_quantile=self._target_quantile,
           learning_rate=self._learning_rate,
           geometric_update=True))
示例#5
0
def _make_quantile_estimation_process(initial_estimate: float,
                                      target_quantile: float,
                                      learning_rate: float):
    return quantile_estimation.PrivateQuantileEstimationProcess(
        tensorflow_privacy.NoPrivacyQuantileEstimatorQuery(
            initial_estimate=initial_estimate,
            target_quantile=target_quantile,
            learning_rate=learning_rate,
            geometric_update=True))
  def test_bad_aggregation_factory(self):
    quantile_estimator_query = tfp.NoPrivacyQuantileEstimatorQuery(
        initial_estimate=1.0,
        target_quantile=0.5,
        learning_rate=1.0,
        geometric_update=True)

    with self.assertRaises(TypeError):
      quantile_estimation.PrivateQuantileEstimationProcess(
          quantile_estimator_query=quantile_estimator_query,
          record_aggregation_factory="I'm not a record_aggregation_factory.")
  def test_process_type_signature(self, private):
    if private:
      quantile_estimator_query = tfp.QuantileEstimatorQuery(
          initial_estimate=1.0,
          target_quantile=0.5,
          learning_rate=1.0,
          below_estimate_stddev=0.5,
          expected_num_records=100,
          geometric_update=True)
    else:
      quantile_estimator_query = tfp.NoPrivacyQuantileEstimatorQuery(
          initial_estimate=1.0,
          target_quantile=0.5,
          learning_rate=1.0,
          geometric_update=True)

    process = quantile_estimation.PrivateQuantileEstimationProcess(
        quantile_estimator_query)

    query_state = quantile_estimator_query.initial_global_state()
    sum_process_state = ()

    server_state_type = computation_types.FederatedType(
        type_conversions.type_from_tensors((query_state, sum_process_state)),
        placements.SERVER)

    self.assertEqual(
        computation_types.FunctionType(
            parameter=None, result=server_state_type),
        process.initialize.type_signature)

    estimate_type = computation_types.FederatedType(tf.float32,
                                                    placements.SERVER)

    self.assertEqual(
        computation_types.FunctionType(
            parameter=server_state_type, result=estimate_type),
        process.report.type_signature)

    client_value_type = computation_types.FederatedType(tf.float32,
                                                        placements.CLIENTS)
    self.assertTrue(
        process.next.type_signature.is_equivalent_to(
            computation_types.FunctionType(
                parameter=collections.OrderedDict(
                    state=server_state_type, value=client_value_type),
                result=server_state_type)))
示例#8
0
    def _build_auto_l2_clip_process(self, target_quantile, learning_rate,
                                    clip_count_stddev):
        """Builds a `tff.templates.EstimationProcess` for adaptive L2 clipping.

    Specifically, we use the private quantile estimation algorithm described in
    https://arxiv.org/abs/1905.03871 for choosing the adaptive L2 clip norm.
    The default noise level for the procedure follows the paper and the
    implementation of `tff.aggregators.DifferentiallyPrivateFactory`.

    Note that for consistency with the use of secure aggregation for the client
    values, the binary flags as part of the quantile estimation procedure
    indicating whether client L2 norms are below the current estimate are also
    securely aggregated.

    Args:
      target_quantile: See `auto_l2_target_quantile` at __init__ docstring.
      learning_rate: See `auto_l2_lr` at __init__ docstring.
      clip_count_stddev: See `auto_l2_clip_count_stddev` at __init__ docstring.

    Returns:
      The `EstimationProcess` for adaptive L2 clipping and the required noise
      multiplier for the record aggregation.
    """
        value_noise_mult, clip_count_stddev = (
            differential_privacy.adaptive_clip_noise_params(
                self._noise_multiplier, self._num_clients, clip_count_stddev))

        estimator_query = tfp.QuantileEstimatorQuery(
            initial_estimate=self._initial_l2_clip,
            target_quantile=target_quantile,
            learning_rate=learning_rate,
            below_estimate_stddev=clip_count_stddev,
            expected_num_records=self._num_clients,
            geometric_update=True)
        # Note also that according to https://arxiv.org/abs/1905.03871, the binary
        # flags for quantile estimation are shifted from [0, 1] to [-0.5, 0.5], so
        # we set the SecAgg input bounds accordingly.
        estimator_process = quantile_estimation.PrivateQuantileEstimationProcess(
            quantile_estimator_query=estimator_query,
            record_aggregation_factory=secure.SecureSumFactory(
                upper_bound_threshold=0.5, lower_bound_threshold=-0.5))

        return estimator_process, value_noise_mult