Esempio n. 1
0
 def test_slice_by_percentiles(self):
     input_data = SlicingSpec(entire_dataset=False, by_percentiles=True)
     expected0 = SingleSliceSpec(SlicingFeature.PERCENTILE, (0, 10))
     expected5 = SingleSliceSpec(SlicingFeature.PERCENTILE, (50, 60))
     output = get_single_slice_specs(input_data)
     self.assertLen(output, 10)
     self.assertTrue(_are_all_fields_equal(output[0], expected0))
     self.assertTrue(_are_all_fields_equal(output[5], expected5))
  def __init__(self, *args, **kwargs):
    super(PrivacyReportTest, self).__init__(*args, **kwargs)

    # Classifier that achieves an AUC of 0.5.
    self.imperfect_classifier_result = SingleAttackResult(
        slice_spec=SingleSliceSpec(None),
        attack_type=AttackType.THRESHOLD_ATTACK,
        roc_curve=RocCurve(
            tpr=np.array([0.0, 0.5, 1.0]),
            fpr=np.array([0.0, 0.5, 1.0]),
            thresholds=np.array([0, 1, 2])),
        data_size=DataSize(ntrain=1, ntest=1))

    # Classifier that achieves an AUC of 1.0.
    self.perfect_classifier_result = SingleAttackResult(
        slice_spec=SingleSliceSpec(None),
        attack_type=AttackType.THRESHOLD_ATTACK,
        roc_curve=RocCurve(
            tpr=np.array([0.0, 1.0, 1.0]),
            fpr=np.array([1.0, 1.0, 0.0]),
            thresholds=np.array([0, 1, 2])),
        data_size=DataSize(ntrain=1, ntest=1))

    self.results_epoch_0 = AttackResults(
        single_attack_results=[self.imperfect_classifier_result],
        privacy_report_metadata=PrivacyReportMetadata(
            accuracy_train=0.4,
            accuracy_test=0.3,
            epoch_num=0,
            model_variant_label='default'))

    self.results_epoch_10 = AttackResults(
        single_attack_results=[self.imperfect_classifier_result],
        privacy_report_metadata=PrivacyReportMetadata(
            accuracy_train=0.4,
            accuracy_test=0.3,
            epoch_num=10,
            model_variant_label='default'))

    self.results_epoch_15 = AttackResults(
        single_attack_results=[self.perfect_classifier_result],
        privacy_report_metadata=PrivacyReportMetadata(
            accuracy_train=0.5,
            accuracy_test=0.4,
            epoch_num=15,
            model_variant_label='default'))

    self.results_epoch_15_model_2 = AttackResults(
        single_attack_results=[self.perfect_classifier_result],
        privacy_report_metadata=PrivacyReportMetadata(
            accuracy_train=0.6,
            accuracy_test=0.7,
            epoch_num=15,
            model_variant_label='model 2'))

    self.attack_results_no_metadata = AttackResults(
        single_attack_results=[self.perfect_classifier_result])
Esempio n. 3
0
 def test_slice_by_correcness(self):
     input_data = SlicingSpec(entire_dataset=False,
                              by_classification_correctness=True)
     expected = SingleSliceSpec(SlicingFeature.CORRECTLY_CLASSIFIED, True)
     output = get_single_slice_specs(input_data)
     self.assertLen(output, 2)
     self.assertTrue(_are_all_fields_equal(output[0], expected))
