def _test_preprocessing_defences_backward(
    get_default_mnist_subset, image_dl_estimator, device_type, preprocessing_defences
):
    (_, _), (x_test_mnist, y_test_mnist) = get_default_mnist_subset

    classifier_, _ = image_dl_estimator()

    clip_values = (0, 1)
    criterion = nn.CrossEntropyLoss()
    classifier = PyTorchClassifier(
        clip_values=clip_values,
        model=classifier_.model,
        preprocessing_defences=preprocessing_defences,
        loss=criterion,
        input_shape=(1, 28, 28),
        nb_classes=10,
        device_type=device_type,
    )

    # The efficient defence-chaining.
    pseudo_gradients = np.random.randn(*x_test_mnist.shape)
    gradients_in_chain = classifier._apply_preprocessing_gradient(x_test_mnist, pseudo_gradients)

    # Apply the same backward pass one by one.
    x = x_test_mnist
    x_intermediates = [x]
    for preprocess in classifier.preprocessing_operations[:-1]:
        x = preprocess(x)[0]
        x_intermediates.append(x)

    gradients = pseudo_gradients
    for preprocess, x in zip(classifier.preprocessing_operations[::-1], x_intermediates[::-1]):
        gradients = preprocess.estimate_gradient(x, gradients)

    np.testing.assert_array_almost_equal(gradients_in_chain, gradients, decimal=4)
def test_device(art_warning):
    try:

        class Flatten(nn.Module):
            def forward(self, x):
                n, _, _, _ = x.size()
                result = x.view(n, -1)

                return result

        # Define the network
        model = nn.Sequential(nn.Conv2d(1, 2, 5),
                              nn.ReLU(), nn.MaxPool2d(2, 2), Flatten(),
                              nn.Linear(288, 10))

        # Define a loss function and optimizer
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)

        # First test cpu
        classifier_cpu = PyTorchClassifier(
            model=model,
            clip_values=(0, 1),
            loss=loss_fn,
            optimizer=optimizer,
            input_shape=(1, 28, 28),
            nb_classes=10,
            device_type="cpu",
        )

        assert classifier_cpu._device == torch.device("cpu")
        assert classifier_cpu._device != torch.device("cuda")

        # Then test gpu
        if torch.cuda.device_count() >= 2:
            with torch.cuda.device(0):
                classifier_gpu0 = PyTorchClassifier(
                    model=model,
                    clip_values=(0, 1),
                    loss=loss_fn,
                    optimizer=optimizer,
                    input_shape=(1, 28, 28),
                    nb_classes=10,
                )
                assert classifier_gpu0._device == torch.device("cuda:0")
                assert classifier_gpu0._device != torch.device("cuda:1")

            with torch.cuda.device(1):
                classifier_gpu1 = PyTorchClassifier(
                    model=model,
                    clip_values=(0, 1),
                    loss=loss_fn,
                    optimizer=optimizer,
                    input_shape=(1, 28, 28),
                    nb_classes=10,
                )
                assert classifier_gpu1._device == torch.device("cuda:1")
                assert classifier_gpu1._device != torch.device("cuda:0")
    except ARTTestException as e:
        art_warning(e)
def _test_preprocessing_defences_forward(
    get_default_mnist_subset, image_dl_estimator, device_type, preprocessing_defences
):
    (_, _), (x_test_mnist, y_test_mnist) = get_default_mnist_subset

    classifier_, _ = image_dl_estimator()

    clip_values = (0, 1)
    criterion = nn.CrossEntropyLoss()
    classifier = PyTorchClassifier(
        clip_values=clip_values,
        model=classifier_.model,
        preprocessing_defences=preprocessing_defences,
        loss=criterion,
        input_shape=(1, 28, 28),
        nb_classes=10,
        device_type=device_type,
    )

    with torch.no_grad():
        predictions_classifier = classifier.predict(x_test_mnist)

    # Apply the same defences by hand
    x_test_defense = x_test_mnist
    for defence in preprocessing_defences:
        x_test_defense, _ = defence(x_test_defense, y_test_mnist)

    x_test_defense = torch.tensor(x_test_defense)
    with torch.no_grad():
        predictions_check = classifier_.model(x_test_defense)
    predictions_check = predictions_check.cpu().numpy()

    # Check that the prediction results match
    np.testing.assert_array_almost_equal(predictions_classifier, predictions_check, decimal=4)
