"""
The script demonstrates a simple example of using ART with Keras. The example train a small model on the MNIST dataset
and creates adversarial examples using the Fast Gradient Sign Method. Here we use the ART classifier to train the model,
it would also be possible to provide a pretrained model to the ART classifier.
The parameters are chosen for reduced computational requirements of the script and not optimised for accuracy.
"""
import tensorflow as tf

tf.compat.v1.disable_eager_execution()
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D
from tensorflow.keras.losses import categorical_crossentropy
from tensorflow.keras.optimizers import Adam
import numpy as np

from art.attacks.evasion import FastGradientMethod
from art.estimators.classification import KerasClassifier
from art.utils import load_mnist

# Step 1: Load the MNIST dataset

(x_train, y_train), (x_test, y_test), min_pixel_value, max_pixel_value = load_mnist()

# Step 2: Create the model

model = Sequential()
model.add(Conv2D(filters=4, kernel_size=(5, 5), strides=1, activation="relu", input_shape=(28, 28, 1)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(filters=10, kernel_size=(5, 5), strides=1, activation="relu", input_shape=(23, 23, 4)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(100, activation="relu"))
model.add(Dense(10, activation="softmax"))

model.compile(loss=categorical_crossentropy, optimizer=Adam(learning_rate=0.01), metrics=["accuracy"])

# Step 3: Create the ART classifier

classifier = KerasClassifier(model=model, clip_values=(min_pixel_value, max_pixel_value), use_logits=False)

# Step 4: Train the ART classifier

classifier.fit(x_train, y_train, batch_size=64, nb_epochs=3)

# Step 5: Evaluate the ART classifier on benign test examples

predictions = classifier.predict(x_test)
accuracy = np.sum(np.argmax(predictions, axis=1) == np.argmax(y_test, axis=1)) / len(y_test)
print("Accuracy on benign test examples: {}%".format(accuracy * 100))

# Step 6: Generate adversarial test examples
attack = FastGradientMethod(estimator=classifier, eps=0.2)
x_test_adv = attack.generate(x=x_test)

# Step 7: Evaluate the ART classifier on adversarial test examples

predictions = classifier.predict(x_test_adv)
accuracy = np.sum(np.argmax(predictions, axis=1) == np.argmax(y_test, axis=1)) / len(y_test)
print("Accuracy on adversarial test examples: {}%".format(accuracy * 100))

tensorflow.keras.layers.Dense tensorflow.keras.layers.Conv2D tensorflow.keras.optimizers.Adam numpy.argmax tensorflow.compat.v1.disable_eager_execution tensorflow.keras.layers.MaxPooling2D tensorflow.keras.models.Sequential tensorflow.keras.layers.Flatten
[(9, 'tensorflow.compat.v1.disable_eager_execution', 'tf.compat.v1.disable_eager_execution', ([], {}), True, 'import tensorflow as tf\n'), (22, 'art.utils.load_mnist', 'load_mnist', ([], {}), False, 'from art.utils import load_mnist\n'), (26, 'tensorflow.keras.models.Sequential', 'Sequential', ([], {}), False, 'from tensorflow.keras.models import Sequential\n'), (39, 'art.estimators.classification.KerasClassifier', 'KerasClassifier', ([], {'model': 'model', 'clip_values': '(min_pixel_value, max_pixel_value)', 'use_logits': '(False)'}), False, 'from art.estimators.classification import KerasClassifier\n'), (52, 'art.attacks.evasion.FastGradientMethod', 'FastGradientMethod', ([], {'estimator': 'classifier', 'eps': '(0.2)'}), False, 'from art.attacks.evasion import FastGradientMethod\n'), (27, 'tensorflow.keras.layers.Conv2D', 'Conv2D', ([], {'filters': '(4)', 'kernel_size': '(5, 5)', 'strides': '(1)', 'activation': '"""relu"""', 'input_shape': '(28, 28, 1)'}), False, 'from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D\n'), (28, 'tensorflow.keras.layers.MaxPooling2D', 'MaxPooling2D', ([], {'pool_size': '(2, 2)'}), False, 'from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D\n'), (29, 'tensorflow.keras.layers.Conv2D', 'Conv2D', ([], {'filters': '(10)', 'kernel_size': '(5, 5)', 'strides': '(1)', 'activation': '"""relu"""', 'input_shape': '(23, 23, 4)'}), False, 'from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D\n'), (30, 'tensorflow.keras.layers.MaxPooling2D', 'MaxPooling2D', ([], {'pool_size': '(2, 2)'}), False, 'from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D\n'), (31, 'tensorflow.keras.layers.Flatten', 'Flatten', ([], {}), False, 'from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D\n'), (32, 'tensorflow.keras.layers.Dense', 'Dense', (['(100)'], {'activation': '"""relu"""'}), False, 'from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D\n'), (33, 'tensorflow.keras.layers.Dense', 'Dense', (['(10)'], {'activation': '"""softmax"""'}), False, 'from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D\n'), (35, 'tensorflow.keras.optimizers.Adam', 'Adam', ([], {'learning_rate': '(0.01)'}), False, 'from tensorflow.keras.optimizers import Adam\n'), (48, 'numpy.argmax', 'np.argmax', (['predictions'], {'axis': '(1)'}), True, 'import numpy as np\n'), (48, 'numpy.argmax', 'np.argmax', (['y_test'], {'axis': '(1)'}), True, 'import numpy as np\n'), (58, 'numpy.argmax', 'np.argmax', (['predictions'], {'axis': '(1)'}), True, 'import numpy as np\n'), (58, 'numpy.argmax', 'np.argmax', (['y_test'], {'axis': '(1)'}), True, 'import numpy as np\n')]