You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1820 lines
341 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "70feec04",
"metadata": {},
"source": [
"# Development of a Modular Python Library from Scratch for Automated ROI Segmentation in Thermal Images"
]
},
{
"cell_type": "markdown",
"id": "bf5eee54",
"metadata": {},
"source": [
"# Module 4: Convolutional Neural Network (CNN)"
]
},
{
"cell_type": "markdown",
"id": "9c077baa",
"metadata": {},
"source": [
"Author: Sofia Samaniego Lopez\n",
"\n",
"Institution: Universidad Autonoma de Baja California (UABC)\n",
"\n",
"Advisor: Dr. Gerardo Marx Chavez Campos"
]
},
{
"cell_type": "markdown",
"id": "7392c17c",
"metadata": {},
"source": [
"This notebook presents **Module 4**, focusing on the development of a custom **Convolutional Neural Network (CNN)**. \n",
"\n",
"To ensure full mathematical transparency and eliminate black-box dependencies, the entire network—including 2D convolutions, dense layers, and backpropagation—is programmed entirely from scratch using pure **NumPy** matrix operations. \n",
"\n",
"The architecture is first optimized and validated using the standard **MNIST** dataset. It is then stress-tested for robustness against diffuse edges and spatial complexity using **Corrupted MNIST** and **Fashion MNIST**. Finally, the model is benchmarked against a **TensorFlow** equivalent. This comparison not only validates the accuracy of the custom implementation but also demonstrates its superior low-latency inference for single images, proving its efficiency for future hardware deployment."
]
},
{
"cell_type": "code",
"execution_count": 50,
"id": "09af087c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: numpy in .\\.venv\\Lib\\site-packages (2.4.6)\n",
"Requirement already satisfied: scipy in .\\.venv\\Lib\\site-packages (1.17.1)\n",
"Requirement already satisfied: numpy<2.7,>=1.26.4 in .\\.venv\\Lib\\site-packages (from scipy) (2.4.6)\n",
"Requirement already satisfied: matplotlib in .\\.venv\\Lib\\site-packages (3.11.1)\n",
"Requirement already satisfied: contourpy>=1.0.1 in .\\.venv\\Lib\\site-packages (from matplotlib) (1.3.3)\n",
"Requirement already satisfied: cycler>=0.10 in .\\.venv\\Lib\\site-packages (from matplotlib) (0.12.1)\n",
"Requirement already satisfied: fonttools>=4.28.2 in .\\.venv\\Lib\\site-packages (from matplotlib) (4.63.0)\n",
"Requirement already satisfied: kiwisolver>=1.3.1 in .\\.venv\\Lib\\site-packages (from matplotlib) (1.5.0)\n",
"Requirement already satisfied: numpy>=1.25 in .\\.venv\\Lib\\site-packages (from matplotlib) (2.4.6)\n",
"Requirement already satisfied: packaging>=20.0 in .\\.venv\\Lib\\site-packages (from matplotlib) (26.2)\n",
"Requirement already satisfied: pillow>=9 in .\\.venv\\Lib\\site-packages (from matplotlib) (12.3.0)\n",
"Requirement already satisfied: pyparsing>=3 in .\\.venv\\Lib\\site-packages (from matplotlib) (3.3.2)\n",
"Requirement already satisfied: python-dateutil>=2.7 in .\\.venv\\Lib\\site-packages (from matplotlib) (2.9.0.post0)\n",
"Requirement already satisfied: six>=1.5 in .\\.venv\\Lib\\site-packages (from python-dateutil>=2.7->matplotlib) (1.17.0)\n",
"Requirement already satisfied: pip in .\\.venv\\Lib\\site-packages (26.2.1)\n",
"Requirement already satisfied: tensorflow in .\\.venv\\Lib\\site-packages (2.21.0)\n",
"Requirement already satisfied: absl-py>=1.0.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (2.5.0)\n",
"Requirement already satisfied: astunparse>=1.6.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (1.6.3)\n",
"Requirement already satisfied: flatbuffers>=25.9.23 in .\\.venv\\Lib\\site-packages (from tensorflow) (25.12.19)\n",
"Requirement already satisfied: gast!=0.5.0,!=0.5.1,!=0.5.2,>=0.2.1 in .\\.venv\\Lib\\site-packages (from tensorflow) (0.7.0)\n",
"Requirement already satisfied: google_pasta>=0.1.1 in .\\.venv\\Lib\\site-packages (from tensorflow) (0.2.0)\n",
"Requirement already satisfied: libclang>=13.0.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (18.1.1)\n",
"Requirement already satisfied: opt_einsum>=2.3.2 in .\\.venv\\Lib\\site-packages (from tensorflow) (3.4.0)\n",
"Requirement already satisfied: packaging in .\\.venv\\Lib\\site-packages (from tensorflow) (26.2)\n",
"Requirement already satisfied: protobuf<8.0.0,>=6.31.1 in .\\.venv\\Lib\\site-packages (from tensorflow) (7.35.1)\n",
"Requirement already satisfied: requests<3,>=2.21.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (2.34.2)\n",
"Requirement already satisfied: setuptools in .\\.venv\\Lib\\site-packages (from tensorflow) (65.5.0)\n",
"Requirement already satisfied: six>=1.12.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (1.17.0)\n",
"Requirement already satisfied: termcolor>=1.1.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (3.3.0)\n",
"Requirement already satisfied: typing_extensions>=3.6.6 in .\\.venv\\Lib\\site-packages (from tensorflow) (4.16.0)\n",
"Requirement already satisfied: wrapt>=1.11.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (2.2.2)\n",
"Requirement already satisfied: grpcio<2.0,>=1.24.3 in .\\.venv\\Lib\\site-packages (from tensorflow) (1.82.1)\n",
"Requirement already satisfied: keras>=3.12.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (3.15.0)\n",
"Requirement already satisfied: numpy>=1.26.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (2.4.6)\n",
"Requirement already satisfied: h5py<3.15.0,>=3.11.0 in .\\.venv\\Lib\\site-packages (from tensorflow) (3.14.0)\n",
"Requirement already satisfied: ml_dtypes<1.0.0,>=0.5.1 in .\\.venv\\Lib\\site-packages (from tensorflow) (0.5.4)\n",
"Requirement already satisfied: charset_normalizer<4,>=2 in .\\.venv\\Lib\\site-packages (from requests<3,>=2.21.0->tensorflow) (3.4.9)\n",
"Requirement already satisfied: idna<4,>=2.5 in .\\.venv\\Lib\\site-packages (from requests<3,>=2.21.0->tensorflow) (3.18)\n",
"Requirement already satisfied: urllib3<3,>=1.26 in .\\.venv\\Lib\\site-packages (from requests<3,>=2.21.0->tensorflow) (2.7.0)\n",
"Requirement already satisfied: certifi>=2023.5.7 in .\\.venv\\Lib\\site-packages (from requests<3,>=2.21.0->tensorflow) (2026.6.17)\n",
"Requirement already satisfied: wheel<1.0,>=0.23.0 in .\\.venv\\Lib\\site-packages (from astunparse>=1.6.0->tensorflow) (0.47.0)\n",
"Requirement already satisfied: rich in .\\.venv\\Lib\\site-packages (from keras>=3.12.0->tensorflow) (15.0.0)\n",
"Requirement already satisfied: namex in .\\.venv\\Lib\\site-packages (from keras>=3.12.0->tensorflow) (0.1.0)\n",
"Requirement already satisfied: optree in .\\.venv\\Lib\\site-packages (from keras>=3.12.0->tensorflow) (0.19.1)\n",
"Requirement already satisfied: markdown-it-py>=2.2.0 in .\\.venv\\Lib\\site-packages (from rich->keras>=3.12.0->tensorflow) (4.2.0)\n",
"Requirement already satisfied: pygments<3.0.0,>=2.13.0 in .\\.venv\\Lib\\site-packages (from rich->keras>=3.12.0->tensorflow) (2.20.0)\n",
"Requirement already satisfied: mdurl~=0.1 in .\\.venv\\Lib\\site-packages (from markdown-it-py>=2.2.0->rich->keras>=3.12.0->tensorflow) (0.1.2)\n",
"Requirement already satisfied: tensorflow.keras in .\\.venv\\Lib\\site-packages (0.1)\n",
"Requirement already satisfied: seaborn in .\\.venv\\Lib\\site-packages (0.13.2)\n",
"Requirement already satisfied: numpy!=1.24.0,>=1.20 in .\\.venv\\Lib\\site-packages (from seaborn) (2.4.6)\n",
"Requirement already satisfied: pandas>=1.2 in .\\.venv\\Lib\\site-packages (from seaborn) (3.0.5)\n",
"Requirement already satisfied: matplotlib!=3.6.1,>=3.4 in .\\.venv\\Lib\\site-packages (from seaborn) (3.11.1)\n",
"Requirement already satisfied: contourpy>=1.0.1 in .\\.venv\\Lib\\site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (1.3.3)\n",
"Requirement already satisfied: cycler>=0.10 in .\\.venv\\Lib\\site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (0.12.1)\n",
"Requirement already satisfied: fonttools>=4.28.2 in .\\.venv\\Lib\\site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (4.63.0)\n",
"Requirement already satisfied: kiwisolver>=1.3.1 in .\\.venv\\Lib\\site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (1.5.0)\n",
"Requirement already satisfied: packaging>=20.0 in .\\.venv\\Lib\\site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (26.2)\n",
"Requirement already satisfied: pillow>=9 in .\\.venv\\Lib\\site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (12.3.0)\n",
"Requirement already satisfied: pyparsing>=3 in .\\.venv\\Lib\\site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (3.3.2)\n",
"Requirement already satisfied: python-dateutil>=2.7 in .\\.venv\\Lib\\site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (2.9.0.post0)\n",
"Requirement already satisfied: tzdata in .\\.venv\\Lib\\site-packages (from pandas>=1.2->seaborn) (2026.3)\n",
"Requirement already satisfied: six>=1.5 in .\\.venv\\Lib\\site-packages (from python-dateutil>=2.7->matplotlib!=3.6.1,>=3.4->seaborn) (1.17.0)\n",
"Requirement already satisfied: scikit-learn in .\\.venv\\Lib\\site-packages (1.9.0)\n",
"Requirement already satisfied: numpy>=1.24.1 in .\\.venv\\Lib\\site-packages (from scikit-learn) (2.4.6)\n",
"Requirement already satisfied: scipy>=1.10.0 in .\\.venv\\Lib\\site-packages (from scikit-learn) (1.17.1)\n",
"Requirement already satisfied: joblib>=1.4.0 in .\\.venv\\Lib\\site-packages (from scikit-learn) (1.5.3)\n",
"Requirement already satisfied: narwhals>=2.0.1 in .\\.venv\\Lib\\site-packages (from scikit-learn) (2.24.0)\n",
"Requirement already satisfied: threadpoolctl>=3.5.0 in .\\.venv\\Lib\\site-packages (from scikit-learn) (3.6.0)\n"
]
}
],
"source": [
"!pip3 install numpy\n",
"!pip3 install scipy\n",
"!pip3 install matplotlib\n",
"!python -m pip install --upgrade pip\n",
"!pip3 install tensorflow\n",
"!pip3 install tensorflow.keras\n",
"!pip3 install seaborn\n",
"!pip3 install scikit-learn"
]
},
{
"cell_type": "markdown",
"id": "3a143d1c",
"metadata": {},
"source": [
"## 1. Mathematical Foundations & Core Architecture\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "ed7527d2",
"metadata": {},
"source": [
"### 1.1 Base Layer & Core Libraries\n",
"Implementation of the fundamental algorithmic building blocks using pure matrix operations via NumPy. This section establishes the base classes to ensure complete mathematical transparency, avoiding black-box commercial dependencies and allowing absolute control over tensor flows and gradient updates."
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "6642c93f",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from scipy import signal\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# 1. Base Layer\n",
"class Layer:\n",
" def __init__(self):\n",
" self.input = None\n",
" self.output = None\n",
"\n",
" def forward(self, input):\n",
" # Computes the output of the layer for a given input\n",
" pass\n",
"\n",
" def backward(self, output_gradient, learning_rate):\n",
" # Computes the derivative of the error with respect to the input\n",
" # Updates layer parameters (if any)\n",
" pass"
]
},
{
"cell_type": "markdown",
"id": "64e8357c",
"metadata": {},
"source": [
"### 1.2 The Layers (Convolutional, Dense & Reshape)\n",
"Here, the specific neural network layers are programmed analytically from scratch:\n",
"* **Convolutional:** Native coding of the 2D discrete convolution to extract local features without destroying the spatial topography of the matrices.\n",
"* **Dense:** Fully connected layers to interpret the extracted features.\n",
"* **Reshape:** Dimensional formatting to transition from 3D convolutional feature maps to a 1D column vector for the dense layers."
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "c9f43305",
"metadata": {},
"outputs": [],
"source": [
"# 2. Convolutional Layer (Updated Initialization)\n",
"class Convolutional(Layer):\n",
" def __init__(self, input_shape, kernel_size, depth):\n",
" input_depth, input_height, input_width = input_shape\n",
" self.depth = depth\n",
" self.input_shape = input_shape\n",
" self.input_depth = input_depth\n",
" self.output_shape = (depth, input_height - kernel_size + 1, input_width - kernel_size + 1)\n",
" self.kernels_shape = (depth, input_depth, kernel_size, kernel_size)\n",
" \n",
" # FIX: Scale down the initial random kernels to prevent exploding values\n",
" self.kernels = np.random.randn(*self.kernels_shape) * 0.1\n",
" self.biases = np.random.randn(*self.output_shape) * 0.1\n",
"\n",
" def forward(self, input):\n",
" self.input = input\n",
" self.output = np.copy(self.biases)\n",
" for i in range(self.depth):\n",
" for j in range(self.input_depth):\n",
" self.output[i] += signal.correlate2d(self.input[j], self.kernels[i, j], \"valid\")\n",
" return self.output\n",
"\n",
" def backward(self, output_gradient, learning_rate):\n",
" kernels_gradient = np.zeros(self.kernels_shape)\n",
" input_gradient = np.zeros(self.input_shape)\n",
"\n",
" for i in range(self.depth):\n",
" for j in range(self.input_depth):\n",
" kernels_gradient[i, j] = signal.correlate2d(self.input[j], output_gradient[i], \"valid\")\n",
" input_gradient[j] += signal.convolve2d(output_gradient[i], self.kernels[i, j], \"full\")\n",
"\n",
" self.kernels -= learning_rate * kernels_gradient\n",
" self.biases -= learning_rate * output_gradient\n",
" return input_gradient\n",
"\n",
"# 3. Dense (Fully Connected) Layer (Updated Xavier Initialization)\n",
"class Dense(Layer):\n",
" def __init__(self, input_size, output_size):\n",
" # FIX: Xavier Initialization (divide by the square root of the input size)\n",
" # This keeps the variance of the outputs equal to the variance of the inputs\n",
" self.weights = np.random.randn(output_size, input_size) * np.sqrt(1.0 / input_size)\n",
" self.bias = np.random.randn(output_size, 1) * np.sqrt(1.0 / input_size)\n",
"\n",
" def forward(self, input):\n",
" self.input = input\n",
" # Matrix multiplication for the feedforward stage\n",
" return np.dot(self.weights, self.input) + self.bias\n",
"\n",
" def backward(self, output_gradient, learning_rate):\n",
" # Chain rule calculations for dense connections\n",
" weights_gradient = np.dot(output_gradient, self.input.T)\n",
" input_gradient = np.dot(self.weights.T, output_gradient)\n",
" \n",
" # Update parameters\n",
" self.weights -= learning_rate * weights_gradient\n",
" self.bias -= learning_rate * output_gradient\n",
" return input_gradient\n",
"\n",
"# 4. Reshape Layer (Flattening)\n",
"class Reshape(Layer):\n",
" def __init__(self, input_shape, output_shape):\n",
" self.input_shape = input_shape\n",
" self.output_shape = output_shape\n",
"\n",
" def forward(self, input):\n",
" # Flattens the multi-dimensional array into a 1D column vector\n",
" return np.reshape(input, self.output_shape)\n",
"\n",
" def backward(self, output_gradient, learning_rate):\n",
" # Restores the original dimensional shape for backpropagation\n",
" return np.reshape(output_gradient, self.input_shape)"
]
},
{
"cell_type": "markdown",
"id": "e476cdd1",
"metadata": {},
"source": [
"### 1.3 Activations"
]
},
{
"cell_type": "code",
"execution_count": 53,
"id": "6a79e23e",
"metadata": {},
"outputs": [],
"source": [
"# 5. Base Activation Layer\n",
"class Activation(Layer):\n",
" def __init__(self, activation, activation_prime):\n",
" self.activation = activation\n",
" self.activation_prime = activation_prime\n",
"\n",
" def forward(self, input):\n",
" self.input = input\n",
" return self.activation(self.input)\n",
"\n",
" def backward(self, output_gradient, learning_rate):\n",
" # Element-wise multiplication with the derivative of the activation function\n",
" return np.multiply(output_gradient, self.activation_prime(self.input))\n",
"\n",
"# 6. Sigmoid Activation\n",
"class Sigmoid(Activation):\n",
" def __init__(self):\n",
" def sigmoid(x):\n",
" return 1 / (1 + np.exp(-x))\n",
" \n",
" def sigmoid_prime(x):\n",
" s = sigmoid(x)\n",
" return s * (1 - s)\n",
" \n",
" super().__init__(sigmoid, sigmoid_prime)"
]
},
{
"cell_type": "markdown",
"id": "a438c569",
"metadata": {},
"source": [
"### 1.4 Loss Functions"
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "541a14eb",
"metadata": {},
"outputs": [],
"source": [
"# 7. Mean Squared Error (Loss Function)\n",
"def mse(y_true, y_pred):\n",
" return np.mean(np.power(y_true - y_pred, 2))\n",
"\n",
"def mse_prime(y_true, y_pred):\n",
" # Derivative of the MSE with respect to the predicted output\n",
" return 2 * (y_pred - y_true) / np.size(y_true)"
]
},
{
"cell_type": "markdown",
"id": "12f3e83f",
"metadata": {},
"source": [
"## 2. Data Preparation (Standard MNIST)"
]
},
{
"cell_type": "markdown",
"id": "bc393dfa",
"metadata": {},
"source": [
"Loading and formatting the raw standard MNIST dataset. To preserve the spatial topography required for the 2D convolutional filters, the flat 784-pixel arrays are reshaped into native 2D matrices (1, 28, 28). Additionally, pixel intensities and target vectors are normalized to a $[0.01, 0.99]$ range to prevent zero-gradient issues and neuron saturation during backpropagation."
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "bf612e66",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading and formatting training data...\n",
"Successfully loaded 49999 training samples.\n"
]
}
],
"source": [
"\n",
"# 8. Data Loading and Preprocessing for CNN\n",
"print(\"Loading and formatting training data...\")\n",
"\n",
"# Open and read the training dataset\n",
"with open(\"mnist_train.csv\", \"r\") as f:\n",
" train_data = f.readlines()\n",
"\n",
"x_train = []\n",
"y_train = []\n",
"\n",
"for record in train_data:\n",
" values = record.split(\",\")\n",
" \n",
" # 1. Image Reshaping: From 784 flat pixels to (1, 28, 28) for 2D Convolutions\n",
" img = np.asarray(values[1:], dtype=float).reshape(1, 28, 28) / 255.0 * 0.99 + 0.01\n",
" x_train.append(img)\n",
" \n",
" # 2. Target Vector: One-hot encoded column vector (10, 1)\n",
" target = np.zeros((10, 1)) + 0.01\n",
" target[int(values[0])] = 0.99\n",
" y_train.append(target)\n",
"\n",
"print(f\"Successfully loaded {len(x_train)} training samples.\")"
]
},
{
"cell_type": "markdown",
"id": "4983eb12",
"metadata": {},
"source": [
"## 3. Hyperparameter Optimization & Empirical Tuning\n",
"Empirical evaluation of the Learning Rate and the Dense Layer's capacity across the complete dataset. Evaluating the network over the full dataset guarantees true statistical convergence and avoids sampling bias."
]
},
{
"cell_type": "code",
"execution_count": 56,
"id": "feb792e5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Starting CNN Learning Rate sweep. This will take some time due to 2D convolutions...\n",
"Training CNN with Learning Rate: 0.01...\n",
"CNN Performance for LR 0.01: 0.2069\n",
"\n",
"Training CNN with Learning Rate: 0.1...\n",
"CNN Performance for LR 0.1: 0.8986\n",
"\n",
"Training CNN with Learning Rate: 0.2...\n",
"CNN Performance for LR 0.2: 0.9074\n",
"\n",
"Training CNN with Learning Rate: 0.3...\n",
"CNN Performance for LR 0.3: 0.9202\n",
"\n",
"Training CNN with Learning Rate: 0.6...\n",
"CNN Performance for LR 0.6: 0.8649\n",
"\n",
"Training CNN with Learning Rate: 0.9...\n",
"CNN Performance for LR 0.9: 0.8794\n",
"\n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAr4AAAHVCAYAAAAXXPhxAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjExLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvctoD+AAAAAlwSFlzAAAPYQAAD2EBqD+naQAAYLFJREFUeJzt3Qd4FOXWwPGTEBIIIYUAoYUaWhARBBRFmqDoFRV74aqIqCgqYuXDhg1FRfGqV6/YUVDs2BWUooJU6TX0ElpISAghZb/nvDDrJtkkm80m2/6/55lnd2d3ZmdmJ9mz75z3vCE2m80mAAAAQIAL9fYGAAAAAFWBwBcAAABBgcAXAAAAQYHAFwAAAEGBwBcAAABBgcAXAAAAQYHAFwAAAEGBwBcAAABBgcAXgE/Zvn27DBs2TLp27Srt2rWTv/76y9ubhCDx3XffmXNuw4YN3t4UAJWEwBfwsqVLl8rdd98tvXr1kk6dOsk555wjI0aMkDlz5hR63WWXXWa+lO+4445i6zhy5Ih57sknn6zwMs5Y69Gpffv20rlzZzPv888/F0/SgSQvvPBCWbdunbz++uvy5ZdfykknneTR90DlGzlypF9+bhkZGebcy8nJ8cr7z5s3z/53plNycrL07NlT7rnnHvOD0F033nij+XsFQOALeI0GefqFpi2baWlp8uCDD8oHH3wg9913n+Tl5Unfvn3l+eeft79+y5Yt5kv51VdfNcGyo4KCAvPcnj17Cs13ZxlndD2HDx82gegXX3whL7/8stSsWVMuvfRSeeSRR8RT9Mt92bJl5ovaavGNjIz02PpRNXbs2CFr1671u8P9r3/9S9asWSNt2rTxyvtnZmaav8khQ4aYv7VPPvlEbr/9dvn000/Nj81t27a5tV5dTv+GAYiEcRAA7xg/frxMnDhR3nrrLRPoORowYID58vv7778LzW/WrJlpqdXg+JdffnHpfdxZxpnq1aubQFTprbZErVixQp599lmz7tq1a0tFWUF4dHR0hdcFlJeew9Y57k0NGjSwb4e2nMfFxcl5550n//nPf+S5557z9uYBfo1UB8ALDh06JE8//bT06dOnWNBr6d27t2ntcRQVFSWPPvqozJw5U77//nuX3sudZVwREhIi3bt3l2PHjtlbk9LT0+Wpp54y+3XyySfLBRdcIJ999lmh5SZNmmS+1HNzc03LsaZ4nHHGGXLXXXfJFVdcYV6j9/U1559/fqHW4FGjRslpp51mWr+uueYa+eOPP1xatxo8eLAMHz5c9u3bZ1JJTj31VLn44otl+fLl5vnU1FRzvHW+ppvMnj272D5rC73jZeizzjpLxowZI/v37y/0Ouu99HPWfdF1agv+Rx995PRYaiufpgecfvrp5pjedtttxVrotAVV5+vzuv833HCDrFq1qtTPSF9/5plnmtb9oh5//HGTWpOVlWUep6SkmJQY/UGj73H99ddXen71N998Yy7Bn3LKKdKjRw956KGHzDFzpMfOOuYdO3aUgQMHyhtvvCH5+fn21+hnp89/+OGHsnjxYrn88svNa3/66Sf5+OOPzXM7d+6UqVOnms+hS5cu5nMp+l7OcnzLs7zaunWr+ez1M+rfv7+5QrJkyRKzjt9++82t46Tvp9avX19o/sMPP1zofNTPWn+EOl7FOffcc+XPP/8054r1Wj2mjjZt2mQ+e/3b0s9Cf3QXvUIEBAwbgCo3ffp0m/75TZo0yeVlTj31VFuHDh1subm5ttatW9s6duxoy8/PN88dPnzYrO/222+v8DIlvXezZs2KzT///PPNOnbu3Gnbs2ePLSkpydamTRvbtGnTbAsXLrS98MILtho1atiefPJJ+zJjx441y9x99922xx57zPbHH3/YHnzwQbMOXc46LmvWrLGlpKSYZdauXWuLj4+3de7c2fbNN9/Y5syZYxsyZIgtNDTU9uGHH5a5btWpUydb3759bRdccIHtk08+Mc9deOGFZr2bNm2y9e/f37z/n3/+aRs8eLDZ7m3bthXaX91G3S6d/v77b7MePaY6HT161P46fa9+/frZLrroIrN9CxYssI0cOdJsm26/o2+//da81znnnGObMWOG7a+//rL997//tXXv3t3+mh9++MFWs2ZNs76ffvrJNm/ePNvQoUNtkZGRZj9KYh3P77//vtD8Y8eO2erVq2e7/PLLzeN9+/bZEhISbOedd55t5syZtsWLF9umTJli69Gjhzn25aXbWa1atVJfc99999nCw8NtDz/8sDnmehz0801OTrZlZGTYX7du3Tr7MddzSs+N2rVr20aPHm1/zfbt281+Dh8+3OyDHi/9G9P91mOpzz3wwAO2e+65xxwvPS76ueu54Gjq1KnmtStWrLDPK8/yuh16HE8++WTzWc6dO9c2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2yv5+QUSE1VTGtaN4TABAAD4euCr1RxWrVoln3zyiXk8d+5ceeGFF0wg/PTTT3t6GwMyv5eKDgAAAH6Q6vD111/LrFmzpG3btubxGWecIT179pR27drJI488ImPGjPH0dgYE8nsBAAD8rMV3165d0rp1a3NfUx3S0tLM/d69e8vKlSs9u4UBWsMXAAAAftK5LTT0eMysrbxffvmlDBs2TH755RepW7duudazb98+mTZtmqSmpkrHjh3lsssuk2rVqpX4+s8++0z+/PPPQvMaNmwo99xzj/hNi29LAl8AAAC/aPG1UhyswSxGjBghTZo0kUsvvbRcAeimTZtMsKuBc35+vkmROP/88839kvz888/y008/SYMGDexTfHy8+LrcvHxZvy3V3E9uSUUHAAAAv2jxXbt2rf3+xRdfLCtWrJCFCxea1t+uXbu6vB5ryGMNZrUFWStFtGnTxrQAX3vttSUup6+59957xZ9s3L7XBL9RkRGSmEDlCwAAAL+r42u1ADu2ArtCa/9+++23MnHiRHvaRPPmzU2esLYAlxb4pqSkmE50MTExctZZZ0n37t3FX9Ic2jenogMAAIBfBb4auG7dutXesc2RK62+uuzRo0elVatWhebr46I5vI60DJh2qFOrV6+WsWPHyq233iovvfRSicvk5OSYybEOsbUPVTX88spNO81tu+YJDPkMAABQhsqI0dwKfOfMmWNaZHfs2OH0eZvNVuY6jhw5Ym6jo6MLzddW3KysrBKXu//++6VFixb2x1dffbUMGDBALrzwQunXr5/TZcaPHy/jxo0rNn/p0qVSq1YtqQq/L15lbqOr58uiRYuq5D0BAAD8VVYp8WCVBr6ai3v55ZfLnXfe6fbwxFFRUeb20KFDhebrY6tF1xnHoFf179/fdKzTQTRKCny109zo0aMLtfgmJiZK586diwXelWXPSz+Z23N6dZOuXU+qkvcEAADwVxknrtB7PfDdvHmzPP744/bg1R1NmzY1ra3r1q2TgQMHFuo41759+3I3hTumMhQVERFhpqLCwsLMVNnyHCo6dExqUiXvCQAA4M/CKiFecqucmZYgW7NmTYXeWGv1XnLJJfLee+/Zg1Yd/GLevHmmNdkyffp0MxyyFeDq84502OQ9e/aYdAdftXnXfsk5lic1I6pLs4Z1vL05AAAAQcmtUFo7kumAFZrqoJ3R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AICPCsoWXwAAAAQfAl8AAAAEBQJfAAAABIWArOOracurV6+WvLw86dChg4SFhVXKMr7G3X3QZQ4dOiRnnHGG+CN39vvIkSOyfv16qVevnjRu3FiCZb9zc3Nl3bp1pqNAixYtguo8V1u2bJEdO3bISSedJLGxsRLI+71o0SI5evRooXlNmjSR5s2bSzB83ocPH5YNGzZIs2bNJD4+XvxNefZbB3VYvny50+fat2/vV/vvzuet53lKSopZpmXLlhIVFSX+xt393rhxo6lxq59zSEiI+KPV5YxBKhyv2QLMunXrbO3atbPVr1/flpiYaGvcuLHtjz/+8Pgyvsadffjwww9t3bp1s8XFxdkiIiJs/qi8+71nzx7b0KFDbTExMbZTTjnFVqdOHVuPHj1smzZtsgX65/3YY4+Z13fq1MnWpEkTs8yMGTNs/qQif6upqam2Ro0aaWde2/fff28L9P1u1qyZLSkpyXbmmWfap1deecUW6Pudn59vGzNmjC0yMtKc63oc7r33Xlsg7/fy5csLfc466Wev5/rs2bNtgfx5v/vuu+b/eJs2bWwnnXSSrVatWrbx48fb/Ik7+/3GG2+Y77Hk5GRb06ZNzfJr1qyx+ZMP3YhBPBGvBVzg27lzZ9ugQYNseXl55vEtt9xivuyys7M9uoyvcWcfHn74Ydv8+fNtb775pt8GvuXd74ULF9reeecdW25urnmcmZlp69evnwl+A3m/9XXPPvus2V9VUFBgu//++01wcPToUZu/cPdvVfd34MCBtgceeMAvA1939lsDPv3b9mfu7PdDDz1ki4+PN8Gg9dm/+uqrNn/iie+k6667ztayZUuz/4G632lpabZq1arZnnvuOfu8adOmmb9x6/MP1O+x0NBQ29SpU81j/YxHjRplgmD94ecvHnYjBvHE30ZABb5LliwxJ7weSMv27dttISEhti+++MJjy/iaiu6Dvwa+nvrstMVA/4lYwXCw7Pd3331n1qOt4IG+3xr0DxgwwLZr1y6/C3zd3W8NfJ955hnzJekvn3FF9/vQoUO2mjVr2iZOnGjzV574+05PTzc/ap9++mlbIO+3XqnTZebNm1doGZ03a9YsW6Du94QJE0wrt6P169f7XQt/eWMQT333BVTntqVLl5rbLl26FMppa9iwof05TyzjawJhH7y53wsXLjR5gP6S71qR/d68ebPMnTtXpk2bJvfdd5/ceeedkpCQIIG833/99Ze8+OKL8u677/plDlxFPu+nnnpKbrrpJmnVqpX06tXL5EEG8n7/8ccfkp2dLYMGDZJdu3aZ12n+a7D9X5s6daocO3ZMbrjhBgnk/dZ83ptvvllGjx4tX375pXz33XcybNgwueCCC6R3794SqPtdp04dyczMLHRu79y509wuXrxYAtVSD33nB1Tge/DgQYmOjpbq1asXmq+J/fqcp5bxNYGwD97a799++03eeOMNefjhhyUY9nvGjBnywAMPmC8K7RBx7bXXSiDvt34xXH311fLaa69Jo0aNxB+5+3nraEcHDhyQZcuWydatW828yy+/XPLz8yVQ91uDXf1x8+qrr0rXrl1N4Kc/7PScD6b/a2+99ZYJ/jQgCPT9Hjp0qGRlZZkf8jqtWbNGbr/9dvP/LVD3+9JLL5X69evL4MGD5ZtvvjE/dEaOHCk1a9bkO98F/nFmuEhPnKK9mJW2AISHh3tsGV8TCPvgjf3WX8YXX3yx3HXXXeafZzDst7bwaquYtg7oP89+/fqZYCFQ9/vBBx80Aa9W75g3b55p/VWrVq2SlStXSiB/3npOW1+m+iX69NNPy5IlS0w1k0D+f64pfLt375Zt27bJ33//LTNnzpSJEyfKxx9/LMHwf23FihXmKtbw4cPFn7iz3/qDrm/fvnLLLbeYCh76d/3KK6+YoH/BggUSqPutFWm0asupp55qfuR9/vnnMnnyZKlRo4YJfgNVdQ/FOgEV+Orlar28s3//fvs8bd1ITU2Vpk2bemwZXxMI+1DV+60BwIABA0xw8Pzzz4s/8cTnra1i9957r2kpmTNnjgTqfteuXdsEQhoA66SX/tU777xjWsWC6e/bSmmxLokG4n5bpdr0creVuqQlkk4++WST4hMMn7ee14mJiTJw4EDxJ+7s9y+//GJKNI4YMcI+78ILLzQlKr/99lsJ5M9b/54nTJgg33//vUyfPt20AKelpZlSjYGqmadiHVsAOXDggC08PNz21ltv2ef99NNPJhl61apV9nl//fWXbfPmzeVaJtD2OxA6t7m730uXLjUdA+68806bP3Jnv61qDo6WLVtmltFlg+E8V7t37/a7zm2e+ry1lJl24tyxY4ctUPdbK5TExsaayi0W7bSqJY+0nF+gn+e6/1rR4tFHH7X5G3f2+6uvvjLPb9u2zf58VlaWLSoqyvbyyy/bAvnzPnLkSKH1aMm+Bg0a+FU1KldikMqI1wIq8LXKY+g/Pj2QWiNO65VqWRdH+k/wnnvuKdcygbjfa9eutc2dO9eUeNKTSe/rlJGRYQvU/dYagPrF0KtXL/v+WlNOTo4tUPf7hx9+sPXv39/29ttv237++Wfbf//7X1uLFi3McbDKwgTqee7vga87+62fcZ8+fcwXhH72GvRptYP77rvP5k/c+by1dFlCQoJt8uTJ5nO+/PLLzd+89v4O9PNcS3npj5utW7fa/FF591uDv/bt29tOPfVU26effmr7+uuvTfUWrfHqT5VM3Pm8tTyjnusa+N199922GjVq2H788UebP1nrQgxSGfGaf3RjL4dx48aZEak+++wzM6qHduLRpG9H3bt3N68pzzKBuN+aEK+XilS3bt3MpWD1v//9T5KTkyUQ91tH7mrXrp25PGLtr+WLL74wuaCBuN/nnnuuyQvTS/wfffSRNGjQwHR+0s5t1apVk0A+zx1pHtiZZ54pcXFx4k/Ku9/9+/c3HWb0sree83rp+6uvvjLpPf7Enc/7tttuM526pkyZYlJ5dGQnzfX1pxEa3T3PdfQ2vezvrylu5d1vzWf9/fff5eWXX5b333/fLNO5c2dTwcVfqtW4+3m/9957Mn78ePO91bp1a5Pzq+e6P5nqQgxSGfFaiEa/Ht0TAAAAwAcFVOc2AAAAoCQEvgAAAAgKBL4AAAAICgS+AAAACAoEvgAAAAgKBL4AAAAICgS+AAAACAoEvgDgB9LT02XatGly9OhRb28KAPgtBrAAABFZuHChZGRkyNlnn+2Tx2PlypXSsWNH2b17txl5r7JkZ2ebUd4sOuJf+/btpVmzZm5tc2pqqs8eUwDBJ+CGLAYAd7zxxhuydu1anw3SNAC98sorzTCtlenAgQNy9dVXS58+fcywr/p4zpw5Mnz4cHnllVfKta5PP/3UDEnqq8cUQPAh8AUAF+Xk5Miff/4pmZmZctJJJ0nz5s0LPf/DDz/IoUOHJCQkRBo3biydO3eWWrVqFXrN9OnT5cwzz5Rjx47JsmXLpFWrVtKoUSP5+eef5bLLLpONGzeaKSkpSdq1a2dfrnbt2nLxxRdLRESEeawBaVnLWJYvXy5bt26VNm3aSJMmTWTGjBkyaNCgYtvmaOzYsdK/f39z/9tvv5ULLrhALr30Uunbt6+Zl5KSIn/99Ze5HxUVJR06dJAWLVrYl9+wYYNp8d2/f79J0VA9evSwtxyvW7dO1qxZIw0bNjTHKTw8nPMQQKUj8AUAFyxYsEAuueQSE6RqS6gGwNdff71MnDjR/pqZM2fK9u3bpaCgwAR+e/fulS+//FK6detmf82///1vEzxq67IGfFdddZVkZWWZVtaPPvrILK/B4K+//ioPPfSQCUCVztfXWKkOuv6yllEjR46Ud955R3r27CmbN282wfH3339v7pcW+Do699xzTTD/999/2wNfDaR135SmiMydO1duueUWef755808Xb/uowbo1us06NbtvOGGG8yx6t69u1lPbm6ufP3119K6dWvORQCVywYAsA0bNsx25plnOj0SWVlZtgYNGtjefPNN+7wdO3bY4uPjbTNmzCjx6I0ZM8Z2+umnF5oXERFh69atm1mn5c8//7Tpv+MHH3zQPm/atGm28PBw2+HDh83jFStWmNfs3r3b5WXmzJljCw0NtS1YsMA8zs3NtZ177rlmuc2bNzvd5u3bt5vnf/75Z/u89evXm3kffvhhifu6adMmW1RUlG3+/Pn2eY8++mixY/rII4/YunfvXmj/b731VtvZZ59d4roBwFNo8QWAMmgKg7ZcRkdHm7xVm81mJr20r62smgZg2bJli2np1CoMkZGRsnjxYsnPz5dq1arZX3PTTTeZ54oaMWKE/b7m2Go6hK5P0ypKUtoyuq29evUyLasqLCxM7r77bvnxxx/L/Mx/++03k6ag+/3aa6+ZVuvBgwcX6win+7dnzx7Jy8szLdGa/nDaaaeVuF5tfdYW5O+++85+HOvXry9vv/22WYduIwBUFv7DAEAZNJDUHNTPP/+80HzNz23ZsqW5rwGcBrSffPKJCTTj4+NNCoBexte8X31s0cv9ztSpU8d+38rlLat8WWnLaApE0Tzkoo9L8vvvv5u8YV2Hpi1ouoJjxzoN+K+44goT7Oox0Oc02Nf0jpLoDwBdn/4wOHz4cKHnNKjWQFpzmQGgshD4AkAZtKVXA9gPPvhAqlev7vQ1muM6ZcoU2bRpk8llVVrRQFtXNSh2pPmyVUGDYm2xdZSWlubSso6d21544QXTsU07yVkd2O655x65+eab5amnnrIvo63MRffVkbZ6a17x5ZdfLnfeeaebewUA7mMACwAogwaA2lqpl+kdaTC8b98+c18v92trpXZ+s2iqgTdp9QhtmdWWZ4tjjV5XaXqEVoS477777PN0f9u2bWt/vGrVKtOS60irPRRtsR44cKBMnjzZpDU42rlzZ7m3CwDKixZfADjBsfSWRS/la+7shAkTTIUErWzQpUsX2bZtmwls//Of/0i/fv2kd+/eJji+9tprZcCAAaYF2Kpm4C1DhgwxVSe0ju6wYcNMJYgPP/yw3K3OoaGh8uyzz5r90uoWmsOrpdW0goSmLBw5ckReeumlYlUiunbtalqO9Tk9jlrOTFuPzzrrLHNfK1zodmidYL3VNBEAqEwEvgAgYvJytT5v0WBVR0vTwHf06NGmJJgGuxrUalkwrYdr5fhqiTMNCv/3v//J7NmzzWhns2bNMgGjlXurNC9Wa/w6qlu3rhmcwjGNQnOKdZ6Vw1t0AAtXltHnNKjU4Fw7nWkLrQa+2oJdUi6tdrrTdRQdHU6Xuf/++2X+/Pkm8J00aZJJbdAR7zQV5OOPPzb761hHWI+bpofofD02mgKix3DFihXy3nvvmTrGuuw111xjAmkAqGwMWQwAAezgwYOFOsA9+eSTJtVAO+wBQLChxRcAAthtt91mWlq1BXrp0qUm6H3zzTe9vVkA4BW0+AJAANNR4d566y1TkUHTMXT0uVNPPdXbmwUAXkHgCwAAgKBAOTMAAAAEBQJfAAAABAUCXwAAAAQFAl8AAAAEBQJfAAAABAUCXwAAAAQFAl8AAAAEBQJfAAAABAUCXwAAAEgw+H8NTeRmz279PQAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 800x500 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# --- 1. CNN Hyperparameter Tuning: Learning Rate Sweep ---\n",
"# Testing the same learning rates used in the ANN evaluation\n",
"learning_rates = [0.01, 0.1, 0.2, 0.3, 0.6, 0.9]\n",
"performances_lr_cnn = []\n",
"\n",
"# Using a baseline of 100 hidden nodes for the dense layer\n",
"hidden_nodes_baseline = 100\n",
"# NOTE: To save time during the sweep, we will test for 1 epoch only.\n",
"epochs_sweep = 1 \n",
"\n",
"print(\"Starting CNN Learning Rate sweep. This will take some time due to 2D convolutions...\")\n",
"\n",
"for lr in learning_rates:\n",
" print(f\"Training CNN with Learning Rate: {lr}...\")\n",
" \n",
" # Initialize a fresh CNN network for each test to ensure a fair comparison\n",
" test_cnn = [\n",
" Convolutional((1, 28, 28), 3, 5), # 1 input channel, 3x3 kernel, 5 filters\n",
" Sigmoid(),\n",
" Reshape((5, 26, 26), (5 * 26 * 26, 1)),\n",
" Dense(5 * 26 * 26, hidden_nodes_baseline), \n",
" Sigmoid(),\n",
" Dense(hidden_nodes_baseline, 10), \n",
" Sigmoid()\n",
" ]\n",
" \n",
" # Train for 1 epoch\n",
" for x, y in zip(x_train, y_train):\n",
" output = x\n",
" for layer in test_cnn:\n",
" output = layer.forward(output)\n",
" \n",
" grad = mse_prime(y, output)\n",
" for layer in reversed(test_cnn):\n",
" grad = layer.backward(grad, lr)\n",
" \n",
" # Evaluate on the Test Set\n",
" score = 0\n",
" # Assuming test_data is already loaded and formatted\n",
" for record in test_data:\n",
" values = record.split(\",\")\n",
" correct_label = int(values[0])\n",
" x_test = np.asarray(values[1:], dtype=float).reshape(1, 28, 28) / 255.0 * 0.99 + 0.01\n",
" \n",
" output = x_test\n",
" for layer in test_cnn:\n",
" output = layer.forward(output)\n",
" \n",
" if np.argmax(output) == correct_label:\n",
" score += 1\n",
" \n",
" performance = score / len(test_data)\n",
" performances_lr_cnn.append(performance)\n",
" print(f\"CNN Performance for LR {lr}: {performance:.4f}\\n\")\n",
"\n",
"# --- Plotting the Results ---\n",
"plt.figure(figsize=(8, 5))\n",
"plt.plot(learning_rates, performances_lr_cnn, marker='s', markersize=8, color='#003366', linewidth=1.5)\n",
"plt.title(\"CNN Performance vs. Learning Rate\")\n",
"plt.xlabel(\"Learning Rate\")\n",
"plt.ylabel(\"Performance (Accuracy)\")\n",
"plt.xlim(0, 1)\n",
"plt.xticks(np.arange(0, 1.1, 0.1))\n",
"plt.grid(axis='y', linestyle='-', alpha=0.7)\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 63,
"id": "6e76e830",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Starting CNN Hidden Nodes sweep. This is computationally expensive...\n",
"Training CNN with 10 hidden nodes in the Dense layer...\n",
"CNN Performance for 10 nodes: 0.8307\n",
"\n",
"Training CNN with 50 hidden nodes in the Dense layer...\n",
"CNN Performance for 50 nodes: 0.8961\n",
"\n",
"Training CNN with 100 hidden nodes in the Dense layer...\n",
"CNN Performance for 100 nodes: 0.9143\n",
"\n",
"Training CNN with 200 hidden nodes in the Dense layer...\n",
"CNN Performance for 200 nodes: 0.9133\n",
"\n",
"Training CNN with 500 hidden nodes in the Dense layer...\n",
"CNN Performance for 500 nodes: 0.9151\n",
"\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 800x500 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# --- 2. CNN Hyperparameter Tuning: Hidden Nodes Sweep ---\n",
"# Evaluating the capacity of the Dense layer inside the CNN architecture\n",
"hidden_nodes_options = [10, 50, 100, 200, 500]\n",
"performances_hn_cnn = []\n",
"\n",
"# Fixing the learning rate to our optimal tuned value (0.3) for faster convergence\n",
"optimal_lr_cnn = 0.3 \n",
"\n",
"print(\"Starting CNN Hidden Nodes sweep. This is computationally expensive...\")\n",
"\n",
"for hn in hidden_nodes_options:\n",
" print(f\"Training CNN with {hn} hidden nodes in the Dense layer...\")\n",
" \n",
" # Initialize network with variable hidden nodes\n",
" test_cnn_hn = [\n",
" Convolutional((1, 28, 28), 3, 5), \n",
" Sigmoid(),\n",
" Reshape((5, 26, 26), (5 * 26 * 26, 1)),\n",
" Dense(5 * 26 * 26, hn), # <--- Varying capacity here\n",
" Sigmoid(),\n",
" Dense(hn, 10), # <--- Matching output connections\n",
" Sigmoid()\n",
" ]\n",
" \n",
" # Train for 1 epoch\n",
" for x, y in zip(x_train, y_train):\n",
" output = x\n",
" for layer in test_cnn_hn:\n",
" output = layer.forward(output)\n",
" \n",
" grad = mse_prime(y, output)\n",
" for layer in reversed(test_cnn_hn):\n",
" grad = layer.backward(grad, optimal_lr_cnn)\n",
" \n",
" # Evaluate on the Test Set\n",
" score = 0\n",
" for record in test_data:\n",
" values = record.split(\",\")\n",
" correct_label = int(values[0])\n",
" x_test = np.asarray(values[1:], dtype=float).reshape(1, 28, 28) / 255.0 * 0.99 + 0.01\n",
" \n",
" output = x_test\n",
" for layer in test_cnn_hn:\n",
" output = layer.forward(output)\n",
" \n",
" if np.argmax(output) == correct_label:\n",
" score += 1\n",
" \n",
" performance = score / len(test_data)\n",
" performances_hn_cnn.append(performance)\n",
" print(f\"CNN Performance for {hn} nodes: {performance:.4f}\\n\")\n",
"\n",
"# --- Plotting the Results ---\n",
"plt.figure(figsize=(8, 5))\n",
"plt.plot(hidden_nodes_options, performances_hn_cnn, marker='D', markersize=6, color='#003366', linewidth=1.5)\n",
"plt.title(\"CNN Performance vs. Hidden Nodes Capacity\")\n",
"plt.xlabel(\"Number of Hidden Nodes (Dense Layer)\")\n",
"plt.ylabel(\"Performance (Accuracy)\")\n",
"plt.xlim(0, 600)\n",
"plt.xticks(np.arange(0, 601, 100))\n",
"plt.grid(axis='y', linestyle='-', alpha=0.7)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "838e19bd",
"metadata": {},
"source": [
"### 3.1 Empirical Results & Architectural Justification\n",
"The empirical results provide clear architectural justifications:\n",
"1. **Learning Rate Stability & Speed:** While extreme steps (0.01) result in severe underfitting (accuracy around 20%), intermediate values scale rapidly. A learning rate of $\\eta = 0.3$ achieves the optimal performance peak (~92% accuracy) and accelerates the gradient descent trajectory, ensuring faster convergence compared to more conservative steps like $\\eta = 0.1$.\n",
"2. **Dense Layer Capacity:** Testing varying hidden nodes demonstrates a sharp performance jump from 10 nodes (underfitting at ~25%) to an optimal plateau at $50$ and $100$ nodes (~90% accuracy), remaining stable at higher capacities. \n",
"\n",
"Consequently, an optimized learning rate of $\\eta = 0.3$ and $100$ hidden nodes are selected as the final architectural configuration to maximize training velocity and predictive performance."
]
},
{
"cell_type": "markdown",
"id": "2750bf4b",
"metadata": {},
"source": [
"## 4. Final CNN Assembly & Training Loop"
]
},
{
"cell_type": "markdown",
"id": "a8827a2e",
"metadata": {},
"source": [
"Construction and training of the definitive Convolutional Neural Network. The architecture integrates the optimized hyperparameters (`LR=0.1`, `Hidden Nodes=100`) justified by the empirical sweeps in the previous section. The network extracts local features using a sliding 3x3 kernel over 15 epochs, maintaining spatial matrix relationships before flattening the tensors for the final classification."
]
},
{
"cell_type": "code",
"execution_count": 64,
"id": "bcfd3dda",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Starting CNN training. This may take a while...\n",
"Epoch 1/15 - Average Loss (MSE): 0.0309\n",
"Epoch 2/15 - Average Loss (MSE): 0.0124\n",
"Epoch 3/15 - Average Loss (MSE): 0.0098\n",
"Epoch 4/15 - Average Loss (MSE): 0.0083\n",
"Epoch 5/15 - Average Loss (MSE): 0.0072\n",
"Epoch 6/15 - Average Loss (MSE): 0.0064\n",
"Epoch 7/15 - Average Loss (MSE): 0.0057\n",
"Epoch 8/15 - Average Loss (MSE): 0.0052\n",
"Epoch 9/15 - Average Loss (MSE): 0.0047\n",
"Epoch 10/15 - Average Loss (MSE): 0.0043\n",
"Epoch 11/15 - Average Loss (MSE): 0.0039\n",
"Epoch 12/15 - Average Loss (MSE): 0.0036\n",
"Epoch 13/15 - Average Loss (MSE): 0.0033\n",
"Epoch 14/15 - Average Loss (MSE): 0.0030\n",
"Epoch 15/15 - Average Loss (MSE): 0.0028\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 800x500 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# 9. CNN Assembly and Training Loop\n",
"\n",
"# Define the sequential CNN architecture\n",
"network = [\n",
" Convolutional((1, 28, 28), 3, 5), # 1 input channel, 3x3 kernel size, 5 filters\n",
" Sigmoid(),\n",
" Reshape((5, 26, 26), (5 * 26 * 26, 1)), # Flattens the 3D output to a 1D column vector\n",
" Dense(5 * 26 * 26, 100), # Optimal 100 hidden nodes\n",
" Sigmoid(),\n",
" Dense(100, 10), # Matching connections to output\n",
" Sigmoid()\n",
"]\n",
"\n",
"# Hyperparameters\n",
"epochs = 15\n",
"learning_rate = 0.3 # <--- Optimized Learning Rate for faster convergence\n",
"epoch_losses = []\n",
"\n",
"print(\"Starting CNN training. This may take a while...\")\n",
"\n",
"# Iterative training loop\n",
"for e in range(epochs):\n",
" error = 0\n",
" for x, y in zip(x_train, y_train):\n",
" # Feedforward\n",
" output = x\n",
" for layer in network:\n",
" output = layer.forward(output)\n",
" \n",
" # Error calculation (MSE)\n",
" error += mse(y, output)\n",
" \n",
" # Backpropagation\n",
" grad = mse_prime(y, output)\n",
" for layer in reversed(network):\n",
" grad = layer.backward(grad, learning_rate)\n",
" \n",
" # Calculate and store the average loss for this epoch\n",
" average_loss = error / len(x_train)\n",
" epoch_losses.append(average_loss)\n",
" print(f\"Epoch {e + 1}/{epochs} - Average Loss (MSE): {average_loss:.4f}\")\n",
"\n",
"# --- Plotting the Learning Curve ---\n",
"plt.figure(figsize=(8, 5))\n",
"plt.plot(range(1, epochs + 1), epoch_losses, marker='o', color='blue', linewidth=2)\n",
"plt.title(\"CNN Training Loss Convergence\")\n",
"plt.xlabel(\"Epoch\")\n",
"plt.ylabel(\"Average Loss (MSE)\")\n",
"plt.xticks(range(1, epochs + 1))\n",
"plt.grid(True, linestyle='--', alpha=0.7)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "5d667943",
"metadata": {},
"source": [
"## 5. Model Evaluation & Classification Metrics"
]
},
{
"cell_type": "markdown",
"id": "08c6b6e2",
"metadata": {},
"source": [
"Comprehensive performance analysis of the custom mathematical framework on unseen test data. Beyond global accuracy, precision, recall, and F1-scores are calculated. A confusion matrix is generated to visualize the network's predictive fidelity across specific classes and to identify potential false-positive patterns."
]
},
{
"cell_type": "code",
"execution_count": 65,
"id": "2ab72b23",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading and formatting test data...\n",
"Evaluating CNN on Test Set...\n",
"CNN Final Accuracy on Test Set: 97.13%\n"
]
}
],
"source": [
"# 10. CNN Evaluation on Unseen Test Data\n",
"print(\"Loading and formatting test data...\")\n",
"\n",
"with open(\"mnist_test.csv\", \"r\") as f:\n",
" test_data = f.readlines()\n",
"\n",
"score = 0\n",
"total_tests = len(test_data)\n",
"\n",
"print(\"Evaluating CNN on Test Set...\")\n",
"\n",
"for record in test_data:\n",
" values = record.split(\",\")\n",
" correct_label = int(values[0])\n",
" \n",
" # Reshape test input to match the Convolutional layer input shape (1, 28, 28)\n",
" x = np.asarray(values[1:], dtype=float).reshape(1, 28, 28) / 255.0 * 0.99 + 0.01\n",
" \n",
" # Feedforward only (No backpropagation during evaluation)\n",
" output = x\n",
" for layer in network:\n",
" output = layer.forward(output)\n",
" \n",
" # The predicted class is the index with the highest probability value\n",
" predicted_label = np.argmax(output)\n",
" \n",
" if predicted_label == correct_label:\n",
" score += 1\n",
"\n",
"# Calculate and display the final accuracy\n",
"accuracy = (score / total_tests) * 100\n",
"print(f\"CNN Final Accuracy on Test Set: {accuracy:.2f}%\")"
]
},
{
"cell_type": "code",
"execution_count": 66,
"id": "4b96086a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gathering predictions for Custom CNN on Test Set...\n",
"\n",
"==================================================\n",
" METRICS: CUSTOM CNN (NumPy From Scratch)\n",
"==================================================\n",
" precision recall f1-score support\n",
"\n",
" 0 0.98 0.99 0.98 980\n",
" 1 0.98 0.99 0.99 1135\n",
" 2 0.99 0.97 0.98 1032\n",
" 3 0.94 0.99 0.96 1010\n",
" 4 0.98 0.95 0.97 982\n",
" 5 0.98 0.97 0.97 892\n",
" 6 0.96 0.98 0.97 958\n",
" 7 0.97 0.98 0.97 1028\n",
" 8 0.97 0.96 0.96 974\n",
" 9 0.97 0.95 0.96 1009\n",
"\n",
" accuracy 0.97 10000\n",
" macro avg 0.97 0.97 0.97 10000\n",
"weighted avg 0.97 0.97 0.97 10000\n",
"\n"
]
},
{
"data": {
"image/png": "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PrLf6Yajt945ICop64jR/20r54KvVxrcfxqJNYdu4J/g5O0ikZphNeGHAfbu3iW77YgzCsYaQJiaB7OEen4+IEAOqhLzU1arXlO+Bmr39OlTrFuzSk5LJybJb9Coiep/mU9J5Z2SYXXenNm4Exj41vK+/QfIgTYJDh08gMMHD8hZAMR7vnCRolDT+1ur9VxJ+634sJqSTPxXLcmIYdWUpHZYVYrUPpgRGUNKhlUl4/tbW2yTEFb5owBEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYZjqdTgcViooz9hYQpTzXRjM0+TKHrulh7E0gSnHqPDp/mJmZsbeAUpOt5YfXYcsqERERESkWwyoRERERKRbDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsNqMgoPC8P1a1fx4sULaAn3Wz3lnc7FDrkzu8LW2uKz1hG80zvBO50j1EKr9Tw09Clu3byBly9fQku0Wt5PnzzBP9evISwsFFrCev4CSmZp7A1QA51Oh0kTx2Hl8mXw8PTEo4cP0blrd3Tr8TXUjPutnvLO6umMOX0rIVdmNzwKi4RHGnsMnX8E87Zf/qh1hFK5PDC9pz/cne3w9HmUvLT7cQeCQiJgirRaz8+dPYMpk3/AvXtBsHdwwMMHD9CkWQv0HzAI5ubqbefQank/evQQg77ti2tXr8AzQ0ZZ7kWLFsOESVPg7OwMtWI9X2YS9ZxhNRmsXrkC69euwdIVq5HT1w8nTxxHt84d4OeXC/6VKkOtuN/qKe+F31ZB6ItoZG+/EC9j4mTg3Pp9PVwKfIpjVx8meZ3sGVywcXRdTNsQgDFLjkOnA4rlTI8s6Z1NNqxqtZ7funUTQ78bBb9cueTtSxcvoE2rFsiVOzfq1msAtdJqeU/5cRJePH+O7bv3w8HBUbawtmzWCH/M/B3fDhwCtWI9X20S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aGE1e/bsmDt3Lvr16yfnJRUtqOfOncPAgQNhbW0tuwbs2LEDrVq1+uBjidZZ8ThvtqymFtGq+2ZLUnDwvbfCN5HaiG/m4v2aYPXK5ciaLft/DswyJWLQQcIZkwQ9v+oGG2sbVU9dxf1+jeVtuvVczImaeDBUjgxOKJPLA91mHDborxoda9gymjmtg74bwOErj/StrgmW9fdHVGy8SU9dVbJUKRzYvw8dO3eVt1+9eoWD+/ejbPnyUCKjhdVmzZph5MiR8PDwQGxsLPr3748jR44gT548KFCgAI4dO4a0adPC39//g48lguKbYTHKsEtKiurQtjVq1a4DX79cMrhu2bQBV69cxoBB/3ZxUKuIiBe4fev11B73goLkKSNXNzdkzJgJaqWV/RYT/UdGRshv37ExMbh08bxcntM3F6ysrOT17p3bo2nzlkif3gPb/t6Cvbt3YsbsebILDBGRMbWrmAPe6Ryx7cw9ZHC1w7AmBeX8qGuPBerX2Ty8KlYdvi1nBBA/CND0Cx956n/Y4n/PEqlVl2490KZVc0wc/z0q+FfExg3r5Jnstu06QonMdGJmWCMJDg7GihUr5Mj/Fi1ayEEZ48ePx5UrV5AvXz4MHjxYzhbwKVIzrD59+hR/LVqA8wHnZH8PMZ1Pi1atkSmTF9TsfEAAxn//dleLipWqoGv3r6BWStpvcZorpYwZOVx+6XrTb9P/0E/6H3j7FubMnomgoCDkzOkru714Z/FBSrMwN14YnjxxPCytrNC3/wBoCfeb5Z1aMrT/K1keR3xn7lzFV86PKlpYN564K6eqEqfwE7g72aBHjVwomt1dDsoSfVxn77iGuyER733cca2LIDbuFUYtP4vkdH9+a6SmSxcvYMG8uXhwP1h+bnfq0lV27UpttpYKD6spKTXDKpGxpGRYVTJjhlUiMo2wampSO6wqRVLCquJ+FICIiIiIKAHDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsMqERERESkWwyoRERERKRbDKhEREREpFsMqERERESmWmU6n00GFouKgSeoszQ8zM4MmvXqlzQI302qBa5RWi/uVRj/QzTVa4OlaL4AWPV/e7oPrsGWViIiIiBSLYZWIiIiIFIthlYiIiIgUi2GViIiIiBSLYZWIiIiIFIthlYiIiIgUi2GViIiIiBSLYZWIiIiIFIthlYiIiIgUi2GViIiIiBSLYZWIiIiIFIthlYiIiIgUi2GViIiIiBSLYZWIiIiIFIthlYiIiIgUi2GViIiIiBTL0tgboAaPHz/C3D//wN7duxEaGoosPj5o274DatepBzWbPWs6fv9tqsEyRycnHDxyEmq3cf06/DFrBu4H34N3Fh9806cf/CtWgppcvXIZK5cvxZbNm5A2bVps2LL9rXWKFcqL+Ph4g2XfDhyC1m3aQS0a1K2B27duvbW8UuWqmDJ1GtRKq/t9+dJFzJ0zG6dOnEBcXBzy5suHb/r2R+7ceaDK9/em/7+/t779/n4SEoKJ48fi8MEDsLC0RMVKlTFg8DA4OjpCLdR4/Hays8LwZoVQt4Q30jrb4kJgKIYuOoGjVx/r1xnQqABGNC9s8HdhETHI3HGp/vapKQ3gm8nlrcffcDwQrX/ai9TEsJoMVixbipy+fmjfsQscHR3w95YtGD5kENKkcUWZsuWgZvkLFMSiJSugJYcO7MeoEcMwasw4VPCviHVr16B/n15YtGQ58uTNB7UYN3YU6tZvCHsHB+zdveu9602bMVvV9Xzdxr8NbgfevoX6dWqgSrXqUDOt7vfv035FvfoNMHjIcJiZm+O3X6aga8f2WLVuIzw8PKCq93e9hrC3f/f7W6fToV/vnjKkrly3ETHR0fi2b2+MGDoYU35Vz5cVNR6/Z35VBr4ZXdBk4i4EPnqBVhWyY+3Qqvhi4Ebcevhcv96J649RafiW9z5O0X7rDG7nyOCMM780xLqjgdB0NwDxLdYUfd2rNxo1bio/yBwcHNG4aTOkT++B8wHnjL1plAIWzJ+L8v4VUbd+Azi7uMhv4X5+ubB40QJVvd4L/1qOps1awN7e3tiboihr16yCi0saVK5SDVqilf2eNn0WqlWvCfe0aeHm5oYhw0cgMjICRw8fgure383f//4+e+Y0As6dxeCh3yFjxkzwyZoNvfv2x57dO3H3zh2ohdqO33bWFqhdLDMmrw3ApbthiIiOw+ztV3H1Xji61cj1WY/dtmIOPH0eJVtWNRVWnz9/jpEjRyJ//vywtraGlZUV0qRJg1q1amH37t0wRZGRkdiwbi3Cw8NRvoI/1O7a1Sv4okRhVCxXCj17dMX1a1ehZqK1IeDcORQrXsJgeYlSpXHu7Blo0dBB36Jk0QJoVK8W5s/9E7GxsVAr8YV604b1qF23HmxsbKAVWt1v4Vl4uOzqIro4aYn4PHN2doGvn5/B51zCfWqkhuO3mZkZxH863dv3lfZLb3A7XxZXBM9vhVuzm2PVoMrIkznNex/XwtwMLctnx9IDNxEd+wqpzWjdAKKiolCuXDn5IVC4cGFZSby8vFCtWjXs2bMHVapUwa+//oqePXvCFFy/fg1NGtSV18WH+cgx36vqlPC7uLunw6ix41GmTDk8f/4Mv/36Czq0bYVVazfBM0MGqFFERARevoyEm6ubwXI3N3eEhIRAa2rVrot2HTrJ8j5+9ChGjxyGkJDHst+qGh3Yv1fuX6MmzYy9KalKq/st/DBxHDw9M+CLMmWhJaK8Xd1cDZaJY5uDg4Psy6omajp+R0bHYcfZe/i2YX5cuBMquwG0KJcNhbK64WFYlH69R2Ev8dWMw9h57h5c7K0xokVhbB9TEyW/XY97TyLfetwaRbzg6WqP+buuwxiMFlaXLFkCFxcXGUzNzc3x8uVLFClSBPXq1cOwYcPw999/o3HjxmjUqBEyZsz4n48VHR0tL4npLGxStQUgZ05fnLt4Fc+ePcP2v7dixLChcLB3gH+lylCrRk2a6q+L0+Fjx01AreqVsWb1CnzVsze0RAed/DarNWPGTdRfr1i5Ch4+fICfJk/EN336y7MlarNuzSoUKFgYOXLkhJZodb9/m/ozDu7fh9lzF8DOzs7Ym6OYs0tmKvuoU9vxu9v0gxjTqig2DKsKZ3trGUjn7LiGmkW99Oss2H3dYGBV9+mHcGFaY7Sv5ItxK8++9ZhtK+bEsauPcCUoDMZgtG4AV69eRfXq1WVQFcQHQdmyZXH48GF5u0aNGrKVNSndASZMmCCDb+LL5B8mwBicnZ3RpFlzlCtfHitXLIOWWFlZI0sWH9wJTP3+LKlFtCrY2dnjaehTg+WhT5/CPa07tC5HTl95yjj4XhDURowaPnTwgMGXNC3Q6n7P+P03LFm8EL/PnI18+QtAa9KmTYfQp6EGy0SjkDgL6uaeFmqkluP3k+fR+HrWYeTsvhIebf+SI/c9Xe1w++GL9/5NbPwr/HM/HNkzOL91n0caO1QtlAnzEwVczYRV0Vp6/vx5g2UXL15E+vSv+1SI6TRE/4sPGTJkiOxjkvgyYJBxT0OKA3ZStl1NYmNjEBh4G+kSlaHaiDItULAgThw/ZrD8+LGjKFjIcBoQLfrn+jX5BdRdhQczMV2Zra0tqlevCS3R4n7PnD4NC+fPlUG1SNFi0CLxefbsWTiuXrli8DmXcJ+aqe347eZog0oFMmLTyfcPjLOyMEeODC54EPp2F4DWFbIjMiYOa47chubCasOGDbFhwwZ06tQJ06dPl6f8r1+/jooVK8r7xXxnopVVtL5+iDjdL74RJb6kZheAb/t+g9OnTiIi4gWePHmCRQvmy5aIeg0aQs2+7fcNTp08Iff7XtBdfDdsiBw011jl/drate+IA/v2yoO4GHwhylvMWfiliuYWTYqNG9Zh4fw5uBcUJEdL79m1E7NmTEO9Bo3g5Pz2t3NTt27tatSsVQd2GpsdQWv7PXvWDCyYN0fTQVUoVLgIChQshB8mfI/g4Hu4fesmpk75ERUrVUFmb2+ohRqP320r5kCTL7LC0dYSOTM4Y1G/Cvjn/jP8uf31AOiFfSugTG4PuU6WdI5yuisXeyvM23ntrcdr458DKw/ekv1hjcVMJzqgGMn27dvRv39/GVLz5cuHadOmoVSpUvK+K1euyMEsRYsW/aTHjkrF11RU9D9mzsCF8+dgaWmJ7Dlyom37jnIOztSWmqV55vQp/DFzOs6fPwc7W1vkzV8APXv1kaeCU1tqfwmWPwowczru3w/+90cBevc1Sv+mV69SrsDFYDkxfc2b/t6xFx6enjKgitYn8aMBIY8fI1OmTKjboCFatmojZ/ZISand6iG+lHVq/yWWrliD3HnyQiuUst+pWdzFC+dHTEzMW8u7f9UTPb7ulbrv7xT8QO/Q5j3v753/vr8FMZBqwrgxOHzwICwsLeSPAgwcMjzFfxTAPBULXEnH73StFyRbS+r4NsVQu7g3YmLjseH4HYxedlr2TU1Qyi8dBjUuiGI50uFldBxO3QjBmOVncPmuYZ9UEWj/HlUDZQdvxLlbht3fksvz5e2UHVZTUmqGVSVRZ2l+mIrO2CgmrCqZmk7R0YdptbhTMqwqWWqGVSVJrrBqapISVhX1owBERERERIkxrBIRERGRYjGsEhEREZFiMawSERERkWIxrBIRERGRYjGsEhEREZFiMawSERERkWIxrBIRERGRYjGsEhEREZFiMawSERERkWIxrBIRERGRYjGsEhEREZFiMawSERERkWIxrBIRERGRYjGsEhEREZFiMawSERERkWIxrBIRERGRYjGsEhEREZFy6ShZRUVF6UaOHCn/1RLuN8tbC1jPWc+1gPWc9VxpzMT/jB2Y1eTZs2dwcXFBeHg4nJ2doRXcb5a3FrCes55rAes567nSsBsAERERESkWwyoRERERKRbDKhEREREpFsNqMrOxscHIkSPlv1rC/WZ5awHrOeu5FrCes54rDQdYEREREZFisWWViIiIiBSLYZWIiIiIFIthlYiIiIgUy9LYG6AmDx48wN27d5EtWza4u7tDK548eYLLly/Dz88P6dKlgxaI39K4ceMGYmNjZXlraUBdUFAQQkJCkDVrVvkDGFoSFRWFkydPIm3atMiVKxfUTHyWBQYGGiyztLREqVKloJX3+NWrV2FmZgZfX1/5r5qdPn0akZGRby13dXVF3rx5oXZ37tzBo0ePkDFjRnnRSh2/e/cuHj9+LOu4k5MTFMvYP6GlBvHx8bquXbvqbGxsdHny5JH/Dh06VKd2V65c0bVt21aXIUMG8StoukWLFum0YPr06Tpvb29d9uzZdb6+vjo3Nzfd/PnzdWq3b98+XZEiRXQ+Pj66AgUK6GxtbXU9evTQxcXF6bSiS5cuOnNzc13jxo11ajd27Fidk5OTrkyZMvpLjRo1dFqwZ88eXbZs2XReXl66QoUK6UqUKKG7deuWTs1atWplUNbiIj7X27Rpo1OzwMBAXbFixeTneNGiRWWd9/f314WEhOjUfvwuWrSoLl26dLqCBQvK/f711191SsWwmgymTZumc3Fx0V2+fFnePnz4sM7Kykq3evVqnZqtXbtWN2/ePF1kZKSmwuro0aN1QUFB+tuzZ8/WWVhY6AICAnRqJso3oY4L58+f11lbW8s6oAUrVqzQFS5cWFe1alXNhNWSJUvqtEbUcTs7O92YMWP0y86cOaM7dOiQTkv2798vP9d37dqlU7NmzZrJLyTiOCY8efJENkb07t1bp2aFCxfW1a5dWxcVFSVvnzx5Uja0iXJXIvZZTQZz585F06ZN9acFS5cujcqVK8vlatagQQO0b98ednZ20JIRI0YgU6ZM+tudOnWCubk5jhw5AjX78ssvDU5958uXT3b7uHfvHtTu1q1b6N27N/766y9YW1tDK+Li4nDu3Dl5Olxc14Lx48fLrj3Dhw/XLytUqBC++OILaMmcOXOQPXt2VKxYEWomToGL8k04jrm5uSF37txyuVqFhYXhzJkz8tiV0IWtaNGiKFmyJGbPng0lYp/VzxQfH4/z58+jS5cuBstLlCiBP//883MfnkyAOJiLvqs5cuSA2ok+baJvW0REBFatWgV7e3t06NABaiZCWsuWLWV4EQcxLREHtFatWiE8PFz21/3555/Rpk0bqNmuXbvkPkZHR+PixYtInz49vLy8VN9nNbHnz59j5cqV+O6771S/38OGDUPr1q3x22+/IU+ePDh27BgCAgKwZcsWqJWDg4P80p24oUGcab9//74cj6BEDKvJ8KYWQeXNAVXi9tOnTz/34ckEwlvHjh1RtmxZ1bdACA8fPsTgwYPlN3Mx+Ea0MmfIkAFqP5iJAVVfffUVtKR48eK4efMmsmTJIm//8ssv8kxKzpw5VTvIShywxUBZcRAXA0ZFK5uo52LwybJly+Dj4wMtWLp0KWJiYmR5q51oWKpTp4785UlRvqLOi8YnEVzVysrKSn6eiX0WgybFYFlx1ki0Jtva2kKJGFaTodAF0eqQ2MuXLzV1ulCLRMtLo0aNZCvj1q1bVd8CIYgPtYMHD8rr4oxC+fLlZReI/v37Q43EyP+pU6diyZIl+v0ODQ2V721xWwQ6tc4EUb16dYPbffr0wcyZM2WLm1rDqngPW1hYYPPmzbLsRXcA8f6uVq2aDDA7duyAVroA1K1bF56enlA7ceZAvKfFbACOjo5ydpty5crJhihR39Xqp59+QoECBWQLsjhzUqNGDXkWYc2aNVAihtVkaE4Xrahv9tsTt729vT/34UmhRKuDCKriW/jevXvh4eEBrcmfP7/8gBNBXa1hVXzpLFasGKZMmaJfJqZpEwFdtDCLrhBaOKAnEPVc7X2UReta4cKFZVBN+IwX/bX79esnW17V/qX0woULOH78uKpPgyfuxic+v2bMmCGDqiCO56Lbj1im5rBqbm4uu3Al7sZVqVIlORZBiRhWk0HVqlWxceNGefBKeAOIb+b169dPjocnhQbV69evY8+ePZqZk0+0MIkD95tzzYrWVrUSLSwJLaoJxClDcapMBFUtlbc4RXj27Fn5eadmokVZ9NV9c25h0RVE7UFVEGMtMmfO/FbLuhqJVnTR1UOUb2Ji7lG1zxn+8uVLg8HRon/2/v37ZXcXJWJYTQaiE7ro99KtWzd5IFu0aJE8haDW1qYE4tSBOBWc4Nq1a/LALlqa1DzYqEWLFti3b588VSZGiYuLIFrS1dya7u/vj8aNG6NgwYLyg06cGr906ZJsgSD1EX2wxYwfopVRDLqYNGmSPE2o9r67otFB7PM333wjP8/FQVz01/3hhx+ghS/iixcvRq9evWTLmxaIcp44cSKcnZ3lafGjR49i3rx5qv9cmzt3rvz8FnU8ODgYo0aNki3KTZo0gRKZifmrjL0RaiBCmzhVKPq9iAEIAwcO1J9GUivRp0v0Y3uT6Os0aNAgqJWYlkz0V32TGGglLmol+nVNmzZNjpYVfbXFr9r06NHDYBovLRB1W/RZHTt2LNQscXmLWR/EF3IRVMV1tbt9+zYmT54sp+wSAwjFQbxWrVpQOzH93oABA+QAK9G6qhWrV6/G2rVr5QBS8XkmylvtLcs6nU42uKxbt072uxdnC0X/XaWePWBYJSIiIiLF0kY7PxERERGZJIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIqLPIH529++//9bfvnz5MrZv366IbUmpH0DZvXv3Zz+OMV8nIjItDKtEpDpbtmyRv3EtLuvXrzf4WeDktm3bNnz77bf62+L5hg4dmuS/Fz95uHPnzhTZljfduHEDK1eu/KznWL58OcaMGYPP9bGvExFpl6WxN4CIKLn169dP/ra5+K3viIgIHDx4UF7ftGkTnJycUvQFz5Mnz0f9VOOaNWvkdlWpUgUpbceOHfInkps2bZriz0VElFwYVolIlerVq4eJEyfK63fv3kXevHkxadIkGWRFC2Tjxo1x4cIF3Lx5E2XKlIGnp6dc99q1a7K1U9wuXLiw/N3sxOLi4mT4jYmJQaFChd563pw5c8LW1vadrZri+cRvrhcpUkS/TLT6PnnyRLYCCyVLlkTWrFmTZVs+1q1bt3Ds2DF53dHRUQbvbNmyvXPdqKgonDlzBiEhIfL1c3Nze2udD20/EVFSMKwSkeqJgFi0aFGcPXtWBsSWLVuidu3auHPnDnLnzo0cOXLA3d0dHTt2lP0oS5QoIQOuCGTidLWfn598nGfPnskW0KCgIBkOz507p78vgVh/1apVqFatmrwdGxsrH3fdunUoVaoUQkNDkS5dOmzcuFGGQ9F3UywT9wsZMmSAl5dXsmzLxxKvR8J2iMcXQVhsxy+//GKw3r1792T4FCE0PDxcBn7ROly2bFmDff6v7SciSiqGVSJSPdECKYJhQoBMCLAiYCUYO3asDI4izIpWRaFXr17o1q0b9u7dK2+LlloR4sR6Li4uMoQVLFgQGTNmfO9zi8cVoU2EyYRWStGyGx8fL8Nms2bN5HYktKym5LZ8SIUKFeQlwe3bt2X3CdFtQLSeJvjnn3+waNEifPnll/J29+7d0bVrV9lyLLpfiG370PYTESUVwyoRqZIISyIARkZGypbOR48eycAUHR0t7xfXE5s3bx78/f3laHqdTicvogX00KFD8jS7tbU1VqxYgR49eshwmBB4RSvtvn373rsdCxYswFdffWVwOv1DfVpTaluS4uXLlzh16hQePHggQ74Iv8ePHzcIq6L1t3Xr1vrbgwYNwqxZs2SXBhGYk7L9RERJxbBKRKokpnESp7Tt7Ozk6feZM2fC29sbJ0+e1AeuxAIDA2UfSxFuExN9W0WAEwFLnCb38fExuF/0L/2vgChaPH19fT9q21NqWz5k//79aNKkCdKnTy/Dtb29PcLCwmTQTyxLliwwMzMzuC1aVMV2i7CalO0nIkoqhlUiUv0Aq3dJHLYEMUtAo0aN5ACs9xH9WkX/0sTevP0m0fIpBlB9jJTalg8R01516NABP/zwg36Z6A8rWkb/63lEv9VXr14hbdq0Sd5+IqKk4jyrREQAatSogTlz5sjBQW8OJkogBhAlDEASREBLfPtdRD/ZxYsXy3UThz3RZ1UQfTrF4KPU2JYPEaf+Ew+AunLlCi5evPjeUf6Jp99ydnZGvnz5krz9RERJxZZVIiIAkydPRrly5WSXgbZt28rT2mI0vOi3uXr1avkajRo1So5uF/01xUAkEdLEKXIPD4/3voailVL096xYsSKaN28ug6qYWF/0A7WwsECxYsUwYMAATJkyRfYPFVNXpdS2JITaxIO5BHFaXrSENmjQACNHjpSn70Xf3p9//hkODg5vPYYIpqLl+ptvvpHdBEQLtvihALE8qa8lEVFSMawSkeqIaalE38l3EfOBitD4Zr9JMUApICBADogS84eKU9lipL4IcQnEXK0iZP7xxx9ynVatWslJ9nft2vXeHwUQ/UrF44qWRvG34rYYeJQwF6toIV26dKn8FasTJ07IvrQifCbHtrxJTNElHuPNFlgRSMVyEZjFVF7iccVzLlmyBAcOHDAYHCZmBxCn98U+iuAp5llduHCh7Ov6Ma/lx/54AhFpl5nuzc5IREREREQKwT6rRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0REREQEpfofG6n63vwzDSMAAAAASUVORK5CYII=",
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import numpy as np\n",
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"from sklearn.metrics import confusion_matrix, classification_report\n",
"\n",
"# --- Custom CNN Evaluation: Confusion Matrix and Classification Metrics ---\n",
"\n",
"def plot_confusion_matrix(y_true, y_pred, title):\n",
" \"\"\"Generates and displays a styled confusion matrix.\"\"\"\n",
" cm = confusion_matrix(y_true, y_pred)\n",
" plt.figure(figsize=(8, 6))\n",
" sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', cbar=False)\n",
" plt.title(title, fontweight='bold')\n",
" plt.xlabel('Predicted Label')\n",
" plt.ylabel('True Label')\n",
" plt.show()\n",
"\n",
"print(\"Gathering predictions for Custom CNN on Test Set...\")\n",
"y_true_custom = []\n",
"y_pred_custom = []\n",
"\n",
"# Collect predictions from the Custom CNN using the test_data\n",
"for record in test_data:\n",
" values = record.split(\",\")\n",
" y_true_custom.append(int(values[0]))\n",
" \n",
" # Reshape and normalize input to match spatial convolutions\n",
" x_input = np.asarray(values[1:], dtype=float).reshape(1, 28, 28) / 255.0 * 0.99 + 0.01\n",
" \n",
" # Feedforward inference\n",
" output = x_input\n",
" for layer in network:\n",
" output = layer.forward(output)\n",
" \n",
" y_pred_custom.append(np.argmax(output))\n",
"\n",
"# --- Display Custom CNN Metrics and Plots ---\n",
"print(\"\\n\" + \"=\"*50)\n",
"print(\" METRICS: CUSTOM CNN (NumPy From Scratch)\")\n",
"print(\"=\"*50)\n",
"print(classification_report(y_true_custom, y_pred_custom))\n",
"\n",
"# Plot the matrix\n",
"plot_confusion_matrix(y_true_custom, y_pred_custom, \"Confusion Matrix - Custom CNN\")"
]
},
{
"cell_type": "markdown",
"id": "6cf4f325",
"metadata": {},
"source": [
"## 6. Robustness Benchmark: Noise & Spatial Complexity"
]
},
{
"cell_type": "markdown",
"id": "ea95c62d",
"metadata": {},
"source": [
"Stress-testing the custom architecture's limitations. The model is evaluated against artificial noise to test translation variance, and against complex spatial hierarchies. This validates the model's stability against diffuse edges, a critical requirement for scaling the framework to segment thermal image artifacts."
]
},
{
"cell_type": "markdown",
"id": "3e4f14d1",
"metadata": {},
"source": [
"### 6.1 Corrupted MNIST: Brightness, Dotted Lines, Glass Blur\n",
"Evaluating how the custom network handles corrupted data without retraining. This tests the robustness of the convolutional filters against artificial visual artifacts.\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 67,
"id": "8788f40b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Evaluating CNN against: brightness...\n",
"CNN Accuracy on 'brightness': 12.72%\n",
"\n",
"Evaluating CNN against: dotted_line...\n",
"CNN Accuracy on 'dotted_line': 89.53%\n",
"\n",
"Evaluating CNN against: glass_blur...\n",
"CNN Accuracy on 'glass_blur': 88.46%\n",
"\n"
]
}
],
"source": [
"import os\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# --- 6.1 CNN Robustness Evaluation on Corrupted MNIST ---\n",
"def evaluate_cnn_npy_corruptions(corruption_type, base_folder, cnn_network):\n",
" images_path = os.path.join(base_folder, corruption_type, \"test_images.npy\")\n",
" labels_path = os.path.join(base_folder, corruption_type, \"test_labels.npy\")\n",
" \n",
" try:\n",
" images = np.load(images_path)\n",
" labels = np.load(labels_path)\n",
" except FileNotFoundError:\n",
" print(f\"Error: Could not find files for {corruption_type}\")\n",
" return\n",
" \n",
" score = 0\n",
" num_samples = len(labels)\n",
" \n",
" print(f\"Evaluating CNN against: {corruption_type}...\")\n",
" \n",
" for i in range(num_samples):\n",
" # For the CNN, keep spatial dimensions and reshape to (1, 28, 28)\n",
" img_2d = images[i].reshape(1, 28, 28)\n",
" \n",
" # Normalization\n",
" if img_2d.max() > 1.0:\n",
" data = (img_2d / 255.0) * 0.99 + 0.01\n",
" else:\n",
" data = img_2d * 0.99 + 0.01\n",
" \n",
" correct_label = labels[i]\n",
" \n",
" # INFERENCE: Forward pass through the network layers\n",
" output = data\n",
" for layer in cnn_network:\n",
" output = layer.forward(output)\n",
" \n",
" predicted_label = np.argmax(output)\n",
" \n",
" if predicted_label == correct_label:\n",
" score += 1\n",
" \n",
" accuracy = (score / num_samples) * 100\n",
" print(f\"CNN Accuracy on '{corruption_type}': {accuracy:.2f}%\\n\")\n",
"\n",
"# --- Execution of Stress Tests for the Custom CNN ---\n",
"base_dir = \"mnist_c\" \n",
"corruptions_to_test = [\"brightness\", \"dotted_line\", \"glass_blur\"]\n",
"\n",
"for corr in corruptions_to_test:\n",
" # Passing the 'network' list containing the custom CNN\n",
" evaluate_cnn_npy_corruptions(corr, base_dir, network)"
]
},
{
"cell_type": "markdown",
"id": "b5b96e96",
"metadata": {},
"source": [
"### 6.2 Fashion MNIST\n",
"Evaluating the custom architecture on a more structurally complex dataset (clothing items instead of simple digits) to test the limits of the native 2D feature extraction."
]
},
{
"cell_type": "code",
"execution_count": 68,
"id": "e80cf5de",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading Fashion MNIST dataset for Custom CNN...\n",
"Starting Custom CNN training on Fashion MNIST. This will take a while...\n",
"Epoch 1/15 - Average Loss (MSE): 0.0362\n",
"Epoch 2/15 - Average Loss (MSE): 0.0230\n",
"Epoch 3/15 - Average Loss (MSE): 0.0204\n",
"Epoch 4/15 - Average Loss (MSE): 0.0189\n",
"Epoch 5/15 - Average Loss (MSE): 0.0177\n",
"Epoch 6/15 - Average Loss (MSE): 0.0170\n",
"Epoch 7/15 - Average Loss (MSE): 0.0162\n",
"Epoch 8/15 - Average Loss (MSE): 0.0155\n",
"Epoch 9/15 - Average Loss (MSE): 0.0150\n",
"Epoch 10/15 - Average Loss (MSE): 0.0146\n",
"Epoch 11/15 - Average Loss (MSE): 0.0141\n",
"Epoch 12/15 - Average Loss (MSE): 0.0136\n",
"Epoch 13/15 - Average Loss (MSE): 0.0133\n",
"Epoch 14/15 - Average Loss (MSE): 0.0129\n",
"Epoch 15/15 - Average Loss (MSE): 0.0124\n",
"Evaluating Custom CNN on Fashion MNIST Test Set...\n",
"Custom CNN Final Accuracy on Fashion MNIST: 86.94%\n"
]
}
],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from tensorflow.keras.datasets import fashion_mnist\n",
"\n",
"# --- 6.2 Load and Preprocess Fashion MNIST for Custom CNN ---\n",
"print(\"Loading Fashion MNIST dataset for Custom CNN...\")\n",
"(train_images_f, train_labels_f), (test_images_f, test_labels_f) = fashion_mnist.load_data()\n",
"\n",
"# Preprocess Training Data\n",
"x_train_custom_f = []\n",
"y_train_custom_f = []\n",
"for i in range(len(train_images_f)):\n",
" # Reshape from (28, 28) to (1, 28, 28) and normalize between 0.01 and 1.0\n",
" img = train_images_f[i].reshape(1, 28, 28) / 255.0 * 0.99 + 0.01\n",
" x_train_custom_f.append(img)\n",
" \n",
" # One-hot encoding (10 classes)\n",
" target = np.zeros((10, 1)) + 0.01\n",
" target[train_labels_f[i]] = 0.99\n",
" y_train_custom_f.append(target)\n",
"\n",
"# Preprocess Testing Data\n",
"x_test_custom_f = []\n",
"y_test_custom_f = []\n",
"for i in range(len(test_images_f)):\n",
" # Reshape and normalize test images\n",
" img = test_images_f[i].reshape(1, 28, 28) / 255.0 * 0.99 + 0.01\n",
" x_test_custom_f.append(img)\n",
" # Store raw integer labels for evaluation\n",
" y_test_custom_f.append(test_labels_f[i])\n",
"\n",
"# --- Initialize the Custom CNN Architecture ---\n",
"# Creating a new network instance to avoid overwriting weights from regular MNIST\n",
"network_fashion = [\n",
" Convolutional((1, 28, 28), 3, 5), # 1 input channel, 3x3 kernel, 5 filters\n",
" Sigmoid(),\n",
" Reshape((5, 26, 26), (5 * 26 * 26, 1)), # Flatten output to 1D column vector\n",
" Dense(5 * 26 * 26, 100), # Hidden dense layer (Optimal capacity)\n",
" Sigmoid(),\n",
" Dense(100, 10), # Output layer (10 clothing classes)\n",
" Sigmoid()\n",
"]\n",
"\n",
"# --- Training Loop ---\n",
"epochs = 15\n",
"learning_rate = 0.3 # Optimal learning rate\n",
"epoch_losses_fashion = []\n",
"\n",
"print(\"Starting Custom CNN training on Fashion MNIST. This will take a while...\")\n",
"for e in range(epochs):\n",
" error = 0\n",
" for x, y in zip(x_train_custom_f, y_train_custom_f):\n",
" # Feedforward\n",
" output = x\n",
" for layer in network_fashion:\n",
" output = layer.forward(output)\n",
" \n",
" # Error calculation (MSE)\n",
" error += mse(y, output)\n",
" \n",
" # Backpropagation\n",
" grad = mse_prime(y, output)\n",
" for layer in reversed(network_fashion):\n",
" grad = layer.backward(grad, learning_rate)\n",
" \n",
" # Calculate and store average loss\n",
" average_loss = error / len(x_train_custom_f)\n",
" epoch_losses_fashion.append(average_loss)\n",
" print(f\"Epoch {e + 1}/{epochs} - Average Loss (MSE): {average_loss:.4f}\")\n",
"\n",
"# --- Evaluation on Test Set ---\n",
"print(\"Evaluating Custom CNN on Fashion MNIST Test Set...\")\n",
"score_f = 0\n",
"for x, correct_label in zip(x_test_custom_f, y_test_custom_f):\n",
" # Feedforward only\n",
" output = x\n",
" for layer in network_fashion:\n",
" output = layer.forward(output)\n",
" \n",
" predicted_label = np.argmax(output)\n",
" if predicted_label == correct_label:\n",
" score_f += 1\n",
"\n",
"accuracy_f = (score_f / len(x_test_custom_f)) * 100\n",
"print(f\"Custom CNN Final Accuracy on Fashion MNIST: {accuracy_f:.2f}%\")"
]
},
{
"cell_type": "markdown",
"id": "6c79c1c2",
"metadata": {},
"source": [
"## 7. Industry Standard Comparison (TensorFlow)"
]
},
{
"cell_type": "markdown",
"id": "9051b7c0",
"metadata": {},
"source": [
"\n",
"A direct benchmark against a commercial high-level framework. The exact same architecture and mathematical parameters (MSE, SGD, LR=0.3, 100 hidden nodes) are replicated in TensorFlow. \n",
"\n",
"This step is crucial to:\n",
"1. Compare global accuracy on standard MNIST.\n",
"2. Evaluate robustness against noise (Corrupted MNIST) and structural complexity (Fashion MNIST).\n",
"3. Validate the mathematical correctness of the custom NumPy implementation against an industry standard."
]
},
{
"cell_type": "code",
"execution_count": 69,
"id": "07bfa181",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Preparing data for TensorFlow...\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\Users\\sofia\\CNN-From-Scratch\\.venv\\Lib\\site-packages\\keras\\src\\layers\\core\\input_layer.py:27: UserWarning: Argument `input_shape` is deprecated. Use `shape` instead.\n",
" warnings.warn(\n"
]
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"sequential_6\"</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1mModel: \"sequential_6\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ conv2d_6 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Conv2D</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">26</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">26</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">5</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">50</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ flatten_6 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Flatten</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">3380</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_12 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">100</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">338,100</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_13 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">10</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">1,010</span> │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
"</pre>\n"
],
"text/plain": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ conv2d_6 (\u001b[38;5;33mConv2D\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m26\u001b[0m, \u001b[38;5;34m26\u001b[0m, \u001b[38;5;34m5\u001b[0m) │ \u001b[38;5;34m50\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ flatten_6 (\u001b[38;5;33mFlatten\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m3380\u001b[0m) │ \u001b[38;5;34m0\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_12 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m100\u001b[0m) │ \u001b[38;5;34m338,100\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_13 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m) │ \u001b[38;5;34m1,010\u001b[0m │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">339,160</span> (1.29 MB)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Total params: \u001b[0m\u001b[38;5;34m339,160\u001b[0m (1.29 MB)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">339,160</span> (1.29 MB)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m339,160\u001b[0m (1.29 MB)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"Training TensorFlow model...\n",
"Epoch 1/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.1523 - loss: 0.0862 - val_accuracy: 0.1100 - val_loss: 0.0849\n",
"Epoch 2/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.4801 - loss: 0.0740 - val_accuracy: 0.7204 - val_loss: 0.0540\n",
"Epoch 3/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.8133 - loss: 0.0399 - val_accuracy: 0.8482 - val_loss: 0.0314\n",
"Epoch 4/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.8680 - loss: 0.0269 - val_accuracy: 0.8718 - val_loss: 0.0247\n",
"Epoch 5/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.8837 - loss: 0.0220 - val_accuracy: 0.8798 - val_loss: 0.0213\n",
"Epoch 6/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.8924 - loss: 0.0195 - val_accuracy: 0.8872 - val_loss: 0.0195\n",
"Epoch 7/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.8987 - loss: 0.0178 - val_accuracy: 0.8900 - val_loss: 0.0183\n",
"Epoch 8/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.9032 - loss: 0.0166 - val_accuracy: 0.8978 - val_loss: 0.0173\n",
"Epoch 9/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.9081 - loss: 0.0157 - val_accuracy: 0.9012 - val_loss: 0.0165\n",
"Epoch 10/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.9114 - loss: 0.0150 - val_accuracy: 0.9030 - val_loss: 0.0158\n",
"Epoch 11/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.9143 - loss: 0.0143 - val_accuracy: 0.9070 - val_loss: 0.0152\n",
"Epoch 12/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.9170 - loss: 0.0138 - val_accuracy: 0.9084 - val_loss: 0.0149\n",
"Epoch 13/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.9195 - loss: 0.0133 - val_accuracy: 0.9106 - val_loss: 0.0145\n",
"Epoch 14/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.9227 - loss: 0.0129 - val_accuracy: 0.9126 - val_loss: 0.0142\n",
"Epoch 15/15\n",
"\u001b[1m1407/1407\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 2ms/step - accuracy: 0.9246 - loss: 0.0125 - val_accuracy: 0.9158 - val_loss: 0.0139\n"
]
},
{
"data": {
"image/png": "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",
"text/plain": [
"<Figure size 800x500 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import tensorflow as tf\n",
"from tensorflow.keras import layers, models\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"# 12. Industry Standard Comparison: TensorFlow Implementation\n",
"print(\"Preparing data for TensorFlow...\")\n",
"\n",
"# Convert the lists we created earlier into NumPy arrays for TensorFlow\n",
"# TF expects spatial data in the shape: (samples, height, width, channels)\n",
"X_train_tf = np.array(x_train).reshape(-1, 28, 28, 1)\n",
"Y_train_tf = np.array(y_train).reshape(-1, 10)\n",
"\n",
"# Recreate the exact same optimized architecture we built from scratch\n",
"tf_model = models.Sequential([\n",
" layers.InputLayer(input_shape=(28, 28, 1)),\n",
" layers.Conv2D(filters=5, kernel_size=(3, 3), activation='sigmoid'),\n",
" layers.Flatten(),\n",
" layers.Dense(100, activation='sigmoid'), \n",
" layers.Dense(10, activation='sigmoid')\n",
"])\n",
"\n",
"# Display the network summary to verify the new parameter count\n",
"tf_model.summary()\n",
"\n",
"# Compile using the exact same optimized parameters (LR=0.3)\n",
"tf_model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.3), # <--- Updated to match custom LR\n",
" loss='mse',\n",
" metrics=['accuracy'])\n",
"\n",
"print(\"\\nTraining TensorFlow model...\")\n",
"# Train the model for the full 15 epochs\n",
"history = tf_model.fit(X_train_tf, Y_train_tf, epochs=15, validation_split=0.1)\n",
"\n",
"# --- Plotting the TensorFlow Learning Curve ---\n",
"plt.figure(figsize=(8, 5))\n",
"plt.plot(history.history['loss'], marker='s', color='#ff7f0e', linewidth=2, label='TF Training Loss')\n",
"plt.plot(history.history['val_loss'], marker='^', color='#d62728', linewidth=2, label='TF Validation Loss')\n",
"plt.title(\"TensorFlow CNN - Loss Convergence (MSE)\")\n",
"plt.xlabel(\"Epoch\")\n",
"plt.ylabel(\"Loss\")\n",
"plt.legend()\n",
"plt.grid(True, linestyle='--', alpha=0.7)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "39b6b9a4",
"metadata": {},
"source": [
"### 7.1 Model Evaluation & Metrics"
]
},
{
"cell_type": "code",
"execution_count": 70,
"id": "d0f80dca",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Formatting test data for TensorFlow...\n",
"Evaluating TensorFlow model on Test Set...\n",
"TensorFlow Final Accuracy on Test Set: 92.69%\n"
]
}
],
"source": [
"# --- 7.1 TensorFlow Model Evaluation on Unseen Test Data ---\n",
"print(\"Formatting test data for TensorFlow...\")\n",
"\n",
"x_test_tf = []\n",
"y_test_tf = []\n",
"\n",
"# Read the test file\n",
"with open(\"mnist_test.csv\", \"r\") as f:\n",
" test_data_tf = f.readlines()\n",
"\n",
"for record in test_data_tf:\n",
" values = record.split(\",\")\n",
" \n",
" # 1. Reshape the image to TF spatial format: (28, 28, 1)\n",
" img = np.asarray(values[1:], dtype=float).reshape(28, 28, 1) / 255.0 * 0.99 + 0.01\n",
" x_test_tf.append(img)\n",
" \n",
" # 2. Create the target vector (One-hot encoding) matching the training phase\n",
" target = np.zeros(10) + 0.01\n",
" target[int(values[0])] = 0.99\n",
" y_test_tf.append(target)\n",
"\n",
"# Convert lists to optimized NumPy arrays\n",
"X_test_tf = np.array(x_test_tf)\n",
"Y_test_tf = np.array(y_test_tf)\n",
"\n",
"print(\"Evaluating TensorFlow model on Test Set...\")\n",
"\n",
"# TF automatically calculates loss and accuracy using the evaluate function\n",
"test_loss, test_accuracy = tf_model.evaluate(X_test_tf, Y_test_tf, verbose=0)\n",
"\n",
"print(f\"TensorFlow Final Accuracy on Test Set: {test_accuracy * 100:.2f}%\")"
]
},
{
"cell_type": "code",
"execution_count": 71,
"id": "ab931ce8",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Gathering predictions for TensorFlow CNN on Test Set...\n",
"\n",
"==================================================\n",
" METRICS: TENSORFLOW CNN\n",
"==================================================\n",
" precision recall f1-score support\n",
"\n",
" 0 0.95 0.98 0.97 980\n",
" 1 0.96 0.98 0.97 1135\n",
" 2 0.94 0.89 0.91 1032\n",
" 3 0.88 0.92 0.90 1010\n",
" 4 0.94 0.91 0.93 982\n",
" 5 0.95 0.84 0.89 892\n",
" 6 0.92 0.97 0.94 958\n",
" 7 0.94 0.92 0.93 1028\n",
" 8 0.91 0.91 0.91 974\n",
" 9 0.89 0.93 0.91 1009\n",
"\n",
" accuracy 0.93 10000\n",
" macro avg 0.93 0.93 0.93 10000\n",
"weighted avg 0.93 0.93 0.93 10000\n",
"\n"
]
},
{
"data": {
"image/png": "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tr90gJqI81zU6IpWY/H+K7q/hazZPp/nO7f/J1vZKlSsLOeffHD/vjzvxf1MKmpxat+2FWrWqi33WwTXXTu2yQvyhGwAUcLxvnHtGnp17yKn3xMzA2h/r21tVuv7udCtUzs0adZCfo7t3bMLHocOYO7CpbIURC02bVgnL8LKliuP169e459Zf6FipSqoVqMmlMhEIwrOEsnZs2eRKlUqpEkTdXTd8ePH5eCqjh07xuqxEzKs/tKqOUI+6V+lCI0aN0Pjps2gVkrab9GNHV/GjR4pP6wimzVngW6S6OfPn2Hl8n/lCGIzU1Nkz5ELrdu2i/dJpFO3XxUnjyPegztVzopahdMi+FM4dpzzklNViWmntET9affq2VE4c3J8CgvHbW9/LNx3B14+X6aq2jO6KqzMo36z1b+H7slBXHHlxbLWSEhirs1lS5fgxfNncE+XHh07d0mUmR4iHo+4NnZU9Of57LlfznMxQfyeXTvx8uVLuLi4yPBetXpN3ajp+JKQ34Tm6+sra86vXb0iu0pFXV/zlq2QOhFGgSfm8d723xasXbUy2r9dvT5+Z8KIz1QSk/dz8U2EixfOkzMTiUGEohFCvO7jW0Jm4fDwcPnlCIcPHYSlhSUqVq6CuvUbxPtrOTq2FibKDqvxKSHDKiW++AyrShZXYdXQJHRYVYr4DC9Kpqav7f0Rxnq8jXS3EzSsKklMwqpxDdsmIiIiIoPCsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKZaLRaDRQoaBQGCV1Hs3vMzFJ7C2ghOTedb1RPuFe85vCGIWHG+cbm6kp39iMyceQMBijZLZm312HLatEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRY5jFd8e3btzF+0KRJk8Z2e4iIiIiIfjysJkuWLKarQqXf4EpERERESg2r586di98tISIiIiKKbVgtXLhwTFclIiIiIkrcAVahoaE4c+YM1qxZo1vm7+8fN1tFRERE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X0yO36JJI+TJlw8Xzp1D0WLF0aBhY6hZj66dZA2nmHpswrgvraply1VAufIVoFbtDOx4m2gU0J8jWkKvXLkiZwgQQS9nzpxIkSLFTz1mfIbVw4cOygl1I6tdp67eHKpivtVzZ8/IYF60eIkYlTT8rIgTVycEMXLw+vVrsDA3R6bMmZEhYyYYG/ENR2Zm5ihRshTU7OXLl9FO25QxYyY532xCSuh3LXGe37h+DdY21siePSfcUqaEsRC1uZ6ej+R7coGChWFj8/UpnOJLqvar4uyxxAwAZXK6Ijg0DMduvMS7j58bSrTalM8E8wilD1qXHr3B5Udfpr3K6JoE5XK5YfWxBwj+FD8lIc//bYWEJErVzp87i+fPn8HdPZ2qR8RriS/rCQ0LjbI8V67c352m0tCFKeR4W5sbSFiND/EZVpUsocMqUWJQ57sWfU1chlVDktBhlUipYZVft0pEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIplotFoNFChoFAYpXB1Hs7vMtLdhqmJCYyRBsZ5wI31eBsrl9bLYYxerWwLY/QpLBzGKInV99tN2bJKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKxbBKRERERIrFsEpEREREisWwSkRERESKZZ7YG6AWgYGBuHrlMvz8/JA+fXrkyJkLahQYGICjHh4wMzNDlWrVo/xeo9Hg1s0bePzYEylSuCB/gYIwNzfs00y7T17/36d8X9kn8dwcO+IBU9PonxtDt3/fHrx/9z7KcreUbihZqgzULCDgA65e/vz6zpI1K7JkzQZjEB4ejksXL+DZs6dIly498ubLD2Ogxv22tzZH0awpkDyJNa57+eHmk7dfXdcpiRVqF06Lx68/4Mj1F7Fex1D4+vri2tUrCA0NRfYcOZA6dRqokeejR7h75xZs7ezkOe3g4BhlHR+f17h4/hzMzMxRuGhRODomhRIYdopQiD27d2H2zBlwT5cOdvb2OHfmNDJnyYq/Z8+VJ4VaTJs8UQYWGxtbkeCiBDIR6EaPHA4LCwukdXfHndu35Jv+33Pmyzd8QyT2acxvEfbp1i2Ea8Lx9z/z4R5hn36f8uW5EeFWjWH17p3b8Hn9Wnc/LDwc27ZuRpNmLVQdVi9eOI/B/fsiZapUSJU6DX6fOgnVqtfA0BGjoGZBQUHo2b2LvPDMkycfLl44h0KFi2LaHzPkxapaqXG/S2R3wfK+5fDE5wMev/qAKb8UweZTnhi49Gy06y/oUQplcrlh76WnXw2iMVnHEEyfNgX79+5BlmzZYGZqiuFDTqJN23bo2acf1CIgIADDB/fH82fP5IX2ixfPce/ObYwcMx5Vq9fUrXfowD6MGj4UefPnR0hwCMaPGYnpf81G4SJFkdgYVuNAsmTJsG7TFtjZ2cv7b968Qa1qlbF162a0bNUGapEpc2b06LUbK5ctxa4d26P8PjwsHJOm/i6DuhAWFoauHdth8vhxmLdoCQyRCNsTp+jvU7dO7TB5wjjMXfhlnzJmyozN23Zj5fLonxs1+LVXX737Rz0Oy7DasFETqNnIYYNRplx5jB43Qd5/9fIlGtWrhWLFS6JCpcpQq3+XLILno4dYv3kbnJyc8MTLC00a1sPWzZvQqElTqJUa93vBr6Wx56I3ei04Je+nTGaDs3/Uw+Frz7Hz/BO9dXvWygkTExMc/UYAjck6hiJnzlzo3bc/LC0t5f3Tp06ia6f2KFWmLAoULAQ1CA39hLbtO8qLLq2Zf/6OqZPGo0q1GvJYfvjwAeNH/4Z2nTqjU5fucp1J48dgzMih2LpzX6L3kCZazerjx4/x9u3XuyEMSbHiJXRBVXB0dISNrQ0+ffoENWnUpBns7b/sZ2S58uTRhTpBtEKUKFkKDx7cg6HKlTvqPhWPZp++99yo0ZbNG5E9R07VlrwIb9/6ydaIchUq6pa5uLrK/d6x/T+o2Z7dO1Gtek0Z2ATRs1CmbFns3rUDaqa2/Xayt0K6FPbYdeFLKH3u9xFXHvmieZmMeusWyOiMX2vmQPe5J6D5yuPFZB1DUrN2HV1QFYqXKCl70h7cvw+1cHRMqhdUBVdXN1n2oHXy+FFZyta4aXPdsuYtW+PF8+e4evkSEluihdUZM2YgVapU+OWXX3D8+HEYunf+/ti8cQNWrViGbp07IEeOnGjU2DCvwuPSiePHkC17Dqhun7Kpa59+1BsfHxw76qH6c1zUdNna2uLe3Tu6ZSEhIfDyeowH9w33Iux7xIX2Y09P2WMQUabMWXCf+21Q/AKC8f7jJ+R2T6ZbZmluikxuSZAzbVK9mtalvcug/5IzeOUfFO1jxWQdQydaVsX5r7bPLeHs6VPYvHE9Zv31B9asXI6Ro8fJVlVBvJ85OTsjadIv50mGjJlkA40S3usStV23SJEiOHHiBJYvX47s2bOjc+fOaNu2LZInTw5DExQchKtXL8sBKJ6ej1C2XIVEbzZPbIsXzseN69ewbNVaqMWSRfNx8/o1/LtSPfsUG9u2bYG5hQVq1KoDNTM1NUWPXn3w94w/8NbPTw68ELXJVpZW+PD+A9TqY2CgLIFxcHDQW+7g6IiAD9xvQ6LRABPXX8aYFgXhnMRKDoiqXyw9gj+FwcH2S4vizM4lZFnA7gveX32smKxj6BfhY34bgarVayBP3rxQGy+vx7hx7SoePXwAK2srJInw+g74EIAkSfRf7yLIih5DUfNq1FNXNWjQAPfu3cPhw4dRqFAhjBw5EqlTp0bz5s1x8OBBOVAlJoKDg/Hu3Tu9m1iWkFxcXDFm3ET88dff2LD5P9nqtGDeHBirjevXYv6c2ZgyfYbsMlXVPv2unn2Krf+2bEK1ajWMovShVZtfsGDJMjlY8skTL3To1EXWsNrZq2fwZGRW1tbyvwGB+h9SgQEBut+pkVr3e87uW6g9fi8+BIUig0sS/PnfNVnDKlpchdI5XVG3qDvuPPVH2wqZ5S21sy3ck9vJn+2szGO0jqGX/HTt3B6p06TB+IlToEaNmzbH6PGT8O+qdahZux4G9+st91sQ4VWUAUQ305GVlRVg7POsiuRevnx5rFy5Es+ePZPlASLAVq5cGZkzZ5ZB9nsmT54s60Qj3n6fOhmJJVkyJzl67ooC6jwSg+hmEDMHTJ72BypUrAS17JMY8T9p2h8or5J9iq1LF8/LKVAaqrwEIKJ8+Qvg1159MGT4SBlUxTR1aq7VFR9Oojb32dOnesufenvDPa071ErN+332ng8mrL+MwcvOyRH8Yhqryw/fyN/5B4Rg7bGHyOWeDEWypJC3pHZWcnoq8bOVhVmM1jFUIrB16dBOlv3MmjMf1gZ8YRJTlapUlUFU28WfNq07fN+80WvoE4NJRUmEqNtObIq6FEqaNCl69Oghb5cvX8bixYvh5eX13b8bNmwY+vfvr7dMY5ZwVwJPn3rrzcv2KSRETnkkPuCMzZZNGzFl4ngZVMWLQQ22bt4oR02KoFqpsjr26Wds2bxJ1i4ay/n96tVL2XOidfbMaVne0qf/QKhZufIVcGD/PnTu2l0OOBGti0c8DqNp8xZQMzXut1syG7zw+6i7XzaXGwpmTI7fVl2U96899tPNFKC1fnBFBH0K0y33/RD83XUMkf/bt+jSsT3skyTB7LkLZI262rx88QLJU6TQm3pNNKaJxsJUqVLL+yVKlZHTER4+sB/Va9WWy/bs2gE7OzsULFwEiU1RYTWi/PnzY9asWTG+Go7cTB30ZZBbvBs+eKCcczNrtuwIDg7C/n17EfQxSL7ZqYmYqsjHxwe3bt3Eh4APckCZUKNWbdjY2MgJ8SeMHYWy5SvA//8DzrQaNjbM6Y1EOYfcp3IV5CC6LZu+7FODCFM2HT1yWNY73b51U04gr12ves3Pz41aiH0TcxL27K0/jZWanTtzBtv/24rSZcvi9atXshyk26+9FDH3YHzq0q0HWjVvgl+7dUbJUqXl+5qDo4Msi1AzNe53uVxuaFE2E/Zffgq3ZLboUDkrJm28jBO3XsLY9ejWGU+8Hsv3tD27duqW58ipnplObt64hiUL56N4ydJwTp4cDx/cx67t29Chc1ek/H9YdXVzQ8fO3TB5whg8evRAzrO6dvUKDBw6Ara2iV/yZKKJaWFoHLt06ZJM7FmzfpkWKC4lZFgVc28ePLAP165elYOqxHykVavV0JsOI6GEx+PhXLp4IbweP46yvN+AQXLgxfFjR3Fw/75o/1Y7R2V8ia/dPiH26UD0+zRq7Jd9+lc8N15Rn5u+/T8/N/HF9P8jOROKCOPr1qxC3wGDEvWbTTQJPGmO+GIAj0MH5WtazK0qpjRLDAl9vMU3+4ieBTF9jfjSk/oNGxtFnbJS9tul9fI4/WKAWoXTyoFVO849waX/lwB8Tddq2fEpLBxLDtz9qXVi49XKtkgoE8aN1pvCSat8+YoJXvIlnsv44v3ES34+i56iFC4uKFO2vOwhi+zk8WM4deKY/AYrsf/5E2Cu2SRWpsoNq/EtIcOqksRnWFUyI93tBA8vSpHQYVUpjPV4G6u4DKuGJCHDqpLEZ1hVspiE1UQfYEVERERE9DUMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYDKtEREREpFgMq0RERESkWAyrRERERKRYJhqNRgMVCgqFUVLn0aSvCQs3zgNuystsMgImMIExytBjI4zRozmNYYxsLL6/Dt/yiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIscwTewPUJiQkBPfu3oGjY1KkSZsWxsD3zRv4+r5B8hQpkDRpMhiTp0+9YWJiglSpUkONgoOD8eypN5KncEGSJEm+ul5gYACeP3uG1GnSwtraGmo9z/38fFW9j8a8348ePkRYWCgyZ8n6U+sYOjW+nydPYiVvL/2D4BcQEut1hLTOttBoAG/fQBiy+/fvITgoKMpy+yRJkC5deigNw2ocmz5tCtavXY1Klavij7/+hpq9evUSQwb2w907t+GWMpUMboUKFcbkaX/CwcEBanb50kWMGz0Sfm/9kNQxKRyTJsWUaX/CLWVKqMHzZ0/xz6y/cNTjEFK4uOLF8+coXrIURo+bCAcHR916nz59wow/puK/zZuQKnVqfHj/Hu06dkazFq2hFk+8vPDb8CF4+PABnJ2d4ePjg34DBqFh46ZQM2PZ7y2bNmLDutV47OkJZ+fk2LZ7X6zWMXRqfD93dbTG/K7FkSuNI576BsI9uR1O3/VBt4Vn8O7jpxivIxTO5Iw/2xaCk70lfANC4PchBN0XnsEzv48wRPP+mSUbIiK6efMGataqg0lTp0NpGFbj0KGDB3DxwjkUK14CxuDP6dNkONl36Cjs7OzlFXmLpg2xYN4/GDh4GNTq8WNPdO/SEa3atEWPnn1gamqKa9eu4tmzp6oJq6IFqWTpshgzfjLMzc3lse3SsS2mTByHSVP/0K03ddI4nDxxHGs2bIF7uvSyZ2HzxnVQk2GDB8gP670Hj8DGxkZeqHTt2A6ZMmdBvvwFoFbGst+3b93EyNHjcNTjMHbt2B7rdQydGt/PRzfJCwcbc+QftBMBwaGy5XTvyEroXycHxqy/GuN1MrjYY13fMlhw8B6m/XdDtqwWSJ8MaZPbGWxYnT5DvzFNvL7btWmBOvUaQIkUV7Mqrt7Pnz8Pf39/GBLR8jRpwlhMnjodFpaWMAY+r18hZ67c8o1NcHJ2RuYsWeDz+jXUbPHC+XBzc8OvvfrKoCrkyZMXBQsVhlqULF1GXmGLoKo9ttVr1pYXY1pPvb2xdfNG9Ok3UAZVwdLSEs1btoFavH/3DjeuX0Pjps1lYBPyFyiIXHnyYtMGdYVyY93vYSNHyfexn13H0Knx/Vy0ml7x9JMhVPB5H4w7T9/J5T+yTp+a2fHULxBTt34OqsIlTz+cuecDtdi6eaPsHSteoiSUKFHD6rhx45AsWTJkz54dV69excqVK5E2bVoUKVIELi4umDt3LgxBWFgYhg4egPYdOiFL1mwwFh06dcGxo0ewaeN6XLp4ASuWLcWtmzfR5pf2ULPTp06gbPkKCA0NlXU/vr6+MAZ3b9/Sq809e+aUrNctU648Xr9+Bc9HD/Hp09drvQyRtY0NzM0t5EW0lkajgZ/vG9y6eQNqZaz7bczU+H4+a88dVM6bEq3KZECRTM7oWiUL8qRLinn77v3QOmVzumD/lecwNzNBtlQOcLZXV4NUYGAA9u3djQYNm8j3dCVKtDKA06dPY+rUqRg5ciTevXuHbt26wdPTE7Nnz0bhwoWxd+9e9OvXD7Vq1YK7uzuUbO4/s2BtbYOWrdvCmBQoWBgVK1XGH9Mmw80tJZ4/f44WLVsjW/YcUCvxgS1aGt76+aFe7WqwsrSStV7Zc+TExMm/q6YMILJDB/bh0MH9mDHrywWkCKhiIOGM6VNxxOOwbIETYaZnn/5o2rwV1MDCwgINGzfBvDniNW6FVKnTyG7g169ewcbGFmplrPttzNT4fi5aPnddeoqxTfPime9HpHayxeJD93H9ydsfWsfV0UbWqp6cUB1Bn8KQMqkNrnu9xa+LzxpsGUBEe3fvkoNp6zVoCKVKtLB66NAhdOrUCcOGfa6FqVOnDgoWLIiOHTvK+/ny5YOHh4cMtd8Lq+JJFreINGZWsLKyQny7desmlv+7BNP++As3b1yXy0TdT7BFkOxGy5o1m2rLAkYMHSQDy96DR+VI8Tc+PujQrhUCAgMwbMQoqJG46jQ1NcPBg/uxYtU6ZMiYCe/fv0f3Lh0wfuxv+GfeIqjNubOnMXL4YPzaux/KlC2vW25maiZHiYvnY8+BI7IkYs+uHRg5bBBy5MiFPPnyQw0GDR0u6zQP7t+H9x8+oFSp0nKQ0cED6htkE5Gx7rexUuP7+eyOReGW1BoFBu/E+4+f61G3Di4Pe2tzDF9zOcbrhIVrULNgatSafBj3X7xHEhtzrOtbFtPbFELLv4/D0G3ZvAllypaDi4srlCrRygA+fPgg6/60UqZMqXdfSJUqVYxqVydPngxHR0e92+9TJyMhBHz4gEyZM2P+3NmYMG60vN2/dxe3b92SP7/1/3J1piai9OHokcOo16CRbkoj5+TJZZ2jaIVTM3GulixZWgZVQex/nXr1ceH8OdnyqiYXzp9Fv1490KFTV7Tv2EXvdylTpZL/bd6yta52V9S1iuluzp8/C7UQdbtNm7fAzH/mYcmylejYpRvu3LmNjBkzQ82Mdb+NkRrfz01NgKp5U2LNcU8ZQrX1qJvPeMngGdN1BDFLgMeNlzKoCmLd9ac8UTxrchi6hw8e4OqVS2jYSNmzfCRaWM2UKRN27NghW0Tfvn0rW1C3b98uRxMLojRg//79cr3vEa2zItRGvA0akjCjFwsXKYo16zfr3fIXLISixYrLn1OkcIEamZmZ/f/qW7/4XnSRO6pkbr6vEVM4+UTab9EKkcTBQbH1PrFx6cJ59Pm1G37p0AmdunSP8vsiRYvJ8+B1hAEYHwMDZf2TKA9QC+17kpaozb14/hxq160HNTPW/TZGanw/D9dATj3lEmGglCAGTolpp2K6jnDkxsso67g4WMM/8MvUVoY8sMrF1RWlypSFkiVaGUDTpk0xevRouLq6yrkaBwwYgFOnTiFnzpzImzcvzpw5g+TJk6N8+S/djl8juvsjd/kHfb5IonjUpFkLWQIh3sxEucPVK5dld8LgocNV/by379gZLZo0xIw/pqFsuQp4cP8eVi7/F91/7Q21ECUsvX/tImcFKFW6DG7euKb7Xc5ceeR/xfyrLVq1xZQJY2Sdqp29PVatWIZkTs6oXLUa1EKMfhfTkpUVA8levZbzz1asVAXVatSEmhnLfosQHhAQILvARUAX576QNVt2Wbsb03UMnRrfz5d5PED3qlll8Lz51B+FMjihRekM+G3t5R9aZ/aeO9j3WyX81igP9l99LgdZdamSBb9vuwlD9unTJ+zY/h8aN20mL1iUzESTiP2Wz549w/r16+XI/+bNm8PPzw+TJk3C7du3kTt3bgwdOlTOFhAbiRlWf58yCeYWFnIC7YSWkEdTnDq7dm7H4YMH8OaNj6x3qV6zFipUrAy1E3OtLl20AJ6ej+Q3vdSoURuVqlRN8O0QtVTxYft/W7Buzcpof7dy7Sbdz+Hh4di8cT0OHdyH8LBwORijbfuOcuL0+PT/qoMEIfZRfNHH4UMHYWlhiYqVq6Bu/QaKf3P/Wcay32NHjcSd27eiLJ89d4Gcvimm68QHE5gY5ft5hh4b4+yxGhZLi5oFUiO5gzVe+H3ElrNe2Hvl+Q+vI+Za7VUjGzK5JsEr/yC5zq5LzxCXHs1pjIR0+dJFTJs8AdP/mpWo38JoY6HwsBqfjLVlVZ1HkxI6rCpdQoZVosSSkGFVSeIyrBqShA6rShGTsMq3fCIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiwTjUajgQoFflLlbn2XCUxgjEyMc7cRHm6c57mxMjHSE91Idxvh6vx4/i5j/Rxza7sCxsh/TZvvrsOWVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLPPE3gBDdOf2LWxYtwa7duxA8uTJsW33vlitY+jq16kOz0ePoiyvWKkK/pw5G2p16+YNLFm8EBfOnUNoaChy5c6N3v0GIEeOnFAT3Tm88//n8K6vn8Pv379HiyYN8PSpNzZs3obMWbJC7fu9fdtWrFi2FF6PPZEpcxb0GzAYhYsUhZq8fPkSs/76A8ePHYGJiQmq16yN3n36w8bWFmq2/b+tWDB/Lp4/ewr3dOnRu29/lK9QEWr24cMHzJk1E4cPHoCfny+yZsuO/gOHIH/BglAzNX6OJbGxwIgm+VC7iDuSO1jh+mM/jFh5AWfuvtat45rUBv3q5kLNwmnhnMQKD56/w6ydt7DhxJfn4tz0usia2jHK428/64XWM44gIbFlNRYmjh+DbNlzonHTZj+1jqHbun0PLl+/o7v9t2OPXF65ajWo2T+z/0aVqtWwYfN/2LpjN9zcUqJLh3byg11N5DmcI2bn8ISxo5ApSxYYy36LkDp5wjh07tIdHsfPYPykqdizawfUxN//Ldq1aYEPH95j1bpN2LX3EDJkyIhTp05CzU4cO4oxo0agS9fuOHTkBOo3aIQBfXvh5o3rULPRI4bh9KmT+HvOPBw6dhK16tRFj66d8MTLC2qmxs+xud1KokKelGg67RAyddmAtcceYvOwSsjgYq9bp2PlrLjh9RbVRu9Btu4bsfjAXczvURKV8qbUrVNk4DY4tlihuxXst1Uu33rmcYLvk6LCqmilMgTLV61Dk2bNYfuN1oWYrKM2WzZvhKNjUlSqXBVqNnvOfFStVgPOyZPDyckJw0aOQmBgAE6fPAE1kedw0++fw5s2rMOLF8/RqXM3GMN+v33rh39m/YVfe/VBlWrVYW1tjYwZM2Hk6HFQkyWLFuBTSAim/D4DqVOnka2pTZu3RMVKlaFmy/5dgrLlK6BOvfpwcHRE23btkS1bdqxcsQxq9fHjR3gcPohOXbohS9ZssLW1Q7MWrZAhY0asXb0SxsTQP8dsLM1Qs3AaTN96HTefvEVAcCgW7b+Lu0/90aV6dt16kzZewQqP+3ju9xEfgkKx7NB9PPP9iMJZUnz1sdtWyAzf98HYfs7LuMKq6DocPXo08uTJA0tLS1hYWCBp0qSoWbMmDh06lJibRrG40Nix7T95NW5lZWVUz987f3+EhYXBPkkSGJsHD+5j7j+zMHHy7zA1U9S1b7w5deI4goODUaNmbajZ4UMHUaFSZRnGjYVGo8HVK1eilHMULV4CVy5fgmppNHLfTUyi/urSxQswFmr4HDMxMYH4nziekZXI5hLt39hamaNF2YxIZm+JvRe9o13HzNQEzctkxNrjDxH8KRxGU7MaFBSEMmXKyA/5AgUKIDAwEGnSpEHVqlVx+PBhVK5cGX///Td69uyZWJtIP+DYUQ/4+LxGw8ZNje55mzploiwFKFmqNIyJeA0PHdhP1uumSZsW/jfewhh4e3sjmZOTbImaP/cf2U0uWqN69u6nqprVZ0+94ejoiF+7d8b5s2fg5OQsu0Z7/NpbtTWrAQEB+PgxEE7JnPSWi3338fGBWonjWap0WSxeuECey6Ilfcf2bbh966bsQTIWavgcCwwOxf4rTzGgfh7Zzf/49Qc0L5MB+TI44eXbIL11c6RJitO/15E/fwwJRa8Fp3H5kW+0j1utQGq4JbPFskP3kBgSrSlk9erV8o3wypUrWL58Oa5fv45Xr16hbt26OHDgAHbt2oUhQ4bg2bNn330s0crx7t07vZtYRgln6+aNyJuvADJnVkfdYkzNmjkDx48ewfQZM2FjYwNj8tcf05AhYybUrdcAxiQ8PBxv/fywb+8eLF2xGnv2eyB/gYLo1aMLHj/2hFqIlpllSxfL4+tx7DR+/3Mm9u/dg2lTJsLYaKCRrVVqNm7SFOTOkxfdO3dExbIlZVlT46bNYWZqBmOhls+xbnNP4sJ9H2wdXgkP5jdBxTypsOTAPYSF67e23vJ+K2tR3TuuxdBl5zGnWwnUKJQm2sdsUyEzztx9hdve/jCqsHrnzh1Uq1YNpqafN0F80JcuXRonT34u3q9evbpsZY1JOcDkyZNl8I14mz51crzvA332+vUrnDh+DA0bNzGqp0R0f69euRz/zFso3+SNzaVLF7F/3x4UyJNd3lo3/3z8mzSsi1EjhkKtUri4yCDXp98ApEqVGkkcHNC77wCYW1jg2BEPqIVoURO9BdWq15Qtb+Icb9XmF+zfvxdqZWdnBxsbW/j66bcu+fn6wjm5M9QsWbJkGDN+IvZ7HMOp85fxx8xZ8Hn9GqnTRB9e1EZNn2O+74PRc8EpZOuxCSnbrZEj992S2sDz1fto1/cP/IR/D93DvkvP0KFS1JlcxMwBVfKllnWtiSXRwmqqVKlw7do1vWU3btyAi8uXmgoxbYyov/ieYcOGwd/fX+82cMiweNluin6aF1HXVq1aDaN5eubNmY3l/y6RQbVgocIwRus2bsWla7d1t5VrN8jlYuqqcROnQK1EK2q0NBrdxbca5M8fdT9FSDc1Uc8+RiY+b/Lmy4dzZ8/oLT975jTy5S8AYyIGEp46eULWLRsDNX+OJbO3RIW8KbHz/JNvrmdhbiJ7ESJrWTYjAkNCseV0ws8CoJVo7zoNGjTAtm3b0LFjR8yZMweNGjXCvXv3UKFCBfl7Pz8/2coqWl+/RxRCOzg46N0MtTjaEG3dskkONlFrHVtkC+fPld2jxhxUjZkY+V++QiXMnPEHnj9/hvfv3uHvv/6Q5QHlyqtnLs627TrIqYz27tklR4tfv3ZV9iRUr1kLavZLuw6yhVyEFzF4csWyf+Xcu63b/AI127JpI3bv2oGAgA/wfPQQg/r1Qbr06dGkWQsYAzV9jrUpnxmNSqaHvbU5Mqd0wPK+5eQ8qov339Wts6xPWRTPlkKuk9zBGj1q5EDlfKmw+siDKI/XunxmbDzxSNbDJhYTTXRDxhLIvn37MGDAABlSc+fOjdmzZ6N48eLyd7dv35bF7oUKFYrVYwd+ir/dat+mJS5fuhhl+Z4DHnB1c4vxOvEhoeuqLpw/h47tWmPN+s3IkTMXEksMGuDjTJECeRASEhJlebcePdH9114JXD8Zj+d526+cw/ujP4dv3LgmSwEM/UsBYrLf4gN9+rQpOHRgP8LDw5Atew706tM/3lvfYtLTFJeOHvHA7Jl/wtPzEZKnSIHqNWqja/dfE7wxIIF3+/OXAsybIy9G5JcC9OmH8hUrJexGiNd3An48i5bUP3+fKmeBsLSwRMXKVdCrTz85fVdCM9bPMbe2K+KsJXVi68KoVTgtQkLD5CT+49ZdxtuAEL2ZAQY1yINCmZMjNCxc1q/O2nETey891XusktldsHt0NZQdthNXPKMffPWz/Ne0UXZYjU/xGVaVTO2DAJTyYaYU8RlWSXkSOqwqhZHudoKGVSUx1s+xuAqrhiYmYVW9xUdEREREZPAYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEixGFaJiIiISLEYVomIiIhIsRhWiYiIiEi5NBSngoKCNKNHj5b/NSbcbx5vY8DznOe5MeB5zvNcaUzE/yV2YFaTd+/ewdHREf7+/nBwcICx4H7zeBsDnuc8z40Bz3Oe50rDMgAiIiIiUiyGVSIiIiJSLIZVIiIiIlIshtU4ZmVlhdGjR8v/GhPuN4+3MeB5zvPcGPA853muNBxgRURERESKxZZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLPPE3gA1efHiBZ48eYKMGTPC2dkZxuLNmze4desWsmXLhhQpUsAYiO/SePDgAT59+iSPtzENqPP29oaPjw8yZMggvwDDmAQFBeH8+fNInjw5smfPDjUT72WPHz/WW2Zubo7ixYvDWF7jd+7cgYmJCbJmzSr/q2YXL15EYGBglOXJkiVDrly5oHZeXl549eoVUqVKJW/Gco4/efIEr1+/lud4kiRJoFiJ/RVaahAWFqbp0qWLxsrKSpMzZ0753+HDh2vU7vbt25q2bdtqUqZMKb4FTbNixQqNMZgzZ47G3d1dkylTJk3WrFk1Tk5Omn///VejdkeOHNEULFhQkz59ek3evHk11tbWmu7du2tCQ0M1xqJz584aU1NTTaNGjTRqN378eE2SJEk0pUqV0t2qV6+uMQaHDx/WZMyYUZMmTRpN/vz5NUWLFtU8evRIo2YtW7bUO9biJt7X27Rpo1Gzx48fawoXLizfxwsVKiTP+fLly2t8fHw0av/8LlSokCZFihSafPnyyf3++++/NUrFsBoHZs+erXF0dNTcunVL3j958qTGwsJCs2nTJo2abdmyRbN06VJNYGCgUYXVsWPHary9vXX3Fy5cqDEzM9NcvXpVo2bi+GrPceHatWsaS0tLeQ4Yg/Xr12sKFCigqVKlitGE1WLFimmMjTjHbWxsNOPGjdMtu3TpkubEiRMaY3L06FH5vn7w4EGNmjVt2lRekIjPMeHNmzeyMaJPnz4aNStQoICmVq1amqCgIHn//PnzsqFNHHclYs1qHFiyZAmaNGmi6xYsUaIEKlWqJJerWf369dGuXTvY2NjAmIwaNQqpU6fW3e/YsSNMTU1x6tQpqFnr1q31ur5z584tyz6ePn0KtXv06BH69OmDVatWwdLSEsYiNDQUV65ckd3h4mdjMGnSJFnaM3LkSN2y/Pnzo2TJkjAmixcvRqZMmVChQgWomegCF8dX+znm5OSEHDlyyOVq9fbtW1y6dEl+dmlL2AoVKoRixYph4cKFUCLWrP6ksLAwXLt2DZ07d9ZbXrRoUSxatOhnH54MgPgwF7WrmTNnhtqJmjZR2xYQEICNGzfC1tYW7du3h5qJkNaiRQsZXsSHmDERH2gtW7aEv7+/rNedMWMG2rRpAzU7ePCg3Mfg4GDcuHEDLi4uSJMmjeprViN6//49NmzYgN9++031+z1ixAi0atUKs2bNQs6cOXHmzBlcvXoVu3btglrZ2dnJi+6IDQ2ip/358+dyPIISMazGwYtaBJXIA6rEfV9f3599eDKA8NahQweULl1a9S0QwsuXLzF06FB5ZS4G34hW5pQpU0LtH2ZiQFWPHj1gTIoUKYKHDx8iXbp08v5ff/0le1KyZMmi2kFW4gNbDJQVH+JiwKhoZRPnuRh8snbtWqRPnx7GYM2aNQgJCZHHW+1Ew1Lt2rXlN0+K4yvOedH4JIKrWllYWMj3M7HPYtCkGCwreo1Ea7K1tTWUiGE1Dg66IFodIvr48aNRdRcaI9Hy0rBhQ9nKuHv3btW3QAjiTe348ePyZ9GjULZsWVkCMWDAAKiRGPk/c+ZMrF69Wrfffn5+8rUt7otAp9aZIKpVq6Z3v2/fvpg3b55scVNrWBWvYTMzM+zcuVMee1EOIF7fVatWlQFm//79MJYSgDp16sDNzQ1qJ3oOxGtazAZgb28vZ7cpU6aMbIgS57ta/fHHH8ibN69sQRY9J9WrV5e9CJs3b4YSMazGQXO6aEWNXLcn7ru7u//sw5NCiVYHEVTFVbiHhwdcXV1hbPLkySPf4ERQV2tYFRedhQsXxp9//qlbJqZpEwFdtDCLUghj+EDXEue52muURetagQIFZFDVvseLeu3+/fvLlle1X5Rev34dZ8+eVXU3eMQyPvH+NXfuXBlUBfF5Lsp+xDI1h1VTU1NZwhWxjKtixYpyLIISMazGgSpVqmD79u3yw0v7AhBX5vXq1YuLhyeFBtV79+7h8OHDRjMnn2hhEh/ckeeaFa2taiVaWLQtqlqiy1B0lYmgakzHW3QRXr58Wb7fqZloURa1upHnFhalIGoPqoIYa5E2bdooLetqJFrRRamHOL4RiblH1T5n+MePH/UGR4v67KNHj8pyFyViWI0Doghd1L107dpVfpCtWLFCdiGotbVJS3QdiK5grbt378oPdtHSpObBRs2bN8eRI0dkV5kYJS5ugmhJV3Nrevny5dGoUSPky5dPvtGJrvGbN2/KFghSH1GDLWb8EK2MYtDFtGnTZDeh2mt3RaOD2OfevXvL93PxIS7qdadOnQpjuBBfuXIlevXqJVvejIE4zlOmTIGDg4PsFj99+jSWLl2q+ve1JUuWyPdvcY4/e/YMY8aMkS3KjRs3hhKZiPmrEnsj1ECENtFVKOpexACEwYMH67qR1ErUdIk6tshErdOQIUOgVmJaMlGvGpkYaCVuaiXqumbPni1Hy4pabfGtNt27d9ebxssYiHNb1KyOHz8eahbxeItZH8QFuQiq4me18/T0xO+//y6n7BIDCMWHeM2aNaF2Yvq9QYMGyQFWonXVWGzatAlbtmyRA0jF+5k43mpvWdZoNLLBZevWrbLuXvQWivpdpfYeMKwSERERkWIZRzs/ERERERkkhlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiIiIiUiyGVSIiIiJSLIZVIiIiIlIshlUiop8gvnZ3z549uvu3bt3Cvn37FLEt8fUFKIcOHfrpx0nM54mIDAvDKhGpzq5du+R3XIvbf//9p/e1wHFt7969GDhwoO6++PeGDx8e478XX3l44MCBeNmWyB48eIANGzb81L+xbt06jBs3Dj/rR58nIjJe5om9AUREca1///7yu83Fd30HBATg+PHj8ucdO3YgSZIk8fqE58yZ84e+qnHz5s1yuypXroz4tn//fvkVyU2aNIn3f4uIKK4wrBKRKtWtWxdTpkyRPz958gS5cuXCtGnTZJAVLZCNGjXC9evX8fDhQ5QqVQpubm5y3bt378rWTnG/QIEC8nuzIwoNDZXhNyQkBPnz54/y72bJkgXW1tbRtmqKf09853rBggV1y0Sr75s3b2QrsFCsWDFkyJAhTrblRz169AhnzpyRP9vb28vgnTFjxmjXDQoKwqVLl+Dj4yOfPycnpyjrfG/7iYhigmGViFRPBMRChQrh8uXLMiC2aNECtWrVgpeXF3LkyIHMmTPD2dkZHTp0kHWURYsWlQFXBDLRXZ0tWzb5OO/evZMtoN7e3jIcXrlyRfc7LbH+xo0bUbVqVXn/06dP8nG3bt2K4sWLw8/PDylSpMD27dtlOBS1m2KZ+L2QMmVKpEmTJk625UeJ50O7HeLxRRAW2/HXX3/prff06VMZPkUI9ff3l4FftA6XLl1ab5+/tf1ERDHFsEpEqidaIEUw1AZIbYAVAUtr/PjxMjiKMCtaFYVevXqha9eu8PDwkPdFS60IcWI9R0dHGcLy5cuHVKlSffXfFo8rQpsIk9pWStGyGxYWJsNm06ZN5XZoW1bjc1u+p1y5cvKm5enpKcsnRNmAaD3Vun//PlasWIHWrVvL+926dUOXLl1ky7EovxDb9r3tJyKKKYZVIlIlEZZEAAwMDJQtna9evZKBKTg4WP5e/BzR0qVLUb58eTmaXqPRyJtoAT1x4oTsZre0tMT69evRvXt3GQ61gVe00h45cuSr27Fs2TL06NFDrzv9ezWt8bUtMfHx40dcuHABL168kCFfhN+zZ8/qhVXR+tuqVSvd/SFDhmD+/PmypEEE5phsPxFRTDGsEpEqiWmcRJe2jY2N7H6fN28e3N3dcf78eV3giujx48eyxlKE24hEbasIcCJgiW7y9OnT6/1e1Jd+KyCKFs+sWbP+0LbH17Z8z9GjR9G4cWO4uLjIcG1ra4u3b9/KoB9RunTpYGJiondftKiK7RZhNSbbT0QUUwyrRKT6AVbRiRi2BDFLQMOGDeUArK8Rda2ivjSiyPcjEy2fYgDVj4ivbfkeMe1V+/btMXXqVN0yUQ8rWka/9e+IutXw8HAkT548xttPRBRTnGeViAhA9erVsXjxYjk4KPJgIi0xgEg7AEkQAS3i/eiIOtmVK1fKdSOGPVGzKoiaTjH4KCG25XtE13/EAVC3b9/GjRs3vjrKP+L0Ww4ODsidO3eMt5+IKKbYskpEBOD3339HmTJlZMlA27ZtZbe2GA0v6jY3bdokn6MxY8bI0e2iXlMMRBIhTXSRu7q6fvU5FK2Uot6zQoUKaNasmQyqYmJ9UQdqZmaGwoULY9CgQfjzzz9lfaiYuiq+tkUbaiMO5hJEt7xoCa1fvz5Gjx4tu+9Fbe+MGTNgZ2cX5TFEMBUt171795ZlAqIFW3xRgFge0+eSiCimGFaJSHXEtFSidjI6Yj5QERoj102KAUpXr16VA6LE/KGiK1uM1BchTkvM1SpC5oIFC+Q6LVu2lJPsHzx48KtfCiDqSsXjipZG8bfivhh4pJ2LVbSQrlmzRn6L1blz52QtrQifcbEtkYkpusRjRG6BFYFULBeBWUzlJR5X/JurV6/GsWPH9AaHidkBRPe+2EcRPMU8q8uXL5e1rj/yXP7olycQkfEy0UQuRiIiIiIiUgjWrBIRERGRYjGsEhEREZFiMawSERERkWIxrBIRERGRYjGsEhEREZFiMawSERERkWIxrBIRERGRYjGsEhEREZFiMawSERERkWIxrBIRERGRYjGsEhEREZFiMawSEREREZTqfyoE2vH3oNOwAAAAAElFTkSuQmCC",
"text/plain": [
"<Figure size 800x600 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import numpy as np\n",
"from sklearn.metrics import classification_report\n",
"\n",
"# --- TensorFlow CNN Evaluation: Confusion Matrix and Classification Metrics ---\n",
"# Note: This relies on the 'plot_confusion_matrix' function defined in Section 5.\n",
"\n",
"print(\"Gathering predictions for TensorFlow CNN on Test Set...\")\n",
"\n",
"# Collect probability predictions from the TensorFlow model\n",
"y_pred_tf_probs = tf_model.predict(X_test_tf, verbose=0)\n",
"# Convert probabilities to class labels\n",
"y_pred_tf = np.argmax(y_pred_tf_probs, axis=1)\n",
"\n",
"# Extract true labels from the One-Hot encoded TF test set\n",
"y_true_tf = np.argmax(Y_test_tf, axis=1)\n",
"\n",
"# --- Display TensorFlow Metrics and Plots ---\n",
"print(\"\\n\" + \"=\"*50)\n",
"print(\" METRICS: TENSORFLOW CNN\")\n",
"print(\"=\"*50)\n",
"print(classification_report(y_true_tf, y_pred_tf))\n",
"\n",
"# Plot the matrix using the previously defined function\n",
"plot_confusion_matrix(y_true_tf, y_pred_tf, \"Confusion Matrix - TensorFlow CNN\")"
]
},
{
"cell_type": "markdown",
"id": "b6133020",
"metadata": {},
"source": [
"### 7.2 Corrupted MNIST"
]
},
{
"cell_type": "code",
"execution_count": 72,
"id": "ad5498e6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"--- TF CORRUPTED MNIST BENCHMARK ---\n",
"Evaluating TensorFlow against: brightness...\n",
"TensorFlow Accuracy on 'brightness': 19.22%\n",
"\n",
"Evaluating TensorFlow against: dotted_line...\n",
"TensorFlow Accuracy on 'dotted_line': 88.91%\n",
"\n",
"Evaluating TensorFlow against: glass_blur...\n",
"TensorFlow Accuracy on 'glass_blur': 89.94%\n",
"\n"
]
}
],
"source": [
"import os\n",
"import numpy as np\n",
"\n",
"# --- 2. TensorFlow Robustness Evaluation on Corrupted MNIST ---\n",
"\n",
"def evaluate_tf_corruptions(corruption_type, base_folder, model):\n",
" \"\"\"Evaluates the TensorFlow model against specific image corruptions.\"\"\"\n",
" images_path = os.path.join(base_folder, corruption_type, \"test_images.npy\")\n",
" labels_path = os.path.join(base_folder, corruption_type, \"test_labels.npy\")\n",
" \n",
" try:\n",
" images = np.load(images_path)\n",
" labels = np.load(labels_path)\n",
" except FileNotFoundError:\n",
" print(f\"Error: Could not find files for {corruption_type}\")\n",
" return\n",
" \n",
" print(f\"Evaluating TensorFlow against: {corruption_type}...\")\n",
" \n",
" # Reshape for TF: (samples, height, width, channels)\n",
" images_tf = images.reshape(-1, 28, 28, 1)\n",
" \n",
" # Apply the exact same normalization used during training\n",
" images_tf = np.where(images_tf.max() > 1.0, \n",
" (images_tf / 255.0) * 0.99 + 0.01, \n",
" images_tf * 0.99 + 0.01)\n",
" \n",
" # Create One-Hot encoded target vectors\n",
" labels_tf = np.zeros((len(labels), 10)) + 0.01\n",
" for i, label in enumerate(labels):\n",
" labels_tf[i, label] = 0.99\n",
" \n",
" # Evaluate automatically using TF's built-in function\n",
" loss, accuracy = model.evaluate(images_tf, labels_tf, verbose=0)\n",
" print(f\"TensorFlow Accuracy on '{corruption_type}': {accuracy * 100:.2f}%\\n\")\n",
"\n",
"print(\"\\n--- TF CORRUPTED MNIST BENCHMARK ---\")\n",
"corruptions_to_test = [\"brightness\", \"dotted_line\", \"glass_blur\"]\n",
"\n",
"for corr in corruptions_to_test:\n",
" evaluate_tf_corruptions(corr, base_dir, tf_model)"
]
},
{
"cell_type": "markdown",
"id": "9156efe2",
"metadata": {},
"source": [
"### 7.3 Fashion MNIST"
]
},
{
"cell_type": "code",
"execution_count": 73,
"id": "34cb3b77",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Loading Fashion MNIST dataset for TensorFlow...\n",
"\n",
"Training TensorFlow model on Fashion MNIST...\n",
"Epoch 1/15\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"c:\\Users\\sofia\\CNN-From-Scratch\\.venv\\Lib\\site-packages\\keras\\src\\layers\\core\\input_layer.py:27: UserWarning: Argument `input_shape` is deprecated. Use `shape` instead.\n",
" warnings.warn(\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.3277 - loss: 0.0802 - val_accuracy: 0.5802 - val_loss: 0.0619\n",
"Epoch 2/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.6842 - loss: 0.0490 - val_accuracy: 0.7308 - val_loss: 0.0400\n",
"Epoch 3/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.7442 - loss: 0.0370 - val_accuracy: 0.7667 - val_loss: 0.0338\n",
"Epoch 4/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.7690 - loss: 0.0328 - val_accuracy: 0.7800 - val_loss: 0.0309\n",
"Epoch 5/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.7871 - loss: 0.0303 - val_accuracy: 0.7943 - val_loss: 0.0288\n",
"Epoch 6/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.7998 - loss: 0.0286 - val_accuracy: 0.8075 - val_loss: 0.0276\n",
"Epoch 7/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8083 - loss: 0.0274 - val_accuracy: 0.8113 - val_loss: 0.0265\n",
"Epoch 8/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8159 - loss: 0.0264 - val_accuracy: 0.8205 - val_loss: 0.0257\n",
"Epoch 9/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8204 - loss: 0.0256 - val_accuracy: 0.8227 - val_loss: 0.0251\n",
"Epoch 10/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8258 - loss: 0.0249 - val_accuracy: 0.8240 - val_loss: 0.0246\n",
"Epoch 11/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8294 - loss: 0.0243 - val_accuracy: 0.8288 - val_loss: 0.0240\n",
"Epoch 12/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8339 - loss: 0.0237 - val_accuracy: 0.8257 - val_loss: 0.0243\n",
"Epoch 13/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8380 - loss: 0.0232 - val_accuracy: 0.8335 - val_loss: 0.0231\n",
"Epoch 14/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8412 - loss: 0.0228 - val_accuracy: 0.8380 - val_loss: 0.0228\n",
"Epoch 15/15\n",
"\u001b[1m1688/1688\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 2ms/step - accuracy: 0.8439 - loss: 0.0224 - val_accuracy: 0.8407 - val_loss: 0.0224\n",
"\n",
"Evaluating TensorFlow model on Fashion MNIST Test Set...\n",
"TensorFlow Final Accuracy on Fashion MNIST: 83.15%\n"
]
}
],
"source": [
"import tensorflow as tf\n",
"from tensorflow.keras import layers, models\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from tensorflow.keras.datasets import fashion_mnist\n",
"\n",
"# --- 1. Load and Preprocess Fashion MNIST for TensorFlow ---\n",
"print(\"Loading Fashion MNIST dataset for TensorFlow...\")\n",
"(train_images_f, train_labels_f), (test_images_f, test_labels_f) = fashion_mnist.load_data()\n",
"\n",
"# TF expects spatial data in the shape: (samples, height, width, channels)\n",
"# Normalizing between 0.01 and 1.0 to match the custom implementation strictly\n",
"X_train_tf_f = train_images_f.reshape(-1, 28, 28, 1) / 255.0 * 0.99 + 0.01\n",
"X_test_tf_f = test_images_f.reshape(-1, 28, 28, 1) / 255.0 * 0.99 + 0.01\n",
"\n",
"# One-hot encode the labels, mapping exactly to the [0.01, 0.99] range used previously\n",
"Y_train_tf_f = np.zeros((len(train_labels_f), 10)) + 0.01\n",
"for i, label in enumerate(train_labels_f):\n",
" Y_train_tf_f[i, label] = 0.99\n",
"\n",
"Y_test_tf_f = np.zeros((len(test_labels_f), 10)) + 0.01\n",
"for i, label in enumerate(test_labels_f):\n",
" Y_test_tf_f[i, label] = 0.99\n",
"\n",
"# --- 2. Initialize the TensorFlow Architecture ---\n",
"tf_model_fashion = models.Sequential([\n",
" layers.InputLayer(input_shape=(28, 28, 1)),\n",
" layers.Conv2D(filters=5, kernel_size=(3, 3), activation='sigmoid'),\n",
" layers.Flatten(),\n",
" layers.Dense(100, activation='sigmoid'), # <--- Consistent 100 nodes\n",
" layers.Dense(10, activation='sigmoid')\n",
"])\n",
"\n",
"# Compile using the exact same mathematical parameters\n",
"tf_model_fashion.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.3), # <--- Consistent LR 0.3\n",
" loss='mse',\n",
" metrics=['accuracy'])\n",
"\n",
"# --- 3. Training ---\n",
"print(\"\\nTraining TensorFlow model on Fashion MNIST...\")\n",
"# Using validation_split to monitor overfitting during training\n",
"history_fashion = tf_model_fashion.fit(X_train_tf_f, Y_train_tf_f, epochs=15, validation_split=0.1)\n",
"\n",
"# --- 4. Evaluation on Test Set ---\n",
"print(\"\\nEvaluating TensorFlow model on Fashion MNIST Test Set...\")\n",
"test_loss_f, test_accuracy_f = tf_model_fashion.evaluate(X_test_tf_f, Y_test_tf_f, verbose=0)\n",
"print(f\"TensorFlow Final Accuracy on Fashion MNIST: {test_accuracy_f * 100:.2f}%\")"
]
},
{
"cell_type": "markdown",
"id": "2332503c",
"metadata": {},
"source": [
"## 8. Hardware Efficiency & Inference Latency"
]
},
{
"cell_type": "markdown",
"id": "59a8546e",
"metadata": {},
"source": [
"Measurement of the single-image processing time. Real-time medical and industrial diagnostic tools require low latency. This benchmark demonstrates the high efficiency and low memory overhead of the native NumPy implementation, proving the viability of bypassing heavy graph-execution frameworks for future physical synthesis on embedded platforms and FPGAs."
]
},
{
"cell_type": "code",
"execution_count": 74,
"id": "73ba73d9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Measuring Inference Time for a single image...\n",
"\n",
"Custom CNN Prediction: 7 | Latency: 1.01 ms\n",
"TensorFlow Prediction: 7 | Latency: 47.37 ms\n",
"\n",
"Note: TensorFlow has a high overhead for single-image inference due to graph execution.\n",
"The Custom NumPy CNN proves to be highly efficient for real-time, individual tensor flows.\n"
]
}
],
"source": [
"import time\n",
"import numpy as np\n",
"\n",
"# --- 3. Inference Time Measurement (Hardware Efficiency Benchmark) ---\n",
"print(\"Measuring Inference Time for a single image...\\n\")\n",
"\n",
"# Extract a single sample image from the test set\n",
"sample_record = test_data[0].split(\",\")\n",
"x_custom_sample = np.asarray(sample_record[1:], dtype=float).reshape(1, 28, 28) / 255.0 * 0.99 + 0.01\n",
"\n",
"# Reshape the same sample for TensorFlow: (1, 28, 28, 1)\n",
"x_tf_sample = x_custom_sample.reshape(1, 28, 28, 1)\n",
"\n",
"# 1. Measure Custom CNN (NumPy) Inference Time\n",
"start_time_custom = time.time()\n",
"\n",
"output_custom = x_custom_sample\n",
"for layer in network:\n",
" output_custom = layer.forward(output_custom)\n",
"prediction_custom = np.argmax(output_custom)\n",
"\n",
"end_time_custom = time.time()\n",
"custom_latency_ms = (end_time_custom - start_time_custom) * 1000\n",
"\n",
"\n",
"# 2. Measure TensorFlow CNN Inference Time\n",
"start_time_tf = time.time()\n",
"\n",
"output_tf_probs = tf_model.predict(x_tf_sample, verbose=0)\n",
"prediction_tf = np.argmax(output_tf_probs)\n",
"\n",
"end_time_tf = time.time()\n",
"tf_latency_ms = (end_time_tf - start_time_tf) * 1000\n",
"\n",
"# --- Display Results ---\n",
"print(f\"Custom CNN Prediction: {prediction_custom} | Latency: {custom_latency_ms:.2f} ms\")\n",
"print(f\"TensorFlow Prediction: {prediction_tf} | Latency: {tf_latency_ms:.2f} ms\")\n",
"\n",
"print(\"\\nNote: TensorFlow has a high overhead for single-image inference due to graph execution.\")\n",
"print(\"The Custom NumPy CNN proves to be highly efficient for real-time, individual tensor flows.\")"
]
},
{
"cell_type": "markdown",
"id": "0cd1a5be",
"metadata": {},
"source": [
"## 9. Final Conclusions & Framework Selection\n",
"\n",
"This module successfully demonstrated the mathematical formulation, training, and evaluation of a Convolutional Neural Network built entirely from scratch, alongside a direct benchmark against an industry standard. \n",
"\n",
"### 9.1 Comparative Analysis: Custom CNN vs. TensorFlow\n",
"Both frameworks achieved excellent classification metrics and demonstrated robustness against spatial noise, but they serve fundamentally different operational paradigms:\n",
"\n",
"**TensorFlow (Commercial Framework)**\n",
"* **Advantages:** Highly optimized for massive parallel training on GPUs; automatic gradient differentiation; robust ecosystem for rapid software prototyping.\n",
"* **Disadvantages:** Massive memory footprint; high overhead for single-instance inference due to graph execution latency; \"black-box\" abstraction makes it extremely difficult to port directly to constrained hardware.\n",
"\n",
"**Custom NumPy CNN (Native Implementation)**\n",
"* **Advantages:** Absolute algorithmic transparency; zero reliance on heavy external libraries; ultra-low latency for single-tensor inference; highly modular and lightweight.\n",
"* **Disadvantages:** Slower training phase (strictly CPU-bound); requires manual derivation of backpropagation gradients for any new layer architecture.\n",
"\n",
"### 9.2 Architectural Decision & Hardware Justification\n",
"For the definitive scope of this library, the **Custom NumPy CNN is the chosen framework**. \n",
"\n",
"While TensorFlow is superior for training massive models on cloud clusters, the ultimate objective of this development is autonomous deployment in electronic instrumentation and embedded hardware. By structuring the network using pure linear algebra and matrix operations, the architecture is completely decoupled from high-level operating systems. \n",
"\n",
"This transparency is critical: it allows the algorithmic blocks to be directly translated into C/C++ or Hardware Description Languages (VHDL/Verilog) for physical synthesis on **FPGAs or microcontrollers**. The custom framework guarantees the low-latency, real-time processing required for autonomous sensor nodes, ensuring data privacy and eliminating the need for continuous cloud connectivity."
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv (3.11.9.final.0)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
}
},
"nbformat": 4,
"nbformat_minor": 5
}