Esempio n. 1
0
def main(seed=0, n_epochs=5, batch_size=100, time=50, update_interval=50, plot=False):

    np.random.seed(seed)

    if torch.cuda.is_available():
        torch.set_default_tensor_type('torch.cuda.FloatTensor')
        torch.cuda.manual_seed_all(seed)
    else:
        torch.manual_seed(seed)

    print()
    print('Creating and training the ANN...')
    print()

    # Create and train an ANN on the MNIST dataset.
    ANN = FullyConnectedNetwork()

    # Get the MNIST data.
    images, labels = MNIST('../../data/MNIST', download=True).get_train()
    images /= images.max()  # Standardizing to [0, 1].
    images = images.view(-1, 784)
    labels = labels.long()

    # Specify optimizer and loss function.
    optimizer = optim.Adam(params=ANN.parameters(), lr=1e-3)
    criterion = nn.CrossEntropyLoss()

    # Train the ANN.
    batches_per_epoch = int(images.size(0) / batch_size)
    for i in range(n_epochs):
        losses = []
        accuracies = []
        for j in range(batches_per_epoch):
            batch_idxs = torch.from_numpy(
                np.random.choice(np.arange(images.size(0)), size=batch_size, replace=False)
            )
            im_batch = images[batch_idxs]
            label_batch = labels[batch_idxs]

            outputs = ANN.forward(im_batch)
            loss = criterion(outputs, label_batch)
            predictions = torch.max(outputs, 1)[1]
            correct = (label_batch == predictions).sum().float() / batch_size

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            losses.append(loss.item())
            accuracies.append(correct.item())

        print(f'Epoch: {i+1} / {n_epochs}; Loss: {np.mean(losses):.4f}; Accuracy: {np.mean(accuracies) * 100:.4f}')

    print()
    print('Converting ANN to SNN...')

    # Do ANN to SNN conversion.
    SNN = ann_to_snn(ANN, input_shape=(784,), data=images)

    for l in SNN.layers:
        if l != 'Input':
            SNN.add_monitor(
                Monitor(SNN.layers[l], state_vars=['s', 'v'], time=time), name=l
            )

    spike_ims = None
    spike_axes = None
    correct = []

    print()
    print('Testing SNN on MNIST data...')
    print()

    # Test SNN on MNIST data.
    start = t()
    for i in range(images.size(0)):
        if i > 0 and i % update_interval == 0:
            print(
                f'Progress: {i} / {images.size(0)}; Elapsed: {t() - start:.4f}; Accuracy: {np.mean(correct) * 100:.4f}'
            )
            start = t()

        SNN.run(inpts={'Input': images[i].repeat(time, 1, 1)}, time=time)

        spikes = {layer: SNN.monitors[layer].get('s') for layer in SNN.monitors}
        voltages = {layer: SNN.monitors[layer].get('v') for layer in SNN.monitors}
        prediction = torch.softmax(voltages['5'].sum(1), 0).argmax()
        correct.append((prediction == labels[i]).item())

        SNN.reset_()

        if plot:
            spikes = {k: spikes[k].cpu() for k in spikes}
            spike_ims, spike_axes = plot_spikes(spikes, ims=spike_ims, axes=spike_axes)
            plt.pause(1e-3)