def net_generation_and_train(X_train, y_train, net_type):

    loss = nn.CrossEntropyLoss()
    net = net_type(n_features=2, n_classes=2)
    optimizer = optim.SGD(net.parameters(),
                          lr=0.1, momentum=0.9)

    clf = PyTorchClassifier(model=net, loss=loss, input_shape=(1,2),
                                nb_classes=2, optimizer=optimizer)
    clf.fit(X_train, y_train, batch_size=10, nb_epochs=100)

    return clf
예제 #5
0
 def _weight_grad(classifier: PyTorchClassifier, x: torch.Tensor,
                  target: torch.Tensor) -> torch.Tensor:
     classifier.model.zero_grad()
     y = classifier.model(x)
     loss_ = classifier.loss(y, target)
     gradspred = torch.autograd.grad(loss_,
                                     list(
                                         classifier.model.parameters()),
                                     create_graph=True,
                                     retain_graph=True)
     d_w = torch.cat([w.flatten() for w in gradspred])
     d_w_norm = d_w / torch.sqrt(torch.sum(torch.square(d_w)))
     return d_w_norm
def test_pickle(art_warning, get_default_mnist_subset, image_dl_estimator):
    try:
        (x_train_mnist,
         y_train_mnist), (x_test_mnist,
                          y_test_mnist) = get_default_mnist_subset

        from art import config

        full_path = os.path.join(config.ART_DATA_PATH, "my_classifier")
        folder = os.path.split(full_path)[0]
        if not os.path.exists(folder):
            os.makedirs(folder)

        # The model used within the common ART pytorch get_image_classifier_list does not support pickling
        model = Model()
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)
        myclassifier_2 = PyTorchClassifier(model=model,
                                           clip_values=(0, 1),
                                           loss=loss_fn,
                                           optimizer=optimizer,
                                           input_shape=(1, 28, 28),
                                           nb_classes=10)
        myclassifier_2.fit(x_train_mnist,
                           y_train_mnist,
                           batch_size=100,
                           nb_epochs=1)

        pickle.dump(myclassifier_2, open(full_path, "wb"))

        with open(full_path, "rb") as f:
            loaded_model = pickle.load(f)
            np.testing.assert_equal(myclassifier_2._clip_values,
                                    loaded_model._clip_values)
            assert myclassifier_2._channel_index == loaded_model._channel_index
            assert set(myclassifier_2.__dict__.keys()) == set(
                loaded_model.__dict__.keys())

        # Test predict
        predictions_1 = myclassifier_2.predict(x_test_mnist)
        accuracy_1 = np.sum(
            np.argmax(predictions_1, axis=1) == np.argmax(
                y_test_mnist, axis=1)) / y_test_mnist.shape[0]
        predictions_2 = loaded_model.predict(x_test_mnist)
        accuracy_2 = np.sum(
            np.argmax(predictions_2, axis=1) == np.argmax(
                y_test_mnist, axis=1)) / y_test_mnist.shape[0]
        assert accuracy_1 == accuracy_2
    except ARTTestException as e:
        art_warning(e)
