{ "cells": [ { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "UEBilEjLj5wY" }, "source": [ "Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n", "- Author: Sebastian Raschka\n", "- GitHub Repository: https://github.com/rasbt/deeplearning-models\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 119 }, "colab_type": "code", "executionInfo": { "elapsed": 536, "status": "ok", "timestamp": 1524974472601, "user": { "displayName": "Sebastian Raschka", "photoUrl": "//lh6.googleusercontent.com/-cxK6yOSQ6uE/AAAAAAAAAAI/AAAAAAAAIfw/P9ar_CHsKOQ/s50-c-k-no/photo.jpg", "userId": "118404394130788869227" }, "user_tz": 240 }, "id": "GOzuY8Yvj5wb", "outputId": "c19362ce-f87a-4cc2-84cc-8d7b4b9e6007" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Author: Sebastian Raschka\n", "\n", "Python implementation: CPython\n", "Python version : 3.8.12\n", "IPython version : 8.0.1\n", "\n", "torch: 1.10.1\n", "\n" ] } ], "source": [ "%load_ext watermark\n", "%watermark -a 'Sebastian Raschka' -v -p torch" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "rH4XmErYj5wm" }, "source": [ "# AlexNet CIFAR-10 Classifier" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Network Architecture" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "References\n", " \n", "- [1] Krizhevsky, Alex, Ilya Sutskever, and Geoffrey E. Hinton. \"[Imagenet classification with deep convolutional neural networks.](https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf)\" In Advances in Neural Information Processing Systems, pp. 1097-1105. 2012.\n" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "MkoGLH_Tj5wn" }, "source": [ "## Imports" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "colab": { "autoexec": { "startup": false, "wait_interval": 0 } }, "colab_type": "code", "id": "ORj09gnrj5wp" }, "outputs": [], "source": [ "import os\n", "import time\n", "import random\n", "\n", "import numpy as np\n", "import pandas as pd\n", "\n", "import torch\n", "import torch.nn as nn\n", "import torch.nn.functional as F\n", "from torch.utils.data import DataLoader\n", "from torch.utils.data.dataset import Subset\n", "\n", "from torchvision import datasets\n", "from torchvision import transforms\n", "\n", "import matplotlib.pyplot as plt\n", "from PIL import Image\n", "\n", "\n", "if torch.cuda.is_available():\n", " torch.backends.cudnn.deterministic = True" ] }, { "cell_type": "markdown", "metadata": { "colab_type": "text", "id": "I6hghKPxj5w0" }, "source": [ "## Model Settings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Setting a random seed" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I recommend using a function like the following one prior to using dataset loaders and initializing a model if you want to ensure the data is shuffled in the same manner if you rerun this notebook and the model gets the same initial random weights:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def set_all_seeds(seed):\n", " os.environ[\"PL_GLOBAL_SEED\"] = str(seed)\n", " random.seed(seed)\n", " np.random.seed(seed)\n", " torch.manual_seed(seed)\n", " torch.cuda.manual_seed_all(seed)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Setting cuDNN and PyTorch algorithmic behavior to deterministic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similar to the `set_all_seeds` function above, I recommend setting the behavior of PyTorch and cuDNN to deterministic (this is particulary relevant when using GPUs). We can also define a function for that:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def set_deterministic():\n", " if torch.cuda.is_available():\n", " torch.backends.cudnn.benchmark = False\n", " torch.backends.cudnn.deterministic = True\n", " torch.set_deterministic(True)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "colab": { "autoexec": { "startup": false, "wait_interval": 0 }, "base_uri": "https://localhost:8080/", "height": 85 }, "colab_type": "code", "executionInfo": { "elapsed": 23936, "status": "ok", "timestamp": 1524974497505, "user": { "displayName": "Sebastian Raschka", "photoUrl": "//lh6.googleusercontent.com/-cxK6yOSQ6uE/AAAAAAAAAAI/AAAAAAAAIfw/P9ar_CHsKOQ/s50-c-k-no/photo.jpg", "userId": "118404394130788869227" }, "user_tz": 240 }, "id": "NnT0sZIwj5wu", "outputId": "55aed925-d17e-4c6a-8c71-0d9b3bde5637" }, "outputs": [], "source": [ "##########################\n", "### SETTINGS\n", "##########################\n", "\n", "# Hyperparameters\n", "RANDOM_SEED = 1\n", "LEARNING_RATE = 0.0001\n", "BATCH_SIZE = 256\n", "NUM_EPOCHS = 40\n", "\n", "# Architecture\n", "NUM_CLASSES = 10\n", "\n", "# Other\n", "DEVICE = \"cuda:0\"\n", "\n", "set_all_seeds(RANDOM_SEED)\n", "\n", "# Deterministic behavior not yet supported by AdaptiveAvgPool2d\n", "#set_deterministic()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Import utility functions" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "import sys\n", "\n", "sys.path.insert(0, \"..\") # to include ../helper_evaluate.py etc.\n", "\n", "from helper_evaluate import compute_accuracy\n", "from helper_data import get_dataloaders_cifar10\n", "from helper_train import train_classifier_simple_v1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Dataset" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to data/cifar-10-python.tar.gz\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e73f98cd265c48ca8922f5968c31d202", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/170498071 [00:00" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "loss_list = log_dict['train_loss_per_batch']\n", "\n", "plt.plot(loss_list, label='Minibatch loss')\n", "plt.plot(np.convolve(loss_list, \n", " np.ones(200,)/200, mode='valid'), \n", " label='Running average')\n", "\n", "plt.ylabel('Cross Entropy')\n", "plt.xlabel('Iteration')\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(np.arange(1, NUM_EPOCHS+1), log_dict['train_acc_per_epoch'], label='Training')\n", "plt.plot(np.arange(1, NUM_EPOCHS+1), log_dict['valid_acc_per_epoch'], label='Validation')\n", "\n", "plt.xlabel('Epoch')\n", "plt.ylabel('Accuracy')\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Train ACC: 73.52%\n", "Validation ACC: 73.52%\n", "Test ACC: 72.11%\n" ] } ], "source": [ "with torch.set_grad_enabled(False):\n", " \n", " train_acc = compute_accuracy(model=model,\n", " data_loader=test_loader,\n", " device=DEVICE)\n", " \n", " test_acc = compute_accuracy(model=model,\n", " data_loader=test_loader,\n", " device=DEVICE)\n", " \n", " valid_acc = compute_accuracy(model=model,\n", " data_loader=valid_loader,\n", " device=DEVICE)\n", " \n", "\n", "print(f'Train ACC: {valid_acc:.2f}%')\n", "print(f'Validation ACC: {valid_acc:.2f}%')\n", "print(f'Test ACC: {test_acc:.2f}%')" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "sys : 3.8.12 | packaged by conda-forge | (default, Oct 12 2021, 21:59:51) \n", "[GCC 9.4.0]\n", "matplotlib : 3.3.4\n", "PIL : 9.0.1\n", "torchvision: 0.11.2\n", "numpy : 1.22.0\n", "torch : 1.10.1\n", "pandas : 1.4.1\n", "\n" ] } ], "source": [ "%watermark -iv" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "accelerator": "GPU", "colab": { "collapsed_sections": [], "default_view": {}, "name": "convnet-vgg16.ipynb", "provenance": [], "version": "0.3.2", "views": {} }, "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.8.12" }, "toc": { "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": true, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "371px" }, "toc_section_display": true, "toc_window_display": true } }, "nbformat": 4, "nbformat_minor": 4 }