print("Execution time to fit 50 epochs: %s minutes" % ((end_time[0] - start_time[0])/60))
Execution time to fit 50 epochs: 5.340209325154622 minutes
nn_plot(hist[0], 50, loss=True, merge=False, binary=True)
nn_plot(hist[0], 50, acc=True, binary=True)
By analyzing the metrics, we can see that the model converges very fast and around epoch 20 it already reaches overfitting. Convolutional neural networks are used in complex problems, involving a big ammount of data. For this particular problem, the overfitting was due to the high number of layers and filters applied to a simple problem.
Before moving to our next analysis, we will show the weight kernels of the first convolutional layer. These kernels usually are called feature maps, and they highlight the main features extracted by the model for interpreting the input data. It does not have any logical or physical interpretation, but through the training process these are the best kernels the model found to express the input data peculiarities.
layer = model[-1].get_layer('conv2d')
kernels = []
for k in range(16):
kernel = []
for i in range(3):
for j in range(3):
kernel.append(layer.weights[0][i][j][0][k])
kernels.append(np.array(kernel).reshape(3, 3))
# Showing the 16 feature maps
rows = 4
cols = 4
axes = []
fig = plt.figure()
for a in range(rows*cols):
axes.append(fig.add_subplot(rows, cols, a+1))
img = plt.imshow(kernels[a], cmap=plt.cm.gray_r)
img.axes.get_xaxis().set_visible(False)
img.axes.get_yaxis().set_visible(False)
plt.tight_layout()
plt.show()
Our next step will be applying the same model structure, but to classify 3 digits: 2, 6 and 7, by changing parameters accordingly.
# Mask for digits 2, 6 and 7
ind = (y_train == 2) | (y_train == 6) | (y_train == 7)
x_train_small = x_train[ind]
y_train_small = y_train[ind]
y_train_small = tf.keras.utils.to_categorical(y_train_small)
y_train_small = y_train_small[:, [2, 6, 7]]
ind = (y_test == 2) | (y_test == 6) | (y_test == 7)
x_test_small = x_test[ind]
y_test_small = y_test[ind]
y_test_small = tf.keras.utils.to_categorical(y_test_small)
y_test_small = y_test_small[:, [2, 6, 7]]
print(f"x_train_small shape: {x_train_small.shape}")
x_train_small shape: (18141, 28, 28, 1)
model.append(tf.keras.models.Sequential([
tf.keras.layers.Conv2D(16, (3, 3), input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
tf.keras.layers.Conv2D(32, (3, 3)),
tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
tf.keras.layers.Conv2D(32, (3, 3)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(3, activation='softmax')
]))
params.append([tf.keras.losses.CategoricalCrossentropy(),
tf.keras.optimizers.Adam(),
tf.keras.metrics.CategoricalAccuracy()])
nn_compile(model[-1], params[-1])