예제 #7
0
    def loss_gradient(self, x: np.ndarray, y: np.ndarray,
                      **kwargs) -> np.ndarray:
        """
        Compute the gradient of the loss function w.r.t. `x`.

        :param x: Sample input with shape as expected by the model.
        :param y: Target values (class labels) one-hot-encoded of shape (nb_samples, nb_classes) or indices of shape
                  (nb_samples,).
        :param sampling: True if loss gradients should be determined with Monte Carlo sampling.
        :type sampling: `bool`
        :return: Array of gradients of the same shape as `x`.
        """
        import torch  # lgtm [py/repeated-import]

        sampling = kwargs.get("sampling")

        if sampling:
            # Apply preprocessing
            x_preprocessed, y_preprocessed = self._apply_preprocessing(
                x, y, fit=False)

            # Check label shape
            if self._reduce_labels:
                y_preprocessed = np.argmax(y_preprocessed, axis=1)

            # Convert the inputs to Tensors
            inputs_t = torch.from_numpy(x_preprocessed).to(self._device)
            inputs_t.requires_grad = True

            # Convert the labels to Tensors
            labels_t = torch.from_numpy(y_preprocessed).to(self._device)
            inputs_repeat_t = inputs_t.repeat_interleave(self.sample_size, 0)

            noise = torch.randn_like(inputs_repeat_t,
                                     device=self._device) * self.scale
            inputs_noise_t = inputs_repeat_t + noise
            if self.clip_values is not None:
                inputs_noise_t.clamp(self.clip_values[0], self.clip_values[1])

            model_outputs = self._model(inputs_noise_t)[-1]
            softmax = torch.nn.functional.softmax(model_outputs, dim=1)
            average_softmax = (softmax.reshape(-1, self.sample_size,
                                               model_outputs.shape[-1]).mean(
                                                   1, keepdim=True).squeeze(1))
            log_softmax = torch.log(average_softmax.clamp(min=1e-20))
            loss = torch.nn.functional.nll_loss(log_softmax, labels_t)

            # Clean gradients
            self._model.zero_grad()

            # Compute gradients
            loss.backward()
            gradients = inputs_t.grad.cpu().numpy().copy()  # type: ignore
            gradients = self._apply_preprocessing_gradient(x, gradients)
            assert gradients.shape == x.shape

        else:
            gradients = PyTorchClassifier.loss_gradient(self, x, y, **kwargs)

        return gradients
def test_fgsm_defences(fix_get_mnist_subset, image_dl_estimator, device_type):

    clip_values = (0, 1)
    smooth_3x3 = SpatialSmoothingPyTorch(window_size=3,
                                         channels_first=True,
                                         device_type=device_type)
    smooth_5x5 = SpatialSmoothingPyTorch(window_size=5,
                                         channels_first=True,
                                         device_type=device_type)
    smooth_7x7 = SpatialSmoothingPyTorch(window_size=7,
                                         channels_first=True,
                                         device_type=device_type)
    classifier_, _ = image_dl_estimator(one_classifier=True)

    criterion = nn.CrossEntropyLoss()
    classifier = PyTorchClassifier(
        clip_values=clip_values,
        model=classifier_.model,
        preprocessing_defences=[smooth_3x3, smooth_5x5, smooth_7x7],
        loss=criterion,
        input_shape=(1, 28, 28),
        nb_classes=10,
        device_type=device_type,
    )
    assert len(classifier.preprocessing_defences) == 3

    attack = FastGradientMethod(classifier, eps=1, batch_size=128)
    backend_test_defended_images(attack, fix_get_mnist_subset)
예제 #9
0
    def setUpClass(cls):
        super().setUpClass()

        cls.x_train_mnist = np.reshape(cls.x_train_mnist, (cls.x_train_mnist.shape[0], 1, 28, 28)).astype(np.float32)
        cls.x_test_mnist = np.reshape(cls.x_test_mnist, (cls.x_test_mnist.shape[0], 1, 28, 28)).astype(np.float32)

        # Define the internal classifier
        classifier = get_image_classifier_pt()

        # Define the internal detector
        conv = nn.Conv2d(1, 16, 5)
        linear = nn.Linear(2304, 1)
        torch.nn.init.xavier_uniform_(conv.weight)
        torch.nn.init.xavier_uniform_(linear.weight)
        model = nn.Sequential(conv, nn.ReLU(), nn.MaxPool2d(2, 2), Flatten(), linear)
        model = Model(model)
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)
        detector = PyTorchClassifier(
            model=model, loss=loss_fn, optimizer=optimizer, input_shape=(1, 28, 28), nb_classes=1, clip_values=(0, 1)
        )

        # Define the detector-classifier
        cls.detector_classifier = DetectorClassifier(classifier=classifier, detector=detector)

        cls.x_train_mnist = np.reshape(cls.x_train_mnist, (cls.x_train_mnist.shape[0], 28, 28, 1)).astype(np.float32)
        cls.x_test_mnist = np.reshape(cls.x_test_mnist, (cls.x_test_mnist.shape[0], 28, 28, 1)).astype(np.float32)