Esempio n. 4
0
    def __init__(self, *args, **kwargs):
        super(AttackResultsCollectionTest, self).__init__(*args, **kwargs)

        self.some_attack_result = SingleAttackResult(
            slice_spec=SingleSliceSpec(None),
            attack_type=AttackType.THRESHOLD_ATTACK,
            roc_curve=RocCurve(tpr=np.array([0.0, 0.5, 1.0]),
                               fpr=np.array([0.0, 0.5, 1.0]),
                               thresholds=np.array([0, 1, 2])))

        self.results_epoch_10 = AttackResults(
            single_attack_results=[self.some_attack_result],
            privacy_report_metadata=PrivacyReportMetadata(
                accuracy_train=0.4,
                accuracy_test=0.3,
                epoch_num=10,
                model_variant_label='default'))

        self.results_epoch_15 = AttackResults(
            single_attack_results=[self.some_attack_result],
            privacy_report_metadata=PrivacyReportMetadata(
                accuracy_train=0.5,
                accuracy_test=0.4,
                epoch_num=15,
                model_variant_label='default'))

        self.attack_results_no_metadata = AttackResults(
            single_attack_results=[self.some_attack_result])

        self.collection_with_metadata = AttackResultsCollection(
            [self.results_epoch_10, self.results_epoch_15])

        self.collection_no_metadata = AttackResultsCollection(
            [self.attack_results_no_metadata, self.attack_results_no_metadata])
    def test_slice_by_class(self):
        class_index = 1
        class_slice = SingleSliceSpec(SlicingFeature.CLASS, class_index)
        output = get_slice(self.input_data, class_slice)

        # Check logits.
        self.assertLen(output.logits_train, 2)
        self.assertLen(output.logits_test, 1)
        self.assertTrue((output.logits_train[1] == [4, 5, 0]).all())

        # Check probs.
        self.assertLen(output.probs_train, 2)
        self.assertLen(output.probs_test, 1)
        self.assertTrue((output.probs_train[1] == [0.4, 0.6, 0]).all())

        # Check labels.
        self.assertLen(output.labels_train, 2)
        self.assertLen(output.labels_test, 1)
        self.assertTrue((output.labels_train == class_index).all())
        self.assertTrue((output.labels_test == class_index).all())

        # Check losses
        self.assertLen(output.loss_train, 2)
        self.assertLen(output.loss_test, 1)
        self.assertTrue((output.loss_train == [2, 4]).all())
        self.assertTrue((output.loss_test == [0.5]).all())

        # Check entropy
        self.assertLen(output.entropy_train, 2)
        self.assertLen(output.entropy_test, 1)
        self.assertTrue((output.entropy_train == [0.4, 0.6]).all())
        self.assertTrue((output.entropy_test == [15]).all())
Esempio n. 6
0
 def test_slice_by_classes(self):
     input_data = SlicingSpec(by_class=True)
     n_classes = 5
     expected = [self.ENTIRE_DATASET_SLICE] + [
         SingleSliceSpec(SlicingFeature.CLASS, c) for c in range(n_classes)
     ]
     output = get_single_slice_specs(input_data, n_classes)
     self.assertTrue(_are_lists_equal(output, expected))
  def test_run_attack_by_slice(self):
    result = mia.run_attacks(
        get_test_input(100, 100), SlicingSpec(by_class=True),
        (AttackType.THRESHOLD_ATTACK,))

    self.assertLen(result.single_attack_results, 6)
    expected_slice = SingleSliceSpec(SlicingFeature.CLASS, 2)
    self.assertEqual(result.single_attack_results[3].slice_spec, expected_slice)
Esempio n. 8
0
    def test_attacker_advantage_random_classifier(self):
        roc = RocCurve(tpr=np.array([0.0, 0.5, 1.0]),
                       fpr=np.array([0.0, 0.5, 1.0]),
                       thresholds=np.array([0, 1, 2]))

        result = SingleAttackResult(roc_curve=roc,
                                    slice_spec=SingleSliceSpec(None),
                                    attack_type=AttackType.THRESHOLD_ATTACK)

        self.assertEqual(result.get_attacker_advantage(), 0.0)
Esempio n. 9
0
    def __init__(self, *args, **kwargs):
        super(AttackResultsTest, self).__init__(*args, **kwargs)

        # ROC curve of a perfect classifier
        self.perfect_classifier_result = SingleAttackResult(
            slice_spec=SingleSliceSpec(SlicingFeature.CORRECTLY_CLASSIFIED,
                                       True),
            attack_type=AttackType.THRESHOLD_ATTACK,
            roc_curve=RocCurve(tpr=np.array([0.0, 1.0, 1.0]),
                               fpr=np.array([1.0, 1.0, 0.0]),
                               thresholds=np.array([0, 1, 2])))

        # ROC curve of a random classifier
        self.random_classifier_result = SingleAttackResult(
            slice_spec=SingleSliceSpec(None),
            attack_type=AttackType.THRESHOLD_ATTACK,
            roc_curve=RocCurve(tpr=np.array([0.0, 0.5, 1.0]),
                               fpr=np.array([0.0, 0.5, 1.0]),
                               thresholds=np.array([0, 1, 2])))
