Esempio n. 1
0
def classification_report_fgsm(model, testloader, device=None, fgsm_params={}):
    if device is not None:
        model.to(device)
    y_true = []
    y_pred = []
    for (images, labels) in testloader:
        if device is not None:
            images = images.to(device)
            labels = labels.to(device)
        attacked_images = fgsm(model,
                               nn.CrossEntropyLoss(),
                               images,
                               labels,
                               device=device,
                               **fgsm_params)
        y_true.append(labels)
        y_pred.append(model(attacked_images))
    y_true = torch.cat(y_true)
    y_pred = torch.cat(y_pred)
    y_pred = y_pred.argmax(dim=1)

    return cf(y_true.cpu().numpy(), y_pred.cpu().numpy())
Esempio n. 2
0
    def __init__(
        self,
        model,
        dataset,
        criterion=nn.CrossEntropyLoss(),
        n_clusters=100,
        method="kmcuda",
        cluster_with="original_data",
        epsilon=0.3,
        n_init=3,
        transform=None,
        device="cuda",
    ):
        # Initialise things
        super().__init__()
        self.model = model
        self.dataset = dataset
        self.criterion = criterion
        self.transform = transform

        # Create a k-Means instance and fit
        if cluster_with == "fgsm_perturb":
            dl = DataLoader(dataset, batch_size=64, shuffle=False)
            d = []
            for images, labels in iter(dl):
                y = (
                    fgsm_perturbs(
                        model,
                        criterion,
                        images,
                        labels,
                        epsilon=epsilon,
                        device=device,
                    )
                    .detach()
                    .cpu()
                    .reshape(len(images), -1)
                    .numpy()
                )
                d.append(y)
            d = np.concatenate(d)
        elif cluster_with == "fgsm_input":
            dl = DataLoader(dataset, batch_size=64, shuffle=False)
            d = []
            for images, labels in iter(dl):
                y = (
                    fgsm(model, criterion, images, labels, device=device)
                    .detach()
                    .cpu()
                    .reshape(len(images), -1)
                    .numpy()
                )
                d.append(y)
            d = np.concatenate(d)
        elif cluster_with == "pgd_perturb":
            dl = DataLoader(dataset, batch_size=64, shuffle=False)
            d = []
            for images, labels in iter(dl):
                y = (
                    pgd_perturbs(
                        model,
                        criterion,
                        images,
                        labels,
                        epsilon=epsilon,
                        device=device,
                    )
                    .detach()
                    .cpu()
                    .reshape(len(images), -1)
                    .numpy()
                )
                d.append(y)
            d = np.concatenate(d)
        elif cluster_with == "pgd_input":
            dl = DataLoader(dataset, batch_size=64, shuffle=False)
            d = []
            for images, labels in iter(dl):
                y = (
                    pgd(model, criterion, images, labels, device=device)
                    .detach()
                    .cpu()
                    .reshape(len(images), -1)
                    .numpy()
                )
                d.append(y)
            d = np.concatenate(d)
        elif cluster_with == "original_data":
            d = self.dataset.data.reshape(len(dataset), -1)
            if type(d) is not np.ndarray:
                d = d.detach().cpu().numpy()
        else:
            raise NotImplementedError
        self.km = KMeansWrapper(d, n_clusters, n_init, method)
        # Obtain targets and ids of each cluster centres
        self.cluster_ids = self.km.y_pred.astype(int)
        self.cluster_centers_idx = self.km.centroids_idxs.astype(int)

        # Extract only interested ones
        X = []
        y = []
        for i in self.cluster_centers_idx:
            x, u = self.dataset[i]
            X.append(x)
            y.append(u)

        # To be used in PGD
        self.centroids_X = torch.stack(X)
        self.centroids_y = torch.Tensor(
            y, device=self.centroids_X.device
        ).long()
Esempio n. 3
0
 def test_fgsm_range(self):
     result = fgsm(mnist_cnn, nn.CrossEntropyLoss(), batch_X, batch_y)
     self.assertTrue(((result >= -1) & (result <= 1)).all())
Esempio n. 4
0
def fgsm_training(
    model,
    trainloader,
    n_epoches=10,
    epsilon=0.3,
    random=False,
    alpha=0.375,
    criterion=nn.CrossEntropyLoss(),
    optimizer=optim.Adam,
    optimizer_params={},
    device=None,
    log=None,
):
    """Standard FGSM Adversarial Training

    Parameters
    ----------
    model: torch.nn.model
        The model to be reinforced
    trainloader: torch.utils.data.DataLoader
        The DataLoader for the training set
    n_epoches: int
        The epoches to be trained
    epsilon: float
        Perturbation bound
    criterion: function
        Criterion function
    optimizer: class of torch.optim
        Optimiser to train the model
    optimizer_params: dict
        Parameters to be passed to the optimiser
    device: torch.device, str, or None
        Device to be used
    log: logger or None
        If logger, logs to the corresponding logger
    """

    # Move to device if desired
    if device is not None:
        model.to(device)
    # Log starting time if desired
    if log is not None:
        log.info(f"Training started: {get_time()}")
        log.info(
            "n_epoches,move_time,fgsm_time,forward_time,backprop_time,training_loss"
        )

    # Create an optimiser instance
    optimizer = optimizer(model.parameters(), **optimizer_params)

    # Iterate over e times of epoches
    for e in range(n_epoches):
        fgsm_time = relativedelta()
        move_time = relativedelta()
        forward_time = relativedelta()
        backprop_time = relativedelta()
        # Running loss, for reference
        running_loss = 0
        # Iterate over minibatches of trainloader
        for i, (images, labels) in enumerate(trainloader):
            # Move tensors to device if desired
            move_timestamp = datetime.now()
            if device is not None:
                images = images.to(device)
                labels = labels.to(device)
            # Calculate perturbations
            fgsm_timestamp = datetime.now()
            adver_images = fgsm(
                model,
                criterion,
                images,
                labels,
                epsilon,
                random,
                alpha,
                device=device,
            )
            optimizer.zero_grad()

            forward_timestamp = datetime.now()
            output = model(adver_images)
            backprop_timestamp = datetime.now()
            loss = criterion(output, labels)
            loss.backward()
            optimizer.step()
            finish_timestamp = datetime.now()

            running_loss += loss.item()

            move_time += relativedelta(fgsm_timestamp, move_timestamp)
            fgsm_time += relativedelta(forward_timestamp, fgsm_timestamp)
            forward_time += relativedelta(backprop_timestamp,
                                          forward_timestamp)
            backprop_time += relativedelta(finish_timestamp,
                                           backprop_timestamp)
        else:
            if log is not None:
                log.info(f"{e},\
{delta_tostr(move_time)},\
{delta_tostr(fgsm_time)},\
{delta_tostr(forward_time)},\
{delta_tostr(backprop_time)},\
{running_loss/len(trainloader)}")
    if log is not None:
        log.info(f"Training ended: {get_time()}")
    return model
Esempio n. 5
0
 def test_fgsm_shape(self):
     result = fgsm(mnist_cnn, nn.CrossEntropyLoss(), batch_X, batch_y)
     self.assertTupleEqual(result.shape, batch_X.shape)