def main(seed=0,
         n_epochs=5,
         batch_size=100,
         time=50,
         update_interval=50,
         plot=False,
         save=True):

    np.random.seed(seed)

    if torch.cuda.is_available():
        torch.set_default_tensor_type('torch.cuda.FloatTensor')
        torch.cuda.manual_seed_all(seed)
    else:
        torch.manual_seed(seed)

    print()
    print('Loading MNIST data...')
    print()

    # Get the CIFAR-10 data.
    images, labels = MNIST('../../data/MNIST', download=True).get_train()
    images /= images.max()  # Standardizing to [0, 1].
    images = images.view(-1, 784)
    labels = labels.long()

    test_images, test_labels = MNIST('../../data/MNIST',
                                     download=True).get_test()
    test_images /= test_images.max()  # Standardizing to [0, 1].
    test_images = test_images.view(-1, 784)
    test_labels = test_labels.long()

    if torch.cuda.is_available():
        images = images.cuda()
        labels = labels.cuda()
        test_images = test_images.cuda()
        test_labels = test_labels.cuda()

    ANN = FullyConnectedNetwork()

    model_name = '_'.join(
        [str(x) for x in [seed, n_epochs, batch_size, time, update_interval]])

    # Specify loss function.
    criterion = nn.CrossEntropyLoss()
    if save and os.path.isfile(os.path.join(params_path, model_name + '.pt')):
        print()
        print('Loading trained ANN from disk...')
        ANN.load_state_dict(
            torch.load(os.path.join(params_path, model_name + '.pt')))

        if torch.cuda.is_available():
            ANN = ANN.cuda()
    else:
        print()
        print('Creating and training the ANN...')
        print()

        # Specify optimizer.
        optimizer = optim.Adam(params=ANN.parameters(),
                               lr=1e-3,
                               weight_decay=1e-4)

        batches_per_epoch = int(images.size(0) / batch_size)

        # Train the ANN.
        for i in range(n_epochs):
            losses = []
            accuracies = []
            for j in range(batches_per_epoch):
                batch_idxs = torch.from_numpy(
                    np.random.choice(np.arange(images.size(0)),
                                     size=batch_size,
                                     replace=False))
                im_batch = images[batch_idxs]
                label_batch = labels[batch_idxs]

                outputs = ANN.forward(im_batch)
                loss = criterion(outputs, label_batch)
                predictions = torch.max(outputs, 1)[1]
                correct = (label_batch
                           == predictions).sum().float() / batch_size

                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

                losses.append(loss.item())
                accuracies.append(correct.item() * 100)

            outputs = ANN.forward(test_images)
            loss = criterion(outputs, test_labels).item()
            predictions = torch.max(outputs, 1)[1]
            test_accuracy = ((test_labels == predictions).sum().float() /
                             test_labels.numel()).item() * 100

            avg_loss = np.mean(losses)
            avg_acc = np.mean(accuracies)

            print(
                f'Epoch: {i+1} / {n_epochs}; Train Loss: {avg_loss:.4f}; Train Accuracy: {avg_acc:.4f}'
            )
            print(
                f'\tTest Loss: {loss:.4f}; Test Accuracy: {test_accuracy:.4f}')

        if save:
            torch.save(ANN.state_dict(),
                       os.path.join(params_path, model_name + '.pt'))

    outputs = ANN.forward(test_images)
    loss = criterion(outputs, test_labels)
    predictions = torch.max(outputs, 1)[1]
    accuracy = ((test_labels == predictions).sum().float() /
                test_labels.numel()).item() * 100

    print()
    print(
        f'(Post training) Test Loss: {loss:.4f}; Test Accuracy: {accuracy:.4f}'
    )

    print()
    print('Evaluating ANN on adversarial examples from FSGM method...')

    # Convert pytorch model to a tf_model and wrap it in cleverhans.
    tf_model_fn = convert_pytorch_model_to_tf(ANN)
    cleverhans_model = CallableModelWrapper(tf_model_fn, output_layer='logits')

    sess = tf.Session()
    x_op = tf.placeholder(tf.float32, shape=(
        None,
        784,
    ))

    # Create an FGSM attack.
    fgsm_op = FastGradientMethod(cleverhans_model, sess=sess)
    fgsm_params = {'eps': 0.2, 'clip_min': 0.0, 'clip_max': 1.0}
    adv_x_op = fgsm_op.generate(x_op, **fgsm_params)
    adv_preds_op = tf_model_fn(adv_x_op)

    # Run an evaluation of our model against FGSM white-box attack.
    total = 0
    correct = 0
    adv_preds = sess.run(adv_preds_op, feed_dict={x_op: test_images})
    correct += (np.argmax(adv_preds, axis=1) == test_labels).sum()
    total += len(test_images)
    accuracy = float(correct) / total

    print()
    print('Adversarial accuracy: {:.3f}'.format(accuracy * 100))

    print()
    print('Converting ANN to SNN...')

    with sess.as_default():
        test_images = adv_x_op.eval(feed_dict={x_op: test_images})

    test_images = torch.tensor(test_images)

    # Do ANN to SNN conversion.
    SNN = ann_to_snn(ANN,
                     input_shape=(784, ),
                     data=test_images,
                     percentile=100)

    for l in SNN.layers:
        if l != 'Input':
            SNN.add_monitor(Monitor(SNN.layers[l],
                                    state_vars=['s', 'v'],
                                    time=time),
                            name=l)

    print()
    print('Testing SNN on FGSM-modified MNIST data...')
    print()

    # Test SNN on MNIST data.
    spike_ims = None
    spike_axes = None
    correct = []

    n_images = test_images.size(0)

    start = t()
    for i in range(n_images):
        if i > 0 and i % update_interval == 0:
            accuracy = np.mean(correct) * 100
            print(
                f'Progress: {i} / {n_images}; Elapsed: {t() - start:.4f}; Accuracy: {accuracy:.4f}'
            )
            start = t()

        SNN.run(inpts={'Input': test_images[i].repeat(time, 1, 1)}, time=time)

        spikes = {
            layer: SNN.monitors[layer].get('s')
            for layer in SNN.monitors
        }
        voltages = {
            layer: SNN.monitors[layer].get('v')
            for layer in SNN.monitors
        }
        prediction = torch.softmax(voltages['fc3'].sum(1), 0).argmax()
        correct.append((prediction == test_labels[i]).item())

        SNN.reset_()

        if plot:
            spikes = {k: spikes[k].cpu() for k in spikes}
            spike_ims, spike_axes = plot_spikes(spikes,
                                                ims=spike_ims,
                                                axes=spike_axes)
            plt.pause(1e-3)