예제 #10
0
    def test_check_params(self):
        model = Model()
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)
        pixel_cnn = PyTorchClassifier(
            model=model, loss=loss_fn, optimizer=optimizer, input_shape=(4,), nb_classes=2, clip_values=(0, 1)
        )

        with self.assertRaises(TypeError):
            _ = PixelDefend(pixel_cnn="pixel_cnn")

        with self.assertRaises(ValueError):
            _ = PixelDefend(pixel_cnn=pixel_cnn, eps=-1)

        with self.assertRaises(ValueError):
            _ = PixelDefend(pixel_cnn=pixel_cnn, clip_values=(1, 0))

        with self.assertRaises(ValueError):
            _ = PixelDefend(pixel_cnn=pixel_cnn, clip_values=(-1, 1))

        with self.assertRaises(ValueError):
            _ = PixelDefend(pixel_cnn=pixel_cnn, clip_values=(0, 2))

        with self.assertRaises(ValueError):
            _ = PixelDefend(pixel_cnn=pixel_cnn, batch_size=-1)

        with self.assertRaises(ValueError):
            _ = PixelDefend(pixel_cnn=pixel_cnn, verbose="False")
    def _create_ptclassifier():
        """
        To create a simple PyTorchClassifier for testing.
        :return:
        """
        class Model(nn.Module):
            def __init__(self):
                super(Model, self).__init__()
                self.conv = nn.Conv2d(1, 16, 5)
                self.pool = nn.MaxPool2d(2, 2)
                self.fc = nn.Linear(2304, 10)

            def forward(self, x):
                x = self.pool(f.relu(self.conv(x)))
                x = x.view(-1, 2304)
                logit_output = self.fc(x)

                return logit_output

        # Define the network
        model = Model()

        # Define a loss function and optimizer
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)

        # Get classifier
        ptc = PyTorchClassifier(model=model,
                                loss=loss_fn,
                                optimizer=optimizer,
                                input_shape=(1, 28, 28),
                                nb_classes=10,
                                clip_values=(0, 1))

        return ptc
예제 #12
0
 def _predict_classifier(self, x: np.ndarray, batch_size: int,
                         training_mode: bool, **kwargs) -> np.ndarray:
     x = x.astype(ART_NUMPY_DTYPE)
     return PyTorchClassifier.predict(self,
                                      x=x,
                                      batch_size=batch_size,
                                      training_mode=training_mode,
                                      **kwargs)
예제 #13
0
 def _fit_classifier(self, x: np.ndarray, y: np.ndarray, batch_size: int,
                     nb_epochs: int, **kwargs) -> None:
     x = x.astype(ART_NUMPY_DTYPE)
     return PyTorchClassifier.fit(self,
                                  x,
                                  y,
                                  batch_size=batch_size,
                                  nb_epochs=nb_epochs,
                                  **kwargs)
