def test_rdp_composition(self): base_event = dp_event.GaussianDpEvent(3.14159) base_rdp = _get_test_rdp(base_event) rdp_with_count = _get_test_rdp(base_event, count=6) self.assertAlmostEqual(rdp_with_count, base_rdp * 6) rdp_with_self_compose = _get_test_rdp( dp_event.SelfComposedDpEvent(base_event, 6)) self.assertAlmostEqual(rdp_with_self_compose, base_rdp * 6) rdp_with_self_compose_and_count = _get_test_rdp( dp_event.SelfComposedDpEvent(base_event, 2), count=3) self.assertAlmostEqual(rdp_with_self_compose_and_count, base_rdp * 6) rdp_with_compose = _get_test_rdp(dp_event.ComposedDpEvent([base_event] * 6)) self.assertAlmostEqual(rdp_with_compose, base_rdp * 6) rdp_with_compose_and_self_compose = _get_test_rdp( dp_event.ComposedDpEvent([ dp_event.SelfComposedDpEvent(base_event, 1), dp_event.SelfComposedDpEvent(base_event, 2), dp_event.SelfComposedDpEvent(base_event, 3) ])) self.assertAlmostEqual(rdp_with_compose_and_self_compose, base_rdp * 6) base_event_2 = dp_event.GaussianDpEvent(1.61803) base_rdp_2 = _get_test_rdp(base_event_2) rdp_with_heterogeneous_compose = _get_test_rdp( dp_event.ComposedDpEvent([base_event, base_event_2])) self.assertAlmostEqual(rdp_with_heterogeneous_compose, base_rdp + base_rdp_2)
def test_compute_rdp_gaussian(self): alpha = 3.14159 sigma = 2.71828 event = dp_event.GaussianDpEvent(sigma) accountant = rdp_privacy_accountant.RdpAccountant(orders=[alpha]) accountant.compose(event) self.assertAlmostEqual(accountant._rdp[0], alpha / (2 * sigma**2))
def test_effective_gaussian_noise_multiplier(self): np.random.seed(0xBAD5EED) sigmas = np.random.uniform(size=(4,)) event = dp_event.ComposedDpEvent([ dp_event.GaussianDpEvent(sigmas[0]), dp_event.SelfComposedDpEvent(dp_event.GaussianDpEvent(sigmas[1]), 3), dp_event.ComposedDpEvent([ dp_event.GaussianDpEvent(sigmas[2]), dp_event.GaussianDpEvent(sigmas[3]) ]) ]) sigma = rdp_privacy_accountant._effective_gaussian_noise_multiplier(event) multi_sigmas = list(sigmas) + [sigmas[1]] * 2 expected = sum(s**-2 for s in multi_sigmas)**-0.5 self.assertAlmostEqual(sigma, expected)
def test_compute_rdp_multi_gaussian(self): alpha = 3.14159 sigma1, sigma2 = 2.71828, 6.28319 rdp1 = alpha / (2 * sigma1**2) rdp2 = alpha / (2 * sigma2**2) rdp = rdp1 + rdp2 accountant = rdp_privacy_accountant.RdpAccountant(orders=[alpha]) accountant.compose( dp_event.PoissonSampledDpEvent( 1.0, dp_event.ComposedDpEvent([ dp_event.GaussianDpEvent(sigma1), dp_event.GaussianDpEvent(sigma2) ]))) self.assertAlmostEqual(accountant._rdp[0], rdp)
def test_zero_fixed_batch_sample(self): accountant = rdp_privacy_accountant.RdpAccountant( [3.14159], privacy_accountant.NeighboringRelation.REPLACE_ONE) accountant.compose( dp_event.SampledWithoutReplacementDpEvent( 1000, 0, dp_event.GaussianDpEvent(1.0))) self.assertEqual(accountant.get_epsilon(1e-10), 0) self.assertEqual(accountant.get_delta(1e-10), 0)
def test_no_tree_no_sampling(self, total_steps, noise_multiplier): orders = [1 + x / 10 for x in range(1, 100)] + list(range(12, 64)) tree_rdp = _compose_trees(noise_multiplier, [1] * total_steps, orders)._rdp accountant = rdp_privacy_accountant.RdpAccountant(orders) event = dp_event.SelfComposedDpEvent( dp_event.GaussianDpEvent(noise_multiplier), total_steps) accountant.compose(event) base_rdp = accountant._rdp self.assertTrue(np.allclose(tree_rdp, base_rdp, rtol=1e-12))
def test_supports(self): aor_accountant = rdp_privacy_accountant.RdpAccountant( [2.0], privacy_accountant.NeighboringRelation.ADD_OR_REMOVE_ONE) ro_accountant = rdp_privacy_accountant.RdpAccountant( [2.0], privacy_accountant.NeighboringRelation.REPLACE_ONE) event = dp_event.GaussianDpEvent(1.0) self.assertTrue(aor_accountant.supports(event)) self.assertTrue(ro_accountant.supports(event)) event = dp_event.SelfComposedDpEvent(dp_event.GaussianDpEvent(1.0), 6) self.assertTrue(aor_accountant.supports(event)) self.assertTrue(ro_accountant.supports(event)) event = dp_event.ComposedDpEvent( [dp_event.GaussianDpEvent(1.0), dp_event.GaussianDpEvent(2.0)]) self.assertTrue(aor_accountant.supports(event)) self.assertTrue(ro_accountant.supports(event)) event = dp_event.PoissonSampledDpEvent(0.1, dp_event.GaussianDpEvent(1.0)) self.assertTrue(aor_accountant.supports(event)) self.assertFalse(ro_accountant.supports(event)) composed_gaussian = dp_event.ComposedDpEvent( [dp_event.GaussianDpEvent(1.0), dp_event.GaussianDpEvent(2.0)]) event = dp_event.PoissonSampledDpEvent(0.1, composed_gaussian) self.assertTrue(aor_accountant.supports(event)) self.assertFalse(ro_accountant.supports(event)) event = dp_event.SampledWithoutReplacementDpEvent( 1000, 10, dp_event.GaussianDpEvent(1.0)) self.assertFalse(aor_accountant.supports(event)) self.assertTrue(ro_accountant.supports(event)) event = dp_event.SampledWithoutReplacementDpEvent(1000, 10, composed_gaussian) self.assertFalse(aor_accountant.supports(event)) self.assertTrue(ro_accountant.supports(event)) event = dp_event.SampledWithReplacementDpEvent( 1000, 10, dp_event.GaussianDpEvent(1.0)) self.assertFalse(aor_accountant.supports(event)) self.assertFalse(ro_accountant.supports(event))
def test_gaussian_basic(self): gaussian_event = dp_event.GaussianDpEvent( noise_multiplier=math.sqrt(3)) accountant = pld_privacy_accountant.PLDAccountant() accountant.compose(gaussian_event, 1) accountant.compose(gaussian_event, 2) exact_epsilon = 1 exact_delta = 0.126936 self.assertAlmostEqual(accountant.get_delta(exact_epsilon), exact_delta, delta=1e-3) self.assertAlmostEqual(accountant.get_epsilon(exact_delta), exact_epsilon, delta=1e-3)
def test_poisson_subsampled_gaussian(self): subsampled_gaussian_event = dp_event.PoissonSampledDpEvent( 0.2, dp_event.GaussianDpEvent(noise_multiplier=0.5)) accountant = pld_privacy_accountant.PLDAccountant() accountant.compose(subsampled_gaussian_event, 1) accountant.compose(subsampled_gaussian_event, 2) exact_epsilon = 1 expected_delta = 0.15594 self.assertAlmostEqual(accountant.get_delta(exact_epsilon), expected_delta, delta=1e-3) self.assertAlmostEqual(accountant.get_epsilon(expected_delta), exact_epsilon, delta=1e-3)
def test_self_composed_subsampled_gaussian(self): event = dp_event.SelfComposedDpEvent( dp_event.PoissonSampledDpEvent(0.2, dp_event.GaussianDpEvent(0.5)), 3) accountant = pld_privacy_accountant.PLDAccountant() accountant.compose(event) exact_epsilon = 1 expected_delta = 0.15594 self.assertAlmostEqual(accountant.get_delta(exact_epsilon), expected_delta, delta=1e-3) self.assertAlmostEqual(accountant.get_epsilon(expected_delta), exact_epsilon, delta=1e-3)
def test_epsilon_delta_consistency(self): orders = range(2, 50) # Large range of orders (helps test for overflows). for q in [0, 0.01, 0.1, 0.8, 1.]: for multiplier in [0.0, 0.1, 1., 10., 100.]: event = dp_event.PoissonSampledDpEvent( q, dp_event.GaussianDpEvent(multiplier)) accountant = rdp_privacy_accountant.RdpAccountant(orders) accountant.compose(event) for delta in [.99, .9, .1, .01, 1e-3, 1e-5, 1e-9, 1e-12]: epsilon = accountant.get_epsilon(delta) delta2 = accountant.get_delta(epsilon) if np.isposinf(epsilon): self.assertEqual(delta2, 1.0) elif epsilon == 0: self.assertLessEqual(delta2, delta) else: self.assertAlmostEqual(delta, delta2)
def test_compute_rdp_poisson_sampled_gaussian(self): orders = [1.5, 2.5, 5, 50, 100, np.inf] noise_multiplier = 2.5 sampling_probability = 0.01 count = 50 event = dp_event.SelfComposedDpEvent( dp_event.PoissonSampledDpEvent( sampling_probability, dp_event.GaussianDpEvent(noise_multiplier)), count) accountant = rdp_privacy_accountant.RdpAccountant(orders=orders) accountant.compose(event) self.assertTrue( np.allclose( accountant._rdp, [ 6.5007e-04, 1.0854e-03, 2.1808e-03, 2.3846e-02, 1.6742e+02, np.inf ], rtol=1e-4))
# You may obtain a copy of the License at # # https://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. """Tests for DpEventBuilder.""" from absl.testing import absltest from dp_accounting import dp_event from dp_accounting import dp_event_builder _gaussian_event = dp_event.GaussianDpEvent(1.0) _laplace_event = dp_event.LaplaceDpEvent(1.0) _poisson_event = dp_event.PoissonSampledDpEvent(_gaussian_event, 0.1) _self_composed_event = dp_event.SelfComposedDpEvent(_gaussian_event, 3) class DpEventBuilderTest(absltest.TestCase): def test_no_op(self): builder = dp_event_builder.DpEventBuilder() self.assertEqual(dp_event.NoOpDpEvent(), builder.build()) def test_single_gaussian(self): builder = dp_event_builder.DpEventBuilder() builder.compose(_gaussian_event) self.assertEqual(_gaussian_event, builder.build())
def test_zero_poisson_sample(self): accountant = rdp_privacy_accountant.RdpAccountant([3.14159]) accountant.compose( dp_event.PoissonSampledDpEvent(0, dp_event.GaussianDpEvent(1.0))) self.assertEqual(accountant.get_epsilon(1e-10), 0) self.assertEqual(accountant.get_delta(1e-10), 0)
def test_non_positive_composition_value_error(self, count): event = dp_event.GaussianDpEvent(1.0) accountant = pld_privacy_accountant.PLDAccountant() with self.assertRaises(ValueError): accountant.compose(event, count)
def test_epsilon_non_private_gaussian(self): accountant = rdp_privacy_accountant.RdpAccountant([3.14159]) accountant.compose(dp_event.GaussianDpEvent(0)) self.assertEqual(accountant.get_epsilon(1e-1), np.inf)
class PldPrivacyAccountantTest(privacy_accountant_test.PrivacyAccountantTest, parameterized.TestCase): def _make_test_accountants(self): return [pld_privacy_accountant.PLDAccountant()] @parameterized.parameters( dp_event.GaussianDpEvent(1.0), dp_event.SelfComposedDpEvent(dp_event.GaussianDpEvent(1.0), 6), dp_event.ComposedDpEvent( [dp_event.GaussianDpEvent(1.0), dp_event.GaussianDpEvent(2.0)]), dp_event.PoissonSampledDpEvent(0.1, dp_event.GaussianDpEvent(1.0)), dp_event.ComposedDpEvent([ dp_event.PoissonSampledDpEvent(0.1, dp_event.GaussianDpEvent(1.0)), dp_event.GaussianDpEvent(2.0) ])) def test_supports_gaussian(self, event): pld_accountant = pld_privacy_accountant.PLDAccountant() self.assertTrue(pld_accountant.supports(event)) @parameterized.parameters(0, -1) def test_non_positive_composition_value_error(self, count): event = dp_event.GaussianDpEvent(1.0) accountant = pld_privacy_accountant.PLDAccountant() with self.assertRaises(ValueError): accountant.compose(event, count) def test_gaussian_basic(self): gaussian_event = dp_event.GaussianDpEvent( noise_multiplier=math.sqrt(3)) accountant = pld_privacy_accountant.PLDAccountant() accountant.compose(gaussian_event, 1) accountant.compose(gaussian_event, 2) exact_epsilon = 1 exact_delta = 0.126936 self.assertAlmostEqual(accountant.get_delta(exact_epsilon), exact_delta, delta=1e-3) self.assertAlmostEqual(accountant.get_epsilon(exact_delta), exact_epsilon, delta=1e-3) def test_poisson_subsampled_gaussian(self): subsampled_gaussian_event = dp_event.PoissonSampledDpEvent( 0.2, dp_event.GaussianDpEvent(noise_multiplier=0.5)) accountant = pld_privacy_accountant.PLDAccountant() accountant.compose(subsampled_gaussian_event, 1) accountant.compose(subsampled_gaussian_event, 2) exact_epsilon = 1 expected_delta = 0.15594 self.assertAlmostEqual(accountant.get_delta(exact_epsilon), expected_delta, delta=1e-3) self.assertAlmostEqual(accountant.get_epsilon(expected_delta), exact_epsilon, delta=1e-3) def test_self_composed_subsampled_gaussian(self): event = dp_event.SelfComposedDpEvent( dp_event.PoissonSampledDpEvent(0.2, dp_event.GaussianDpEvent(0.5)), 3) accountant = pld_privacy_accountant.PLDAccountant() accountant.compose(event) exact_epsilon = 1 expected_delta = 0.15594 self.assertAlmostEqual(accountant.get_delta(exact_epsilon), expected_delta, delta=1e-3) self.assertAlmostEqual(accountant.get_epsilon(expected_delta), exact_epsilon, delta=1e-3)