def test_raises_with_empty_value(self): value_type = type_conversions.type_from_tensors(()) with self.assertRaises(ValueError): adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type=value_type, initial_quantile_estimate=100.0, target_quantile=0.99, multiplier=2.0, increment=1.0, learning_rate=1.0, norm_order=np.inf)
def test_adaptation_achieved_with_multiplier(self, shapes): value_type = type_conversions.type_from_tensors(_make_value(0, shapes)) mean_process = adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type=value_type, initial_quantile_estimate=100.0, target_quantile=0.5, multiplier=2.0, increment=10.0, learning_rate=np.log(4.0), norm_order=np.inf) global_state = mean_process.initialize() values = [_make_value(x, shapes) for x in [30, 60]] # With target 0.5, learning rate λ=ln(4), estimate should be cut in # half in first round: exp(ln(4)(-0.5)) = 1/sqrt(4) = 0.5. output = mean_process.next(global_state, values, [1, 1]) self._check_result(output, 45, shapes) global_state = output.state metrics = output.measurements self.assertAllClose(metrics.zeroing_threshold, 110.0) self.assertEqual(metrics.num_zeroed, 0) # In second round, target is achieved, no adaptation occurs, and no updates # are zeroed becaues of multiplier. output = mean_process.next(global_state, values, [1, 1]) self._check_result(output, 45, shapes) global_state = output.state metrics = output.measurements self.assertAllClose(metrics.zeroing_threshold, 110.0) self.assertEqual(metrics.num_zeroed, 0)
def test_adaptation_achieved(self, shapes): value_type = type_conversions.type_from_tensors(_make_value(0, shapes)) mean_process = adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type, 100.0, 0.5, 1.0, np.log(4.0), np.inf) global_state = mean_process.initialize() self.assertEqual(global_state.current_estimate, 100.0) values = [_make_value(x, shapes) for x in [30, 60]] # With target 0.5, learning rate λ=ln(4), estimate should be cut in # half in first round: exp(ln(4)(-0.5)) = 1/sqrt(4) = 0.5. output = mean_process.next(global_state, values, [1, 1]) self._check_result(output, 45, shapes) global_state = output['state'] self.assertAllClose(global_state.current_estimate, 50.0) metrics = output['measurements'] self.assertAllClose(metrics.current_threshold, 50.0) self.assertEqual(metrics.num_zeroed, 0) # In second round, target is achieved, no adaptation occurs, but one update # is zeroed. output = mean_process.next(global_state, values, [1, 1]) self._check_result(output, 30, shapes) global_state = output['state'] self.assertAllClose(global_state.current_estimate, 50.0) metrics = output['measurements'] self.assertAllClose(metrics.current_threshold, 50.0) self.assertEqual(metrics.num_zeroed, 1)
def test_adaptation_up(self, shapes): value_type = type_conversions.type_from_tensors(_make_value(0, shapes)) mean_process = adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type=value_type, initial_quantile_estimate=1.0, target_quantile=1.0, multiplier=1.0, increment=1.0, learning_rate=np.log(2.0), norm_order=np.inf) global_state = mean_process.initialize() values = [_make_value(x, shapes) for x in [90, 91, 92]] output = mean_process.next(global_state, values, [1, 1, 1]) self._check_result(output, 0, shapes) global_state = output.state metrics = output.measurements self.assertAllClose(metrics.zeroing_threshold, 3.0) self.assertEqual(metrics.num_zeroed, 3) output = mean_process.next(global_state, values, [1, 1, 1]) self._check_result(output, 0, shapes) global_state = output.state metrics = output.measurements self.assertAllClose(metrics.zeroing_threshold, 5.0) self.assertEqual(metrics.num_zeroed, 3)
def test_simple_average(self, shapes): value_type = type_conversions.type_from_tensors(_make_value(0, shapes)) mean_process = adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type=value_type, initial_quantile_estimate=100.0, target_quantile=1.0, multiplier=1.0, increment=0.0, learning_rate=0.0, norm_order=np.inf) # Basic average. global_state = mean_process.initialize() values = [_make_value(x, shapes) for x in [0, 1, 2]] output = mean_process.next(global_state, values, [1, 1, 1]) self._check_result(output, 1, shapes) metrics = output.measurements self.assertEqual(metrics.zeroing_threshold, 100.0) self.assertEqual(metrics.num_zeroed, 0) # Weighted average. global_state = output.state values = [_make_value(x, shapes) for x in [3, 5, 1, 0]] output = mean_process.next(global_state, values, [1, 2, 3, 2]) self._check_result(output, 2, shapes) metrics = output.measurements self.assertEqual(metrics.zeroing_threshold, 100.0) self.assertEqual(metrics.num_zeroed, 0) # One value zeroed. global_state = output.state values = [_make_value(x, shapes) for x in [50, 150]] output = mean_process.next(global_state, values, [1, 1]) self._check_result(output, 50, shapes) metrics = output.measurements self.assertEqual(metrics.zeroing_threshold, 100.0) self.assertEqual(metrics.num_zeroed, 1) # Both values zeroed. global_state = mean_process.initialize() values = [_make_value(x, shapes) for x in [250, 150]] output = mean_process.next(global_state, values, [1, 1]) self._check_result(output, 0, shapes) metrics = output.measurements self.assertEqual(metrics.zeroing_threshold, 100.0) self.assertEqual(metrics.num_zeroed, 2)
def test_process_type_signature(self, value_template): value_type = type_conversions.type_from_tensors(value_template) mean_process = adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type=value_type, initial_quantile_estimate=100.0, target_quantile=0.99, multiplier=2.0, increment=1.0, learning_rate=1.0, norm_order=np.inf) dummy_quantile_query = tensorflow_privacy.NoPrivacyQuantileEstimatorQuery( 50.0, 0.99, 1.0, True) quantile_query_state = dummy_quantile_query.initial_global_state() server_state_type = computation_types.FederatedType( type_conversions.type_from_tensors(quantile_query_state), placements.SERVER) self.assertEqual( mean_process.initialize.type_signature, computation_types.FunctionType(parameter=None, result=server_state_type)) client_value_type = computation_types.FederatedType( value_type, placements.CLIENTS) client_value_weight_type = computation_types.FederatedType( tf.float32, placements.CLIENTS) server_result_type = computation_types.FederatedType( value_type, placements.SERVER) server_metrics_type = computation_types.FederatedType( adaptive_zeroing.AdaptiveZeroingMetrics( zeroing_threshold=tf.float32, num_zeroed=tf.int32), placements.SERVER) self.assertTrue( mean_process.next.type_signature.is_equivalent_to( computation_types.FunctionType( parameter=collections.OrderedDict( global_state=server_state_type, value=client_value_type, weight=client_value_weight_type), result=collections.OrderedDict( state=server_state_type, result=server_result_type, measurements=server_metrics_type, ))))
def test_adaptation_up(self, shapes): value_type = type_conversions.type_from_tensors(_make_value(0, shapes)) mean_process = adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type, 1.0, 1.0, 1.0, np.log(2.0), np.inf) global_state = mean_process.initialize() values = [_make_value(x, shapes) for x in [90, 91, 92]] output = mean_process.next(global_state, values, [1, 1, 1]) self._check_result(output, 0, shapes) global_state = output.state metrics = output.measurements self.assertAllClose(metrics.current_threshold, 2.0) self.assertEqual(metrics.num_zeroed, 3) output = mean_process.next(global_state, values, [1, 1, 1]) self._check_result(output, 0, shapes) global_state = output.state metrics = output.measurements self.assertAllClose(metrics.current_threshold, 4.0) self.assertEqual(metrics.num_zeroed, 3)
def test_simple_average(self, shapes): value_type = type_conversions.type_from_tensors(_make_value(0, shapes)) mean_process = adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type, 100.0, 1.0, 1.0, 0.0, np.inf) # Basic average. global_state = mean_process.initialize() values = [_make_value(x, shapes) for x in [0, 1, 2]] output = mean_process.next(global_state, values, [1, 1, 1]) self._check_result(output, 1, shapes) metrics = output['measurements'] self.assertEqual(metrics.num_zeroed, 0) # Weighted average. global_state = output['state'] values = [_make_value(x, shapes) for x in [3, 5, 1, 0]] output = mean_process.next(global_state, values, [1, 2, 3, 2]) self._check_result(output, 2, shapes) metrics = output['measurements'] self.assertEqual(metrics.num_zeroed, 0) # One value zeroed. global_state = output['state'] values = [_make_value(x, shapes) for x in [50, 150]] output = mean_process.next(global_state, values, [1, 1]) self._check_result(output, 50, shapes) metrics = output['measurements'] self.assertEqual(metrics.num_zeroed, 1) # Both values zeroed. global_state = mean_process.initialize() values = [_make_value(x, shapes) for x in [250, 150]] output = mean_process.next(global_state, values, [1, 1]) self._check_result(output, 0, shapes) metrics = output['measurements'] self.assertEqual(metrics.num_zeroed, 2)
def test_adaptation_down(self, shapes): value_type = type_conversions.type_from_tensors(_make_value(0, shapes)) mean_process = adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type, 100.0, 0.0, 1.0, np.log(2.0), np.inf) global_state = mean_process.initialize() self.assertEqual(global_state.current_estimate, 100.0) values = [_make_value(x, shapes) for x in [0, 1, 2]] output = mean_process.next(global_state, values, [1, 1, 1]) self._check_result(output, 1, shapes) global_state = output['state'] self.assertAllClose(global_state.current_estimate, 50.0) metrics = output['measurements'] self.assertAllClose(metrics.current_threshold, 50.0) self.assertEqual(metrics.num_zeroed, 0) output = mean_process.next(global_state, values, [1, 1, 1]) self._check_result(output, 1, shapes) global_state = output['state'] self.assertAllClose(global_state.current_estimate, 25.0) metrics = output['measurements'] self.assertAllClose(metrics.current_threshold, 25.0) self.assertEqual(metrics.num_zeroed, 0)
def test_raises_with_empty_value(self): value_type = type_conversions.type_from_tensors(()) with self.assertRaises(ValueError): adaptive_zeroing.build_adaptive_zeroing_mean_process( value_type, 100.0, 0.99, 2.0, 1.0, np.inf)