예제 #14
0
def test_black_box_with_model(art_warning, decision_tree_estimator, get_iris_dataset):
    try:
        attack_feature = 2  # petal length

        # need to transform attacked feature into categorical
        def transform_feature(x):
            x[x > 0.5] = 2.0
            x[(x > 0.2) & (x <= 0.5)] = 1.0
            x[x <= 0.2] = 0.0

        values = [0.0, 1.0, 2.0]

        (x_train_iris, y_train_iris), (x_test_iris, y_test_iris) = get_iris_dataset
        # training data without attacked feature
        x_train_for_attack = np.delete(x_train_iris, attack_feature, 1)
        # only attacked feature
        x_train_feature = x_train_iris[:, attack_feature].copy().reshape(-1, 1)
        transform_feature(x_train_feature)
        # training data with attacked feature (after transformation)
        x_train = np.concatenate((x_train_for_attack[:, :attack_feature], x_train_feature), axis=1)
        x_train = np.concatenate((x_train, x_train_for_attack[:, attack_feature:]), axis=1)

        # test data without attacked feature
        x_test_for_attack = np.delete(x_test_iris, attack_feature, 1)
        # only attacked feature
        x_test_feature = x_test_iris[:, attack_feature].copy().reshape(-1, 1)
        transform_feature(x_test_feature)

        model = nn.Linear(4, 3)

        # Define a loss function and optimizer
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)
        attack_model = PyTorchClassifier(
            model=model, clip_values=(0, 1), loss=loss_fn, optimizer=optimizer, input_shape=(4,), nb_classes=3
        )

        classifier = decision_tree_estimator()

        attack = AttributeInferenceBlackBox(classifier, attack_model=attack_model, attack_feature=attack_feature)
        # get original model's predictions
        x_train_predictions = np.array([np.argmax(arr) for arr in classifier.predict(x_train_iris)]).reshape(-1, 1)
        x_test_predictions = np.array([np.argmax(arr) for arr in classifier.predict(x_test_iris)]).reshape(-1, 1)
        # train attack model
        attack.fit(x_train)
        # infer attacked feature
        inferred_train = attack.infer(x_train_for_attack, x_train_predictions, values=values)
        inferred_test = attack.infer(x_test_for_attack, x_test_predictions, values=values)
        # check accuracy
        # train_acc
        _ = np.sum(inferred_train == x_train_feature.reshape(1, -1)) / len(inferred_train)
        # test_acc
        _ = np.sum(inferred_test == x_test_feature.reshape(1, -1)) / len(inferred_test)
        # assert train_acc == pytest.approx(0.5523, abs=0.03)
        # assert test_acc == pytest.approx(0.5777, abs=0.03)
    except ARTTestException as e:
        art_warning(e)
def test_black_box_with_model(get_tabular_classifier_list, get_iris_dataset):
    classifier_list = get_tabular_classifier_list(AttributeInferenceBlackBox)
    if not classifier_list:
        logging.warning("Couldn't perform  this test because no classifier is defined")
        return

    attack_feature = 2  # petal length

    # need to transform attacked feature into categorical
    def transform_feature(x):
        x[x > 0.5] = 2.0
        x[(x > 0.2) & (x <= 0.5)] = 1.0
        x[x <= 0.2] = 0.0

    values = [0.0, 1.0, 2.0]

    (x_train_iris, y_train_iris), (x_test_iris, y_test_iris) = get_iris_dataset
    # training data without attacked feature
    x_train_for_attack = np.delete(x_train_iris, attack_feature, 1)
    # only attacked feature
    x_train_feature = x_train_iris[:, attack_feature].copy().reshape(-1, 1)
    transform_feature(x_train_feature)
    # training data with attacked feature (after transformation)
    x_train = np.concatenate((x_train_for_attack[:, :attack_feature], x_train_feature), axis=1)
    x_train = np.concatenate((x_train, x_train_for_attack[:, attack_feature:]), axis=1)

    # test data without attacked feature
    x_test_for_attack = np.delete(x_test_iris, attack_feature, 1)
    # only attacked feature
    x_test_feature = x_test_iris[:, attack_feature].copy().reshape(-1, 1)
    transform_feature(x_test_feature)

    model = nn.Linear(4, 3)

    # Define a loss function and optimizer
    loss_fn = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.01)
    attack_model = PyTorchClassifier(
        model=model, clip_values=(0, 1), loss=loss_fn, optimizer=optimizer, input_shape=(4,), nb_classes=3
    )

    for classifier in classifier_list:
        if type(classifier).__name__ == "ScikitlearnDecisionTreeClassifier":
            attack = AttributeInferenceBlackBox(classifier, attack_model=attack_model, attack_feature=attack_feature)
            # get original model's predictions
            x_train_predictions = np.array([np.argmax(arr) for arr in classifier.predict(x_train_iris)]).reshape(-1, 1)
            x_test_predictions = np.array([np.argmax(arr) for arr in classifier.predict(x_test_iris)]).reshape(-1, 1)
            # train attack model
            attack.fit(x_train)
            # infer attacked feature
            inferred_train = attack.infer(x_train_for_attack, x_train_predictions, values=values)
            inferred_test = attack.infer(x_test_for_attack, x_test_predictions, values=values)
            # check accuracy
            train_acc = np.sum(inferred_train == x_train_feature.reshape(1, -1)) / len(inferred_train)
            test_acc = np.sum(inferred_test == x_test_feature.reshape(1, -1)) / len(inferred_test)