Esempio n. 10
0
class SingleSliceSpecsTest(absltest.TestCase):
    """Tests for get_single_slice_specs."""

    ENTIRE_DATASET_SLICE = SingleSliceSpec()

    def test_no_slices(self):
        input_data = SlicingSpec(entire_dataset=False)
        expected = []
        output = get_single_slice_specs(input_data)
        self.assertTrue(_are_lists_equal(output, expected))

    def test_entire_dataset(self):
        input_data = SlicingSpec()
        expected = [self.ENTIRE_DATASET_SLICE]
        output = get_single_slice_specs(input_data)
        self.assertTrue(_are_lists_equal(output, expected))

    def test_slice_by_classes(self):
        input_data = SlicingSpec(by_class=True)
        n_classes = 5
        expected = [self.ENTIRE_DATASET_SLICE] + [
            SingleSliceSpec(SlicingFeature.CLASS, c) for c in range(n_classes)
        ]
        output = get_single_slice_specs(input_data, n_classes)
        self.assertTrue(_are_lists_equal(output, expected))

    def test_slice_by_percentiles(self):
        input_data = SlicingSpec(entire_dataset=False, by_percentiles=True)
        expected0 = SingleSliceSpec(SlicingFeature.PERCENTILE, (0, 10))
        expected5 = SingleSliceSpec(SlicingFeature.PERCENTILE, (50, 60))
        output = get_single_slice_specs(input_data)
        self.assertLen(output, 10)
        self.assertTrue(_are_all_fields_equal(output[0], expected0))
        self.assertTrue(_are_all_fields_equal(output[5], expected5))

    def test_slice_by_correcness(self):
        input_data = SlicingSpec(entire_dataset=False,
                                 by_classification_correctness=True)
        expected = SingleSliceSpec(SlicingFeature.CORRECTLY_CLASSIFIED, True)
        output = get_single_slice_specs(input_data)
        self.assertLen(output, 2)
        self.assertTrue(_are_all_fields_equal(output[0], expected))

    def test_slicing_by_multiple_features(self):
        input_data = SlicingSpec(entire_dataset=True,
                                 by_class=True,
                                 by_percentiles=True,
                                 by_classification_correctness=True)
        n_classes = 10
        expected_slices = n_classes
        expected_slices += 1  # entire dataset slice
        expected_slices += 10  # percentiles slices
        expected_slices += 2  # correcness classification slices
        output = get_single_slice_specs(input_data, n_classes)
        self.assertLen(output, expected_slices)
    def test_auc_random_classifier(self):
        roc = RocCurve(tpr=np.array([0.0, 0.5, 1.0]),
                       fpr=np.array([0.0, 0.5, 1.0]),
                       thresholds=np.array([0, 1, 2]))

        result = SingleAttackResult(roc_curve=roc,
                                    slice_spec=SingleSliceSpec(None),
                                    attack_type=AttackType.THRESHOLD_ATTACK,
                                    data_size=DataSize(ntrain=1, ntest=1))

        self.assertEqual(result.get_auc(), 0.5)
Esempio n. 12
0
def run_seq2seq_attack(
        attack_input: Seq2SeqAttackInputData,
        privacy_report_metadata: PrivacyReportMetadata = None,
        balance_attacker_training: bool = True) -> AttackResults:
    """Runs membership inference attacks on a seq2seq model.

  Args:
    attack_input: input data for running an attack
    privacy_report_metadata: the metadata of the model under attack.
    balance_attacker_training: Whether the training and test sets for the
      membership inference attacker should have a balanced (roughly equal)
      number of samples from the training and test sets used to develop the
      model under attack.

  Returns:
    the attack result.
  """
    attack_input.validate()

    # The attacker uses the average rank (a single number) of a seq2seq dataset
    # record to determine membership. So only Logistic Regression is supported,
    # as it makes the most sense for single-number features.
    attacker = models.LogisticRegressionAttacker()

    # Create attacker data and populate fields of privacy_report_metadata
    privacy_report_metadata = privacy_report_metadata or PrivacyReportMetadata(
    )
    prepared_attacker_data = create_seq2seq_attacker_data(
        attack_input_data=attack_input,
        balance=balance_attacker_training,
        privacy_report_metadata=privacy_report_metadata)

    attacker.train_model(prepared_attacker_data.features_train,
                         prepared_attacker_data.is_training_labels_train)

    # Run the attacker on (permuted) test examples.
    predictions_test = attacker.predict(prepared_attacker_data.features_test)

    # Generate ROC curves with predictions.
    fpr, tpr, thresholds = metrics.roc_curve(
        prepared_attacker_data.is_training_labels_test, predictions_test)

    roc_curve = RocCurve(tpr=tpr, fpr=fpr, thresholds=thresholds)

    attack_results = [
        SingleAttackResult(slice_spec=SingleSliceSpec(),
                           attack_type=AttackType.LOGISTIC_REGRESSION,
                           roc_curve=roc_curve,
                           data_size=prepared_attacker_data.data_size)
    ]

    return AttackResults(single_attack_results=attack_results,
                         privacy_report_metadata=privacy_report_metadata)
    def test_attack_with_varied_thresholds(self):

        result = SingleMembershipProbabilityResult(
            slice_spec=SingleSliceSpec(None),
            train_membership_probs=np.array([0.91, 1, 0.92, 0.82, 0.75]),
            test_membership_probs=np.array([0.81, 0.7, 0.75, 0.25, 0.3]))

        self.assertEqual(
            result.attack_with_varied_thresholds(
                threshold_list=np.array([0.8, 0.7]))[1].tolist(), [0.8, 0.625])
        self.assertEqual(
            result.attack_with_varied_thresholds(
                threshold_list=np.array([0.8, 0.7]))[2].tolist(), [0.8, 1])
