Python:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.metrics import CategoricalAccuracy
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import keras_tuner as kt
# 1. Load and Pre‑process the Data
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(-1, 28, 28, 1).astype('float32') / 255.0
x_test = x_test.reshape(-1, 28, 28, 1).astype('float32') / 255.0
y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)
# 2. Define a Model Builder for Hyperparameter Tuning
def build_cnn_model(hp):
model = Sequential()
# Tune the number of filters in the first Conv2D layer
filters = hp.Int('filters', min_value=16, max_value=64, step=16)
model.add(Conv2D(filters, (3,3), activation='relu', input_shape=(28,28,1)))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Flatten())
# Tune the number of units in the Dense layer
dense_units = hp.Int('dense_units', min_value=32, max_value=128, step=32)
model.add(Dense(dense_units, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
return model
# 3. Hyperparameter Tuning using Keras Tuner (RandomSearch)
tuner = kt.RandomSearch(
build_cnn_model,
objective='val_accuracy',
max_trials=5,
executions_per_trial=1,
directory='cnn_tuning',
project_name='mnist_cnn'
)
tuner.search(x_train, y_train, epochs=5, batch_size=128, validation_split=0.2)
best_model = tuner.get_best_models(num_models=1)[0]
best_hp = tuner.get_best_hyperparameters(num_trials=1)[0]
print("Best hyperparameters:", best_hp.values)
# 4. Train Best Model and Evaluate
history = best_model.fit(x_train, y_train, epochs=5, batch_size=128, validation_split=0.2)
loss, accuracy = best_model.evaluate(x_test, y_test)
print("Test accuracy:", accuracy)
# Plot training vs. validation loss curves
plt.figure()
plt.plot(history.history['loss'], label='Train Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('CNN Training vs Validation Loss')
plt.legend()
plt.show()
# Display confusion matrix
y_pred = best_model.predict(x_test)
y_pred_labels = np.argmax(y_pred, axis=1)
y_true_labels = np.argmax(y_test, axis=1)
cm = confusion_matrix(y_true_labels, y_pred_labels)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=[str(i) for i in range(10)])
disp.plot(cmap=plt.cm.Blues)
plt.title("Confusion Matrix for MNIST CNN")
plt.show()
# 5. Visualize Hyperparameter Tuning Results
trials = tuner.oracle.get_best_trials(num_trials=len(tuner.oracle.trials))
filters_list = []
val_acc_list = []
for trial in trials:
filters_list.append(trial.hyperparameters.get('filters'))
val_acc_list.append(trial.metrics.get_last_value('val_accuracy'))
plt.figure()
sns.scatterplot(x=filters_list, y=val_acc_list, s=100, color='green')
plt.xlabel("Filters in First Conv Layer")
plt.ylabel("Validation Accuracy")
plt.title("Hyperparameter Tuning: Filters vs Validation Accuracy")
plt.grid(True)
plt.show()
R:
library(keras)
library(ggplot2)
library(dplyr)
# 1. Load and Pre‑process the Data
mnist <- dataset_mnist()
x_train <- mnist$train$x
y_train <- mnist$train$y
x_test <- mnist$test$x
y_test <- mnist$test$y
x_train <- array_reshape(x_train, c(nrow(x_train), 28, 28, 1)) / 255
x_test <- array_reshape(x_test, c(nrow(x_test), 28, 28, 1)) / 255
y_train <- to_categorical(y_train, 10)
y_test <- to_categorical(y_test, 10)
# 2. Hyperparameter Tuning: Loop over candidate filters in the first Conv layer
candidate_filters <- c(16, 32, 48, 64)
results <- data.frame(filters = candidate_filters, test_accuracy = NA)
for(i in seq_along(candidate_filters)){
model <- keras_model_sequential() %>%
layer_conv_2d(filters = candidate_filters[i], kernel_size = c(3,3), activation = 'relu', input_shape = c(28,28,1)) %>%
layer_max_pooling_2d(pool_size = c(2,2)) %>%
layer_flatten() %>%
layer_dense(units = 64, activation = 'relu') %>%
layer_dense(units = 10, activation = 'softmax')
model %>% compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = 'accuracy')
history <- model %>% fit(x_train, y_train, epochs = 5, batch_size = 128, validation_split = 0.2, verbose = 0)
scores <- model %>% evaluate(x_test, y_test, verbose = 0)
results$test_accuracy[i] <- scores[[2]]
cat("Filters:", candidate_filters[i], "Test Accuracy:", scores[[2]], "\n")
}
print(results)
# 3. Visualize Hyperparameter Tuning Results
ggplot(results, aes(x = filters, y = test_accuracy)) +
geom_line(color = "blue") +
geom_point(color = "red", size = 3) +
ggtitle("Hyperparameter Tuning: Filters vs Test Accuracy") +
xlab("Number of Filters in First Conv Layer") +
ylab("Test Accuracy")
# 4. Model Evaluation: Train best model (highest accuracy) and plot loss curves
best_filters <- results$filters[which.max(results$test_accuracy)]
best_model <- keras_model_sequential() %>%
layer_conv_2d(filters = best_filters, kernel_size = c(3,3), activation = 'relu', input_shape = c(28,28,1)) %>%
layer_max_pooling_2d(pool_size = c(2,2)) %>%
layer_flatten() %>%
layer_dense(units = 64, activation = 'relu') %>%
layer_dense(units = 10, activation = 'softmax')
best_model %>% compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = 'accuracy')
history <- best_model %>% fit(x_train, y_train, epochs = 5, batch_size = 128, validation_split = 0.2)
plot(1:length(history$metrics$loss), history$metrics$loss, type = 'l', col = 'blue',
ylim = range(c(history$metrics$loss, history$metrics$val_loss)),
xlab = "Epochs", ylab = "Loss", main = "Training vs Validation Loss")
lines(1:length(history$metrics$val_loss), history$metrics$val_loss, col = 'red')
legend("topright", legend = c("Train Loss", "Validation Loss"), col = c("blue", "red"), lty = 1)