{ "cells": [ { "cell_type": "markdown", "id": "2c33caea-527f-4bc7-a337-5642943f4249", "metadata": {}, "source": [ "# Image classification for the MNIST dataset" ] }, { "cell_type": "code", "execution_count": 1, "id": "279aabec-4a30-4708-ae14-5232495a6f1d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# To use full widht of screen in the notebook\n", "from IPython.display import display, HTML\n", "display(HTML(\"\"))" ] }, { "cell_type": "markdown", "id": "0f3dd6dd-ff9a-4e84-a3cd-9e747fc17cbc", "metadata": {}, "source": [ "## Import Libraries and test GPUs\n", "\n", "We import the required libraries and check if the GPU cards are available (cuda)." ] }, { "cell_type": "code", "execution_count": 2, "id": "ed0cffe6-5633-4d94-abde-b6adcc18c5fe", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Using device: cuda\n" ] } ], "source": [ "# Import libraries\n", "import torch\n", "import torch.nn as nn\n", "from torch.utils.data import DataLoader\n", "from torch.optim import Adam\n", "from torchvision import datasets, transforms\n", "import matplotlib.pyplot as plt\n", "\n", "# Check if GPU is available\n", "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n", "print(f\"Using device: {device}\")" ] }, { "cell_type": "markdown", "id": "49427fca-cec1-4b67-826e-ca6e345a93a4", "metadata": {}, "source": [ "## Dataset\n", "\n", "We download the MNIST datasets for the first time and transform them tensors in order to be used by PyTorch. Afterward, when running the notebook again, the datasets are already stored locally." ] }, { "cell_type": "code", "execution_count": 3, "id": "6661e5ae-68e6-45a4-a3d3-18a92808468f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dataset MNIST\n", " Number of datapoints: 60000\n", " Root location: ./data\n", " Split: Train\n", " StandardTransform\n", "Transform: Compose(\n", " ToTensor()\n", " )\n", "Dataset MNIST\n", " Number of datapoints: 10000\n", " Root location: ./data\n", " Split: Test\n", " StandardTransform\n", "Transform: Compose(\n", " ToTensor()\n", " )\n", "Image batch shape: torch.Size([64, 1, 28, 28])\n", "Label batch shape: torch.Size([64])\n" ] } ], "source": [ "# Define transformations\n", "my_transform = transforms.Compose([transforms.ToTensor()])\n", "\n", "# Load datasets\n", "train_dataset = datasets.MNIST(root='./data', train=True, transform=my_transform, download=True)\n", "test_dataset = datasets.MNIST(root='./data', train=False, transform=my_transform, download=True)\n", "print(train_dataset)\n", "print(test_dataset)\n", "\n", "# Data loaders\n", "train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)\n", "test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)\n", "\n", "# Inspect data shape\n", "images, labels = next(iter(train_loader))\n", "print(f\"Image batch shape: {images.shape}\")\n", "print(f\"Label batch shape: {labels.shape}\")" ] }, { "cell_type": "markdown", "id": "88d1036e-4026-416d-9013-aa5c79a4ee51", "metadata": {}, "source": [ "## Data visualization\n", "\n", "Let's print an element of the training dataset as a tensor." ] }, { "cell_type": "code", "execution_count": 4, "id": "b47f2c6e-fdff-407b-909f-9663a57cb156", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.1, 0.5, 0.5, 0.7, 0.1, 0.7, 1.0, 1.0, 0.5, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.1, 0.4, 0.6, 0.7, 1.0, 1.0, 1.0, 1.0, 1.0, 0.9, 0.7, 1.0, 0.9, 0.8, 0.3, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.9, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.4, 0.3, 0.3, 0.2, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.9, 1.0, 1.0, 1.0, 1.0, 1.0, 0.8, 0.7, 1.0, 0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.6, 0.4, 1.0, 1.0, 0.8, 0.0, 0.0, 0.2, 0.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.6, 1.0, 0.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 1.0, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.7, 1.0, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.9, 0.9, 0.6, 0.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.9, 1.0, 1.0, 0.5, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.7, 1.0, 1.0, 0.6, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.4, 1.0, 1.0, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.5, 0.7, 1.0, 1.0, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.6, 0.9, 1.0, 1.0, 1.0, 1.0, 0.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.4, 0.9, 1.0, 1.0, 1.0, 1.0, 0.8, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.3, 0.8, 1.0, 1.0, 1.0, 1.0, 0.8, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.9, 1.0, 1.0, 1.0, 1.0, 0.8, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.2, 0.7, 0.9, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.5, 1.0, 1.0, 1.0, 0.8, 0.5, 0.5, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", " [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# We set the decimal precision to 1 (or 2) only for printing purposes, i.e. to be able to visualize the matrix (tensor) similarly as the actual image\n", "torch.set_printoptions(precision=1, linewidth=300)\n", "\n", "# Let's check the first element as a tensor\n", "train_dataset[0][0][0]" ] }, { "cell_type": "markdown", "id": "25d2b649-b7c4-4a85-81b6-dddc75939814", "metadata": {}, "source": [ "We can barely distinguish the element with the naked eye. Let's check a couple more of elements (this is the first one), but now as images." ] }, { "cell_type": "code", "execution_count": 5, "id": "c78b2a40-e4fa-4866-969c-091daa4fd7db", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAABdEAAACtCAYAAABfjTYXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAArxUlEQVR4nO3dd3xUVf7/8U9IQqSIlGRB8EsxSJPelCKgNEGkKSKCVAFFigrYQFFqVtFdikg1gPAwoFRdFFGqigrr4i4oCqxgEAKIIqEm4P394U/WO59zzWRyJzN38no+Hvxx3py58yEc7kwOk/OJsizLEgAAAAAAAAAAoOQLdQEAAAAAAAAAAIQrNtEBAAAAAAAAAHDAJjoAAAAAAAAAAA7YRAcAAAAAAAAAwAGb6AAAAAAAAAAAOGATHQAAAAAAAAAAB2yiAwAAAAAAAADggE10AAAAAAAAAAAcsIkOAAAAAAAAAIADz22iL1y4UKKiomTnzp2uXC8qKkqGDh3qyrX+eM3nnnsuoMcePHhQoqKijL9SUlJcrRO/ifQ1JSKSmZkpzz//vJQvX17i4uKkSpUqMmPGDPcKxBV5YT390QcffHDlHvXjjz+6ck3Y5YU1NXbsWOnQoYOUKVNGoqKipG/fvq7VBru8sJ6+/fZbueuuu6RYsWJSsGBBuemmm2Tt2rXuFQibSF9T//znP+Xhhx+WGjVqyNVXXy0lS5aUVq1aycaNG12tEb+J9PUkwmtebov0NZWamipdunSR66+/XgoVKiTXXHON1KlTR2bOnCmXLl1ytU5E/noS4R6V2/LCmvojr+8feG4TPa8YNmyYbN++3fardevWoS4LHjVkyBCZMmWKPPzww7J+/Xrp0qWLjBgxQiZPnhzq0uBhZ86ckYEDB0rp0qVDXQo87m9/+5ucPHlSOnbsKPnz5w91OfCwgwcPSqNGjeSbb76R2bNny5tvvikJCQnSuXNnWbFiRajLgwe98cYb8vnnn0v//v1lzZo1Mn/+fImLi5OWLVvK4sWLQ10ePIjXPLjp7NmzUqRIEXnmmWdk7dq1kpKSIk2bNpVhw4bJgw8+GOry4EHcoxAskbB/EBPqAmBWtmxZufnmm0NdBiLAnj17ZMGCBTJp0iQZPXq0iIi0aNFCTp48KRMnTpQHH3xQihcvHuIq4UVPPvmkFCtWTO644w6ZOHFiqMuBh6Wnp0u+fL/9v/7rr78e4mrgZUlJSXLu3DlZv369lClTRkREbr/9dqlRo4Y8+uij0qVLlytrDfDH448/LlOnTrVl7du3l7p168r48eOld+/eIaoMXsVrHtxUpUoVWbRokS1r166dHD9+XBYtWiSvvPKKxMXFhag6eBH3KARLJOwfROR3ERcuXJCRI0dK7dq15ZprrpHixYtLo0aNZM2aNY6PmTNnjlSqVEni4uKkWrVqxqNT0tLSZPDgwXLddddJ/vz5pUKFCvL888/zY1J5gJfX1OrVq8WyLOnXr58t79evn5w/f17ee+89154L/vHyevrdtm3bZO7cuTJ//nyJjo52/frIHq+vKTY1w4uX19PHH38stWrVurKBLiISHR0t7dq1k9TUVPn8889dey74z8tr6i9/+YvKoqOjpV69epKamura88B/Xl5PIrzmhSOvrymThIQEyZcvH+/TQ8Dr64l7VPjx+poSiZz9g4j8JPrFixflp59+klGjRkmZMmUkIyNDPvjgA+nataskJyerT4ysXbtWNm3aJOPHj5dChQrJrFmzpEePHhITEyN33323iPy2uBo2bCj58uWTZ599VhITE2X79u0yceJEOXjwoCQnJ/9pTeXLlxeR337M2B9JSUny9NNPS0xMjNStW1cef/xx6dixY7a/FnCHl9fU7t27JSEhQUqVKmXLa9aseeX3kbu8vJ5ERM6fPy8DBgyQRx55ROrWrctZw2HA62sK4cXL6ykjI8P401W/fwrv3//+Nz/pFwJeXlMmly5dkm3btsmNN96Y7cci5yJtPSH0ImFNWZYlly9flvT0dHn//fdl4cKFMnLkSImJicgtn7AWCesJ4cXrayqi9g8sj0lOTrZExNqxY4ffj7l06ZKVmZlpDRgwwKpTp47t90TEKlCggJWWlmabX6VKFatixYpXssGDB1uFCxe2Dh06ZHv81KlTLRGx9uzZY7vmuHHjbPMSExOtxMTELGs9cuSINXDgQGv58uXWtm3brKVLl1o333yzJSLWvHnz/P4zw3+RvqZat25tVa5c2fh7+fPntwYNGpTlNeC/SF9PlmVZI0eOtK6//nrr3LlzlmVZ1rhx4ywRsU6cOOHX45E9eWFN/VGhQoWsPn36ZPtx8E+kr6fOnTtbRYsWtdLT0235LbfcYomINXny5CyvgeyJ9DVlMmbMGEtErNWrVwf0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4gAf119/fahLQIDS0tJUlpCQYBvHxcWpOaY+Lybr1q1T2datW23j1atXqzkHDx5UWW6ff47ItmfPHpX5cy/j+7rcZfr+vnr16lk+7vHHH1dZenq6KzWJmM9hr1u3rspM77F9bd68WWWvvvqqyny/R0TeY1pPvu/7EVnKlSunsgceeMA2Nq2LuXPnquzw4cPuFRbh2AkBAAAAAAAAAMABm+gAAAAAAAAAADhgEx0AAAAAAAAAAAdsogMAAAAAAAAA4CCsG4sWL17cNp4zZ46aY2qw5mYTK1Nzx5deekll69evV9n58+ddqwPu2L59u228Y8cONadBgwZ+XatUqVIqMzW69XXy5EmVpaSkqGzEiBF+1QHktkaNGqls4cKFuV9IHlW0aFGVme5HJj/88INtPGrUKDdKAhxt27ZNZabmxDTkCz/NmjVTWefOnW1jU7O848ePq+y1115T2c8//6wymqAhHJiart15550hqATB8NBDD4W6BBEx3yvffvtt29j0/eCFCxeCVhO8q0iRIirr1KmTbbxq1arcKge5YMOGDSrzbTa6ZMkSNWfcuHFBqykv4JPoAAAAAAAAAAA4YBMdAAAAAAAAAAAHbKIDAAAAAAAAAOCATXQAAAAAAAAAAByEpLHoTTfdpLLRo0errGHDhrZxmTJlXK3j3LlztvH06dPVnMmTJ6vs7NmzrtaB3HP48GHbuGvXrmrO4MGDVTZ27NiAnm/atGkqe/XVV1W2f//+gK4PBFtUVFSoSwDgYbt371bZvn37VGZqCp+YmGgbnzhxwr3CkKX09HSVvf766386BiLBV199pbKvv/5aZVWrVs2NcuCgb9++Khs2bJht3KdPn6DWcODAAZX57jGImJtsmxrYml4zAV/33HOPyi5evKgy030LkSM5OVllEyZMsI3XrFmTW+XkGXwSHQAAAAAAAAAAB2yiAwAAAAAAAADggE10AAAAAAAAAAAcsIkOAAAAAAAAAICDKMuyLL8muthcLikpSWWmxqL+MDV+eeedd1R26dIllb300ku28alTpwKqIS/zc/kY0bAQJoGuKdZTzpkaNL322msqmzdvnspMDXnDQSTeo0qVKqWyZcuWqaxp06Yq++6772zjihUruldYHsE9KudM95r58+erbMuWLbaxb8M4EfP7QC+JxHsUQot7FNzktXtUXFycbWx6vZk4caLKihUrprLVq1erbMOGDbaxqWlfWlpaFlXmbdyjci4lJUVlpkbHHTt2tI0PHToUtJpCxWv3KIS/rNYUn0QHAAAAAAAAAMABm+gAAAAAAAAAADhgEx0AAAAAAAAAAAdsogMAAAAAAAAA4CAkjUUROWjkALfRbAZu4h4Ft3GPyrkiRYqobPny5Spr1aqVbbxy5Uo1p1+/fio7e/ZsDqrLXdyj4DbuUXAT9yi4jXsU3MQ9Cm6jsSgAAAAAAAAAAAFiEx0AAAAAAAAAAAdsogMAAAAAAAAA4IAz0ZEjnEEFt3FOHtzEPQpu4x4VHKZz0idNmmQbP/TQQ2pOzZo1VfbVV1+5V1iQcY+C27hHwU3co+A27lFwE/couI0z0QEAAAAAAAAACBCb6AAAAAAAAAAAOGATHQAAAAAAAAAAB2yiAwAAAAAAAADggMaiyBEaOcBtNJuBm7hHwW3co+Am7lFwG/couIl7FNzGPQpu4h4Ft9FYFAAAAAAAAACAALGJDgAAAAAAAACAAzbRAQAAAAAAAABwwCY6AAAAAAAAAAAO/G4sCgAAAAAAAABAXsMn0QEAAAAAAAAAcMAmOgAAAAAAAAAADthEBwAAAAAAAADAAZvoAAAAAAAAAAA4YBMdAAAAAAAAAAAHbKIDAAAAAAAAAOCATXQAAAAAAAAAABywiQ4AAAAAAAAAgAM20QEAAAAAAAAAcPD/ALthrtb717kNAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "n_imgs=10\n", "fig, axes = plt.subplots(1, n_imgs, figsize=(15, 4))\n", "for i in range(n_imgs):\n", " ax = axes[i]\n", " x, y = train_dataset[i]\n", " image = transforms.functional.to_pil_image(x)\n", " ax.imshow(image, cmap='gray')\n", " ax.set_title(f\"Label: {y}\")\n", " ax.axis('off')\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "1eaa46f7-d7ca-4da3-a5e6-086084061339", "metadata": {}, "source": [ "## Neural network and training\n", "\n", "Now we define our neural network and start the training process." ] }, { "cell_type": "code", "execution_count": 6, "id": "1139183a-1ea0-4ff8-9c97-3131201a8831", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MNISTModel(\n", " (network): Sequential(\n", " (0): Flatten(start_dim=1, end_dim=-1)\n", " (1): Linear(in_features=784, out_features=128, bias=True)\n", " (2): ReLU()\n", " (3): Linear(in_features=128, out_features=64, bias=True)\n", " (4): ReLU()\n", " (5): Linear(in_features=64, out_features=10, bias=True)\n", " )\n", ")\n" ] } ], "source": [ "# Define the neural network\n", "class MNISTModel(nn.Module):\n", " def __init__(self):\n", " super(MNISTModel, self).__init__()\n", " self.network = nn.Sequential(\n", " nn.Flatten(),\n", " nn.Linear(28*28, 128),\n", " nn.ReLU(),\n", " nn.Linear(128, 64),\n", " nn.ReLU(),\n", " nn.Linear(64, 10)\n", " )\n", " \n", " def forward(self, x):\n", " return self.network(x)\n", "\n", "# Initialize model\n", "model = MNISTModel().to(device)\n", "print(model)" ] }, { "cell_type": "code", "execution_count": 7, "id": "1cc351e5-c643-4f35-a041-b777c2bb3a27", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch [1/5], Loss: 0.3365\n", "Epoch [2/5], Loss: 0.1377\n", "Epoch [3/5], Loss: 0.0945\n", "Epoch [4/5], Loss: 0.0699\n", "Epoch [5/5], Loss: 0.0563\n" ] } ], "source": [ "# Define loss function and optimizer\n", "criterion = nn.CrossEntropyLoss()\n", "optimizer = Adam(model.parameters(), lr=0.001)\n", "\n", "# Training loop\n", "epochs = 5\n", "for epoch in range(epochs):\n", " model.train()\n", " running_loss = 0.0\n", " for images, labels in train_loader:\n", " images, labels = images.to(device), labels.to(device)\n", " \n", " # Forward pass\n", " outputs = model(images)\n", " loss = criterion(outputs, labels)\n", " \n", " # Backward pass\n", " optimizer.zero_grad()\n", " loss.backward()\n", " optimizer.step()\n", " \n", " running_loss += loss.item()\n", " \n", " print(f\"Epoch [{epoch+1}/{epochs}], Loss: {running_loss/len(train_loader):.4f}\")" ] }, { "cell_type": "markdown", "id": "645153a8-a79b-44a3-9ebf-df45a1109957", "metadata": {}, "source": [ "## Predictions and inference\n", "\n", "Now that the model is trained we can test it." ] }, { "cell_type": "code", "execution_count": 8, "id": "40374e27-c391-4a74-b4e7-0261965b716d", "metadata": {}, "outputs": [], "source": [ "def test_model(model, test_loader, device):\n", " model.eval() # Set model to evaluation mode\n", " \n", " # Get a batch of test data\n", " images, labels = next(iter(test_loader))\n", " images, labels = images.to(device), labels.to(device)\n", " \n", " # Predict\n", " outputs = model(images)\n", " _, predictions = torch.max(outputs, 1)\n", " \n", " # Visualize results\n", " n_imgs=10\n", " fig, axes = plt.subplots(1, n_imgs, figsize=(15, 4))\n", " for i in range(n_imgs):\n", " ax = axes[i]\n", " ax.imshow(images[i].cpu().squeeze(), cmap='gray')\n", " ax.set_title(f\"Label: {labels[i].item()}\\nPredicted: {predictions[i].item()}\")\n", " ax.axis('off')\n", " plt.tight_layout()\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 9, "id": "d0ce9ca0-7101-474a-a321-1d313d6d2f23", "metadata": {}, "outputs": [ { "data": { "image/png": "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aSLin3/dQD1lnzXKaxqLWtWmTRtZunSppKWlyf333286r2HDhiJy61YmNWrUSI8vX75cUlNT7/gYZcqUkZiYGJk7d64MGTLE9Grb2/EbN27o4s2bN5fg4GA5fvy48uca/1W2bFkpUqSILFmyRIYMGZL+n+rEiROyY8cOKVq06B3ztGLOnDkiItK7d+8sn8sfUU/WHDhwQJo0aSLFixeXL774QsLCwpw+l7+jpmAn6ilj999/vxQpUkTmzZsn3bp1S4+vXLlSEhMTpVOnTk6d119RUxl7880306/uvO3AgQMyePBgGTdunDRo0EDy5s3r1Ln9DfUEu1FTGWONso56ypzbzf00TZPXXntNihYtKl26dMnyef0JNeW8BQsWiIikX00M6imzvGGN8rlN9O7du8vixYulVatW8txzz0nt2rUlJCRETp8+LVu2bJH27dtLx44dpXz58vL444/Lm2++KSEhIdKkSRM5dOiQTJ8+XfkTCiMzZ86Utm3bSp06dWTw4MFSokQJOXnypGzcuFEWL14sIv+7+u2tt96SuLg4CQkJkbJly0rJkiVlwoQJMnr0aPntt9+kRYsWEhYWJufOnZM9e/ZInjx5ZPz48RIYGCgTJ06UPn36SMeOHaVv375y+fJlGTdunOGVBb1795b58+fL8ePHLd2HKikpST766COpW7eulC9fPpM/6eyBesq4nn7++Wdp0qSJiIhMnjxZfv31V/n111/Tvx8TE6PrOp3dUVPW1qgjR47IkSNHROTWb6avX78uK1euFJFbXcD/e0VxdkY9ZVxPQUFBMnXqVHniiSekf//+8uijj8qvv/4qw4cPl6ZNm0qLFi2c/On7J2oq45qqWrWq6fcqVKiQ/kEG1BOvefajplij7EQ9WVujRo8eLZUqVZIiRYrIyZMnZe7cubJ792757LPPJFeuXE785P0XNZVxTX300UeyevVqad26tURHR8vly5dlxYoVsnTpUunRo4dUqVLFyZ++/6GefHCNcmsbU+1/3Wu/++67O86Li4vT8uTJY/i9lJQUbfr06VqVKlW0nDlzannz5tXKlSun9e/fX/v111/T5/3777/a0KFDtUKFCmk5c+bU6tSpo+3cuVOLjo7OsHutpmnazp07tZYtW2r58+fXQkNDtZiYGKUb7osvvqgVLVpUCwwMVM6xZs0arVGjRtpdd92lhYaG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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "test_model(model, test_loader, device)" ] }, { "cell_type": "code", "execution_count": null, "id": "5d4b4111-1485-4636-91ef-c07f1e6172af", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.7" } }, "nbformat": 4, "nbformat_minor": 5 }