Esempio n. 14
0
    def test_slice_by_percentile(self):
        percentile_slice = SingleSliceSpec(SlicingFeature.PERCENTILE, (0, 50))
        output = get_slice(self.input_data, percentile_slice)

        # Check logits.
        self.assertLen(output.logits_train, 3)
        self.assertLen(output.logits_test, 1)
        self.assertTrue((output.logits_test[0] == [10, 0, 11]).all())

        # Check labels.
        self.assertLen(output.labels_train, 3)
        self.assertLen(output.labels_test, 1)
        self.assertTrue((output.labels_train == [1, 0, 2]).all())
        self.assertTrue((output.labels_test == [1]).all())
Esempio n. 15
0
    def test_slice_by_correctness(self):
        percentile_slice = SingleSliceSpec(SlicingFeature.CORRECTLY_CLASSIFIED,
                                           False)
        output = get_slice(self.input_data, percentile_slice)

        # Check logits.
        self.assertLen(output.logits_train, 2)
        self.assertLen(output.logits_test, 3)
        self.assertTrue((output.logits_train[1] == [6, 7, 0]).all())
        self.assertTrue((output.logits_test[1] == [12, 13, 0]).all())

        # Check labels.
        self.assertLen(output.labels_train, 2)
        self.assertLen(output.labels_test, 3)
        self.assertTrue((output.labels_train == [0, 2]).all())
        self.assertTrue((output.labels_test == [1, 2, 0]).all())
Esempio n. 16
0
def get_single_slice_specs(slicing_spec: SlicingSpec,
                           num_classes: int = None) -> List[SingleSliceSpec]:
    """Returns slices of data according to slicing_spec."""
    result = []

    if slicing_spec.entire_dataset:
        result.append(SingleSliceSpec())

    # Create slices by class.
    by_class = slicing_spec.by_class
    if isinstance(by_class, bool):
        if by_class:
            assert num_classes, "When by_class == True, num_classes should be given."
            assert 0 <= num_classes <= 1000, (
                f"Too much classes for slicing by classes. "
                f"Found {num_classes}.")
            for c in range(num_classes):
                result.append(SingleSliceSpec(SlicingFeature.CLASS, c))
    elif isinstance(by_class, int):
        result.append(SingleSliceSpec(SlicingFeature.CLASS, by_class))
    elif isinstance(by_class, collections.Iterable):
        for c in by_class:
            result.append(SingleSliceSpec(SlicingFeature.CLASS, c))

    # Create slices by percentiles
    if slicing_spec.by_percentiles:
        for percent in range(0, 100, 10):
            result.append(
                SingleSliceSpec(SlicingFeature.PERCENTILE,
                                (percent, percent + 10)))

    # Create slices by correctness of the classifications.
    if slicing_spec.by_classification_correctness:
        result.append(
            SingleSliceSpec(SlicingFeature.CORRECTLY_CLASSIFIED, True))
        result.append(
            SingleSliceSpec(SlicingFeature.CORRECTLY_CLASSIFIED, False))

    return result
Esempio n. 17
0
 def testStr(self, feature, value, expected_str):
     self.assertEqual(str(SingleSliceSpec(feature, value)), expected_str)
Esempio n. 18
0
 def testStrEntireDataset(self):
     self.assertEqual(str(SingleSliceSpec()), 'Entire dataset')
Esempio n. 19
0
 def test_slice_entire_dataset(self):
     entire_dataset_slice = SingleSliceSpec()
     output = get_slice(self.input_data, entire_dataset_slice)
     expected = self.input_data
     expected.slice_spec = entire_dataset_slice
     self.assertTrue(_are_all_fields_equal(output, self.input_data))
def _get_slice_spec(data: AttackInputData) -> SingleSliceSpec:
    if hasattr(data, 'slice_spec'):
        return data.slice_spec
    return SingleSliceSpec()