keras.applications
provides models that have pretrained weights
In [32]:
%matplotlib inline
import matplotlib.pyplot as plt
import foolbox
import keras
import numpy as np
from keras.applications import resnet50
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.applications.imagenet_utils import decode_predictions
In [121]:
# instantiate model
keras.backend.set_learning_phase(0)
kmodel = resnet50.ResNet50(weights='imagenet')
preprocessing = (np.array([104, 116, 123]), 1) # The values here are the values of ImageNet pictures
fmodel = foolbox.models.KerasModel(kmodel, bounds=(0, 255), preprocessing=preprocessing)
In [122]:
from PIL import Image
label = 285 # 285 is "Egyptian Cat" in ImageNet
# Printout the image. By default, resnet50 expects (224, 224)
def read_testimage(path, shape=(224, 224), data_format='channels_last'):
image = Image.open(path)
image = image.resize(shape)
image = np.asarray(image, dtype=np.float32)
image = image[:, :, :3]
assert image.shape == shape + (3,)
if data_format == 'channels_first':
image = np.transpose(image, (2, 0, 1))
return image
# Predict the image with Keras
def predict_image_label(img, pretrained_model):
image_batch = np.expand_dims(img, axis=0)
# prepare the image for the RestNet50 model
processed_image = resnet50.preprocess_input(image_batch.copy())
# get the predicted probabilities for each class
predictions = pretrained_model.predict(processed_image)
# convert the probabilities to class labels
# We will get top 5 predictions which is the default
label = decode_predictions(predictions)
return label
In [123]:
# get source image and label
image = read_testimage('baby_cat.png')
plt.figure()
plt.title('Original')
plt.imshow(image / 255) # division by 255 to convert [0, 255] to [0, 1]
Out[123]:
In [124]:
print(image.shape)
In [7]:
# apply attack on source image
# ::-1 reverses the color channels, because Keras ResNet50 expects BGR instead of RGB
attack = foolbox.attacks.SaliencyMapAttack(fmodel)
adversarial= attack(image[:, :, ::-1], label) # if the attack fails, adversarial will be None
image[:, ::-1, :]
, it will change the second channel, it will reverse the image horienticallyimage[::-1, :, :]
, it will change the first channel, it will reverse the image vertically
In [126]:
plt.figure()
plt.subplot(1, 3, 1)
plt.title('Original')
plt.imshow(image / 255) # division by 255 to convert [0, 255] to [0, 1]
plt.axis('off')
plt.subplot(1, 3, 2)
plt.title('Adversarial')
plt.imshow(adversarial[:, :, ::-1] / 255) # ::-1 to convert BGR to RGB
plt.axis('off')
plt.subplot(1, 3, 3)
plt.title('Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(difference)
plt.axis('off')
plt.show()
In [127]:
# Because adversarial didin't happen, nothing changed
difference[7:9]
Out[127]:
In [129]:
# Let's see why it gets misclassified
original_labels = predict_image_label(image, kmodel)
print original_labels
In [130]:
original_top_pred = original_labels[0][0]
plt.title('Predicted as:' + original_top_pred[1] + ', ' + str(original_top_pred[2]), fontsize=20)
plt.imshow(image / 255)
plt.axis('off')
Out[130]:
In [131]:
# get source image and label
image = read_testimage('baby_cat2.png')
plt.figure()
plt.title('Original')
plt.imshow(image / 255)
Out[131]:
In [132]:
# Gradient based attack
# This is GradientSignAttack
# it will adds the sign of the gradient to the image, gradually increasing the magnitude until the image is misclassified.
attack = foolbox.attacks.FGSM(fmodel)
adversarial= attack(image[:, :, ::-1], label)
In [133]:
plt.figure()
plt.subplot(1, 5, 1)
plt.title('Original')
plt.imshow(image / 255) # division by 255 to convert [0, 255] to [0, 1]
plt.axis('off')
plt.subplot(1, 5, 2)
plt.title('Adversarial')
plt.imshow(adversarial[:, :, ::-1] / 255) # ::-1 to convert BGR to RGB
plt.axis('off')
plt.subplot(1, 5, 3)
plt.title('Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(abs(difference))
plt.axis('off')
plt.subplot(1, 5, 5)
plt.title('Enlarged Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(difference / abs(difference).max() * 0.2 + 0.5)
plt.axis('off')
plt.show()
In [134]:
difference[7:9] # At least this time it does classified as "Egyptian cat"
Out[134]:
In [135]:
original_labels = predict_image_label(image, kmodel)
print original_labels
adversarial_labels = predict_image_label(adversarial[:, :, ::-1], kmodel)
print adversarial_labels
In [144]:
plt.figure()
plt.subplot(1, 7, 1)
original_top_pred = original_labels[0][0]
plt.title('Original Prediction:' + original_top_pred[1], fontsize=10)
plt.imshow(image / 255)
plt.axis('off')
plt.subplot(1, 7, 7)
adv_top_pred = adversarial_labels[0][0]
plt.title('Adversarial Prediction:' + adv_top_pred[1], fontsize=10)
plt.imshow(image / 255)
plt.axis('off')
plt.show()
In [145]:
# Decision based attack
# This is BlendedUniformNoiseAttack
# It will blend the image with a uniform noise image until it is misclassified.
attack = foolbox.attacks.BlendedUniformNoiseAttack(fmodel)
adversarial= attack(image[:, :, ::-1], label)
In [146]:
plt.figure()
plt.subplot(1, 5, 1)
plt.title('Original')
plt.imshow(image / 255) # division by 255 to convert [0, 255] to [0, 1]
plt.axis('off')
plt.subplot(1, 5, 2)
plt.title('Adversarial')
plt.imshow(adversarial[:, :, ::-1] / 255) # ::-1 to convert BGR to RGB
plt.axis('off')
plt.subplot(1, 5, 3)
plt.title('Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(abs(difference))
plt.axis('off')
plt.subplot(1, 5, 5)
plt.title('Enlarged Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(difference / abs(difference).max() * 0.2 + 0.5)
plt.axis('off')
plt.show()
In [147]:
# But still, got predicted right...
original_labels = predict_image_label(image, kmodel)
print original_labels
adversarial_labels = predict_image_label(adversarial[:, :, ::-1], kmodel)
print adversarial_labels
In [148]:
plt.figure()
plt.subplot(1, 7, 1)
original_top_pred = original_labels[0][0]
plt.title('Original Prediction:' + original_top_pred[1], fontsize=10)
plt.imshow(image / 255)
plt.axis('off')
plt.subplot(1, 7, 7)
adv_top_pred = adversarial_labels[0][0]
plt.title('Adversarial Prediction:' + adv_top_pred[1], fontsize=10)
plt.imshow(image / 255)
plt.axis('off')
plt.show()
In [149]:
# Decision based attack
# This is GaussianBlurAttack
# It will blur the image until it is misclassified.
attack = foolbox.attacks.GaussianBlurAttack(fmodel)
adversarial= attack(image[:, :, ::-1], label)
In [150]:
plt.figure()
plt.subplot(1, 5, 1)
plt.title('Original')
plt.imshow(image / 255) # division by 255 to convert [0, 255] to [0, 1]
plt.axis('off')
plt.subplot(1, 5, 2)
plt.title('Adversarial')
plt.imshow(adversarial[:, :, ::-1] / 255) # ::-1 to convert BGR to RGB
plt.axis('off')
plt.subplot(1, 5, 3)
plt.title('Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(abs(difference))
plt.axis('off')
plt.subplot(1, 5, 5)
plt.title('Enlarged Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(difference / abs(difference).max() * 0.2 + 0.5)
plt.axis('off')
plt.show()
In [152]:
# But still, got predicted right...
original_labels = predict_image_label(image, kmodel)
print original_labels
adversarial_labels = predict_image_label(adversarial[:, :, ::-1], kmodel)
print adversarial_labels
In [153]:
plt.figure()
plt.subplot(1, 7, 1)
original_top_pred = original_labels[0][0]
plt.title('Original Prediction:' + original_top_pred[1], fontsize=10)
plt.imshow(image / 255)
plt.axis('off')
plt.subplot(1, 7, 7)
adv_top_pred = adversarial_labels[0][0]
plt.title('Adversarial Prediction:' + adv_top_pred[1], fontsize=10)
plt.imshow(image / 255)
plt.axis('off')
plt.show()
In [154]:
# This is a typical "Egyptian Cat" from ImageNet
image = read_testimage('cat.png')
plt.figure()
plt.title('Original')
plt.imshow(image / 255)
Out[154]:
In [155]:
attack = foolbox.attacks.BlendedUniformNoiseAttack(fmodel)
adversarial= attack(image[:, :, ::-1], label)
In [156]:
plt.figure()
plt.subplot(1, 5, 1)
plt.title('Original')
plt.imshow(image / 255) # division by 255 to convert [0, 255] to [0, 1]
plt.axis('off')
plt.subplot(1, 5, 2)
plt.title('Adversarial')
plt.imshow(adversarial[:, :, ::-1] / 255) # ::-1 to convert BGR to RGB
plt.axis('off')
plt.subplot(1, 5, 3)
plt.title('Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(abs(difference))
plt.axis('off')
plt.subplot(1, 5, 5)
plt.title('Enlarged Difference')
difference = adversarial[:, :, ::-1] - image
plt.imshow(difference / abs(difference).max() * 0.2 + 0.5)
plt.axis('off')
plt.show()
In [157]:
# But still, got predicted right...
original_labels = predict_image_label(image, kmodel)
print original_labels
adversarial_labels = predict_image_label(adversarial[:, :, ::-1], kmodel)
print adversarial_labels
In [158]:
plt.figure()
plt.subplot(1, 7, 1)
original_top_pred = original_labels[0][0]
plt.title('Original Prediction:' + original_top_pred[1], fontsize=10)
plt.imshow(image / 255)
plt.axis('off')
plt.subplot(1, 7, 7)
adv_top_pred = adversarial_labels[0][0]
plt.title('Adversarial Prediction:' + adv_top_pred[1], fontsize=10)
plt.imshow(image / 255)
plt.axis('off')
plt.show()
Attacks in Foobox: https://foolbox.readthedocs.io/en/latest/modules/attacks.html
I have also tried to wrong the same code on Mac and Windows, very weird, my windows has the latest Tensorflow, twice larger RAM and much much more memory, it was slower than my mac... and finally exactly same code will simply give error on my windows. There maybe bugs in Tensorflow.