예제 #16
0
    def test_feature_vectors(self):
        # Define the network
        model = Model()
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)
        pixel_cnn = PyTorchClassifier(
            model=model, loss=loss_fn, optimizer=optimizer, input_shape=(4,), nb_classes=2, clip_values=(0, 1)
        )

        x = np.random.rand(5, 4).astype(np.float32)
        preprocess = PixelDefend(eps=5, pixel_cnn=pixel_cnn)
        x_defended, _ = preprocess(x)

        self.assertEqual(x_defended.shape, x.shape)
        self.assertTrue((x_defended <= 1.0).all())
        self.assertTrue((x_defended >= 0.0).all())
예제 #17
0
def test_pytorch_binary_pgd(art_warning, get_mnist_dataset):
    """
    This test instantiates a binary classification PyTorch model, then attacks it using PGD

    """
    class BasicModel(nn.Module):
        def __init__(self):
            super(BasicModel, self).__init__()
            self.layer_1 = nn.Linear(20, 32)
            self.layer_2 = nn.Linear(32, 1)

        def forward(self, x):
            x = F.relu(self.layer_1(x))
            x = torch.sigmoid(self.layer_2(x))

            return x

    try:
        device = "cpu"
        x, y = sklearn.datasets.make_classification(n_samples=10000,
                                                    n_features=20,
                                                    n_informative=5,
                                                    n_redundant=2,
                                                    n_repeated=0,
                                                    n_classes=2)
        train_x, test_x, train_y, test_y = sklearn.model_selection.train_test_split(
            x, y, test_size=0.2)
        train_x = test_x.astype(np.float32)
        train_y = train_y.astype(np.float32)
        test_x = test_x.astype(np.float32)
        model = BasicModel()
        loss_func = nn.BCELoss()
        model.to(device)
        opt = optim.Adam(model.parameters(), lr=0.001)
        classifier = PyTorchClassifier(
            model=model,
            loss=loss_func,
            optimizer=opt,
            input_shape=(1, 28, 28),
            nb_classes=2,
        )
        classifier.fit(train_x, train_y, batch_size=64, nb_epochs=3)
        test_x_batch = test_x[0:16]
        preds = classifier.predict(test_x_batch)
        attacker = ProjectedGradientDescent(classifier, eps=0.5)
        generated = attacker.generate(test_x_batch)
        adv_predicted = classifier.predict(generated)
        assert (adv_predicted != preds).all()
    except ARTTestException as e:
        art_warning(e)
예제 #18
0
    def _create_ptclassifier():
        """
        To create a simple PyTorchClassifier for testing.
        :return:
        """
        # Define the network
        model = Model()

        # Define a loss function and optimizer
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)

        # Get classifier
        ptc = PyTorchClassifier(model=model,
                                loss=loss_fn,
                                optimizer=optimizer,
                                input_shape=(1, 28, 28),
                                nb_classes=10,
                                clip_values=(0, 1))

        return ptc