Esempio n. 3
0
def main(seed=0, n_epochs=5, batch_size=100):

    np.random.seed(seed)

    if torch.cuda.is_available():
        torch.set_default_tensor_type('torch.cuda.FloatTensor')
        torch.cuda.manual_seed_all(seed)
    else:
        torch.manual_seed(seed)

    print()
    print('Creating and training the ANN...')
    print()

    # Create and train an ANN on the MNIST dataset.
    ANN = FullyConnectedNetwork()

    # Get the MNIST data.
    images, labels = MNIST(os.path.join(
        ROOT_DIR, 'data', 'MNIST'
    ), download=True).get_train()

    images /= images.max()  # Standardizing to [0, 1].
    images = images.view(-1, 784)
    labels = labels.long()

    # Specify optimizer and loss function.
    optimizer = optim.Adam(params=ANN.parameters(), lr=1e-3)
    criterion = nn.CrossEntropyLoss()

    # Train the ANN.
    batches_per_epoch = int(images.size(0) / batch_size)
    for i in range(n_epochs):
        losses = []
        accuracies = []
        for j in range(batches_per_epoch):
            batch_idxs = torch.from_numpy(
                np.random.choice(np.arange(images.size(0)), size=batch_size, replace=False)
            )
            im_batch = images[batch_idxs]
            label_batch = labels[batch_idxs]

            outputs = ANN.forward(im_batch)
            loss = criterion(outputs, label_batch)
            predictions = torch.max(outputs, 1)[1]
            correct = (label_batch == predictions).sum().float() / batch_size

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

            losses.append(loss.item())
            accuracies.append(correct.item())

        print(f'Epoch: {i+1} / {n_epochs}; Loss: {np.mean(losses):.4f}; Accuracy: {np.mean(accuracies) * 100:.4f}')

    ANN = ANN.eval()

    fmodel = PyTorchModel(
        ANN, bounds=(0, 1), num_classes=10
    )

    # apply attack on source image
    for i in range(10000):
        image = images[i].cpu().numpy()
        label = labels[i].long().item()

        attack = foolbox.attacks.BoundaryAttack(fmodel)
        try:
            adversarial = attack(image, label, verbose=True, iterations=1000) * 1.001
        except AssertionError:
            continue

        print(f'{i}: adversarial')