In this exercise we will create class activation maps (CAMs) for predictions made by a model trained to classify magentic phases (see Exercise 7_1).
from tensorflow import keras
import numpy as np
callbacks = keras.callbacks
layers = keras.layers
print("keras", keras.__version__)
See https://doi.org/10.1038/nphys4035 for more information
import gdown
url = "https://drive.google.com/u/0/uc?export=download&confirm=HgGH&id=1Ihxt1hb3Kyv0IrjHlsYb9x9QY7l7n2Sl"
output = 'ising_data.npz'
gdown.download(url, output, quiet=True)
f = np.load(output)
n_train = 20000
x_train, x_test = f["C"][:n_train], f["C"][n_train:]
T_train, T_test = f["T"][:n_train], f["T"][n_train:]
Tc = 2.27
y_train = np.zeros_like(T_train)
y_train[T_train > Tc] = 1
y_train = keras.utils.to_categorical(y_train, 2)
y_test = np.zeros_like(T_test)
y_test[T_test > Tc] = 1
y_test = keras.utils.to_categorical(y_test, 2)
import matplotlib.pyplot as plt
for i,j in enumerate(np.random.choice(n_train, 6)):
plt.subplot(2,3,i+1)
image = x_train[j]
plot = plt.imshow(image)
plt.title("T: %.2f" % T_train[j])
plt.tight_layout()
plt.show()
Define a CNN for discriminative localization. Note that the CNN must use GlobalAveragePooling2D
after the convolutional part and must not feature more than a single fully-connected layer as output.
model = keras.models.Sequential()
model.add(layers.InputLayer(input_shape=(32, 32)))
model.add(layers.Reshape((32, 32,1)))
model.add(layers.Convolution2D(16, (3, 3), padding='same', activation='relu'))
model.add(layers.Convolution2D(16, (3, 3), padding='same', activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Convolution2D(32, (3, 3), padding='same', activation='relu'))
model.add(layers.Convolution2D(32, (3, 3), padding='same', activation='relu'))
model.add(layers.GlobalAveragePooling2D())
model.add(layers.Dropout(0.25))
model.add(layers.Dense(2, activation='softmax'))
model.summary()
model.compile(
loss='binary_crossentropy',
optimizer=keras.optimizers.Adam(0.001),
metrics=['accuracy'])
results = model.fit(x_train, y_train,
batch_size=64,
epochs=50,
verbose=2,
validation_split=0.1,
callbacks=[
callbacks.EarlyStopping(patience=5, verbose=1),
callbacks.ReduceLROnPlateau(factor=0.67, patience=2, verbose=1)]
)
plt.figure(1, (12, 4))
plt.subplot(1, 2, 1)
plt.plot(results.history['loss'])
plt.plot(results.history['val_loss'])
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='upper right')
plt.figure(1, (12, 4))
plt.subplot(1, 2, 1)
plt.plot(results.history['accuracy'])
plt.plot(results.history['val_accuracy'])
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='upper right')
Look at Exercise 8.1 to extract weights and feature maps from the trained network model.
First, extract the activations of the last convolutional layer.
conv = model.layers[-4] # last conv layer
Then, create the class activation maps by omitting the global average pooling operation and applying the weights of the single classification layer to the extracted activations.
Plot the CAMs for wrongly and correctly classified images.
Note, you can use interpolation='bilinear
in plt.imshow
to upsample the CAMs.