예제 #19
0
    def test_one_channel(self):
        (x_train, _), (_, _), _, _ = load_mnist()
        x_train = x_train[:2, 10:15, 15:20, :]
        x_train = x_train.astype(np.float32)
        x_train_original = x_train.copy()

        # Define the network
        model = ModelImage()
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)
        self.pixelcnn = PyTorchClassifier(
            model=model, loss=loss_fn, optimizer=optimizer, input_shape=(1, 28, 28), nb_classes=10, clip_values=(0, 1)
        )
        preprocess = PixelDefend(eps=5, pixel_cnn=self.pixelcnn)
        x_defended, _ = preprocess(x_train)

        self.assertEqual(x_defended.shape, x_train.shape)
        self.assertTrue((x_defended <= 1.0).all())
        self.assertTrue((x_defended >= 0.0).all())

        # Check that x_train has not been modified by attack and classifier
        self.assertAlmostEqual(float(np.max(np.abs(x_train_original - x_train))), 0.0, delta=0.00001)
def test_loss_gradient_amp(
    art_warning,
    get_default_mnist_subset,
    image_dl_estimator,
    expected_values,
    mnist_shape,
    device_type,
):
    import torch
    import torch.nn as nn

    from art.estimators.classification.pytorch import PyTorchClassifier

    try:
        (expected_gradients_1, expected_gradients_2) = expected_values()

        (_, _), (x_test_mnist, y_test_mnist) = get_default_mnist_subset

        classifier, _ = image_dl_estimator(from_logits=True)
        optimizer = torch.optim.Adam(classifier.model.parameters(), lr=0.01)

        # Redefine the classifier with amp
        clip_values = (0, 1)
        criterion = nn.CrossEntropyLoss()
        classifier = PyTorchClassifier(
            clip_values=clip_values,
            model=classifier.model,
            preprocessing_defences=[],
            loss=criterion,
            input_shape=(1, 28, 28),
            nb_classes=10,
            device_type=device_type,
            optimizer=optimizer,
            use_amp=True,
            loss_scale=1.0,
        )

        # Compute loss gradients
        gradients = classifier.loss_gradient(x_test_mnist, y_test_mnist)

        # Test shape
        assert gradients.shape == (x_test_mnist.shape[0], ) + mnist_shape

        # First test of gradients
        sub_gradients = gradients[0, 0, :, 14]

        np.testing.assert_array_almost_equal(
            sub_gradients,
            expected_gradients_1,
            decimal=4,
        )

        # Second test of gradients
        sub_gradients = gradients[0, 0, 14, :]

        np.testing.assert_array_almost_equal(
            sub_gradients,
            expected_gradients_2,
            decimal=4,
        )

        # Compute loss gradients with framework
        gradients = classifier.loss_gradient_framework(
            torch.tensor(x_test_mnist).to(classifier.device),
            torch.tensor(y_test_mnist).to(classifier.device))
        gradients = gradients.cpu().numpy()

        # Test shape
        assert gradients.shape == (x_test_mnist.shape[0], ) + mnist_shape

        # First test of gradients
        sub_gradients = gradients[0, 0, :, 14]

        np.testing.assert_array_almost_equal(
            sub_gradients,
            expected_gradients_1,
            decimal=4,
        )

        # Second test of gradients
        sub_gradients = gradients[0, 0, 14, :]

        np.testing.assert_array_almost_equal(
            sub_gradients,
            expected_gradients_2,
            decimal=4,
        )

    except ARTTestException as e:
        art_warning(e)
    def test_pytorch_classifier(self):
        """
        Third test with the PyTorchClassifier.
        :return:
        """
        x_train = np.reshape(self.x_train_mnist,
                             (self.x_train_mnist.shape[0], 1, 28, 28)).astype(
                                 np.float32)

        # Build PyTorchClassifier
        victim_ptc = get_image_classifier_pt()

        class Model(nn.Module):
            """
            Create model for pytorch.
            """
            def __init__(self):
                super(Model, self).__init__()

                self.conv = nn.Conv2d(in_channels=1,
                                      out_channels=1,
                                      kernel_size=7)
                self.pool = nn.MaxPool2d(4, 4)
                self.fullyconnected = nn.Linear(25, 10)

            # pylint: disable=W0221
            # disable pylint because of API requirements for function
            def forward(self, x):
                """
                Forward function to evaluate the model

                :param x: Input to the model
                :return: Prediction of the model
                """
                x = self.conv(x)
                x = torch.nn.functional.relu(x)
                x = self.pool(x)
                x = x.reshape(-1, 25)
                x = self.fullyconnected(x)
                x = torch.nn.functional.softmax(x, dim=1)

                return x

        # Define the network
        model = Model()

        # Define a loss function and optimizer
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.01)

        # Get classifier
        thieved_ptc = PyTorchClassifier(model=model,
                                        loss=loss_fn,
                                        optimizer=optimizer,
                                        input_shape=(1, 28, 28),
                                        nb_classes=10,
                                        clip_values=(0, 1))

        # Create attack
        copycat_cnn = CopycatCNN(
            classifier=victim_ptc,
            batch_size_fit=self.batch_size,
            batch_size_query=self.batch_size,
            nb_epochs=NB_EPOCHS,
            nb_stolen=NB_STOLEN,
        )

        thieved_ptc = copycat_cnn.extract(x=x_train,
                                          thieved_classifier=thieved_ptc)
        victim_preds = np.argmax(victim_ptc.predict(x=x_train[:100]), axis=1)
        thieved_preds = np.argmax(thieved_ptc.predict(x=x_train[:100]), axis=1)

        acc = np.sum(victim_preds == thieved_preds) / len(victim_preds)

        self.assertGreater(acc, 0.3)
    def test_pytorch_iris(self):
        """
        Third test for PyTorch.
        :return:
        """
        # Build PyTorchClassifier
        victim_ptc = get_tabular_classifier_pt()

        class Model(nn.Module):
            """
            Create Iris model for PyTorch.
            """
            def __init__(self):
                super(Model, self).__init__()

                self.fully_connected1 = nn.Linear(4, 10)
                self.fully_connected2 = nn.Linear(10, 10)
                self.fully_connected3 = nn.Linear(10, 3)

            # pylint: disable=W0221
            # disable pylint because of API requirements for function
            def forward(self, x):
                x = self.fully_connected1(x)
                x = self.fully_connected2(x)
                logit_output = self.fully_connected3(x)

                return logit_output

        # Define the network
        model = Model()

        # Define a loss function and optimizer
        loss_fn = nn.CrossEntropyLoss()
        optimizer = optim.Adam(model.parameters(), lr=0.001)

        # Get classifier
        thieved_ptc = PyTorchClassifier(
            model=model,
            loss=loss_fn,
            optimizer=optimizer,
            input_shape=(4, ),
            nb_classes=3,
            clip_values=(0, 1),
            channels_first=True,
        )

        # Create attack
        copycat_cnn = CopycatCNN(
            classifier=victim_ptc,
            batch_size_fit=self.batch_size,
            batch_size_query=self.batch_size,
            nb_epochs=NB_EPOCHS,
            nb_stolen=NB_STOLEN,
        )
        thieved_ptc = copycat_cnn.extract(x=self.x_train_iris,
                                          thieved_classifier=thieved_ptc)

        victim_preds = np.argmax(victim_ptc.predict(x=self.x_train_iris[:100]),
                                 axis=1)
        thieved_preds = np.argmax(
            thieved_ptc.predict(x=self.x_train_iris[:100]), axis=1)
        acc = np.sum(victim_preds == thieved_preds) / len(victim_preds)

        self.assertGreater(acc, 0.3)
예제 #23
0
 def _predict_classifier(self, x: np.ndarray,
                         batch_size: int) -> np.ndarray:
     x = x.astype(ART_NUMPY_DTYPE)
     return PyTorchClassifier.predict(self, x=x, batch_size=batch_size)