{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# MNIST Database" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* Find this notebook at `EpyNN/epynnlive/captcha_mnist/prepare_dataset.ipynb`. \n", "* Regular python code at `EpyNN/epynnlive/captcha_mnist/prepare_dataset.py`.\n", "\n", "Run the notebook online with [Google Colab](https://colab.research.google.com/github/Synthaze/EpyNN/blob/main/epynnlive/captcha_mnist/prepare_dataset.ipynb).\n", "\n", "**Level: Advanced**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook is part of the series on preparing data for Neural Network regression with EpyNN. \n", "\n", "It deals with a real world problem and therefore will focus on the problem itself, rather than basics that were reviewed along with the preparation of the following dummy dataset: \n", "\n", "* [Boolean dataset](../dummy_boolean/prepare_dataset.ipynb)\n", "* [String dataset](../dummy_string/prepare_dataset.ipynb)\n", "* [Time-series (numerical)](../dummy_time/prepare_dataset.ipynb)\n", "* [Image (numerical)](../dummy_image/prepare_dataset.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Recognition of hand-written digits" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are numerous applications of [Handwritten Digit Recognition using Machine and Deep Learning Algorithms](https://arxiv.org/pdf/2106.12614.pdf). Among those we may cite postal mail sorting, bank check processing or text extraction.\n", "\n", "There were also consequences that arose from the capability of ANNs to overperform at recognizing hand-written digits: the widely spread re-Captcha standard that replaced the digit based or noisy-digit based captcha. Indeed, such controls were put in place to prevent non-human (bots) from requesting internet pages or brute force sign-in interfaces. The [MNIST Database](http://yann.lecun.com/exdb/mnist/) may be seen as a benchmark dataset to bypass first generation captcha made of simple hand-written digits in a row." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prepare a set of hand-written digits as images" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "MNIST data retrieved below are mirrored from the official web-page of the database." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Imports" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# EpyNN/epynnlive/captcha_mnist/prepare_dataset.ipynb\n", "# Install dependencies\n", "!pip3 install --upgrade-strategy only-if-needed epynn\n", "\n", "# Standard library imports\n", "import tarfile\n", "import random\n", "import gzip\n", "import os\n", "\n", "# Related third party imports\n", "import wget\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "# Local application/library specific imports\n", "from epynn.commons.logs import process_logs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note the `tarfile` and `gzip` which are Python built-in *standard* libraries the first choices to deal with `.tar` and `.gz` archives, respectively." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Seeding" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "random.seed(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For reproducibility." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Download MNIST database" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Simple function to download data from the cloud as `.tar` archive. Once uncompressed, it yields a `data/` directory containing `.gz` archives for features and label and for both training and testing sets." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def download_mnist():\n", " \"\"\"Download a subset of the MNIST database.\n", " \"\"\"\n", " data_path = os.path.join('.', 'data')\n", "\n", " if not os.path.exists(data_path):\n", "\n", " # Download @url with wget\n", " url = 'https://synthase.s3.us-west-2.amazonaws.com/mnist_database.tar'\n", " fname = wget.download(url)\n", "\n", " # Extract archive\n", " tar = tarfile.open(fname).extractall('.')\n", " process_logs('Make: '+fname, level=1)\n", "\n", " # Clean-up\n", " os.remove(fname)\n", "\n", " return None" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Retrieve the data as follows." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1m\u001b[32mMake: mnist_database.tar\u001b[0m\n" ] } ], "source": [ "download_mnist()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "('data', [], ['train-labels-idx1-ubyte.gz', 't10k-labels-idx1-ubyte.gz', 'train-images-idx3-ubyte.gz', 't10k-images-idx3-ubyte.gz'])\n" ] } ], "source": [ "for path in os.walk('data'):\n", " print(path)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You may have noted the `idx3-ubyte` and `idx1-ubyte` in file names. This refers to the *IDX* file format which is a *\"simple format for vectors and multidimensional matrices of various numerical types\"*.\n", "\n", "Directly sourced from [MNIST web-page](http://yann.lecun.com/exdb/mnist/) the files content is as follow:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# TRAINING SET IMAGE FILE (train-images-idx3-ubyte)\n", "\n", "# [offset] [type] [value] [description]\n", "# 0000 32 bit integer 0x00000803(2051) magic number\n", "# 0004 32 bit integer 60000 number of images\n", "# 0008 32 bit integer 28 number of rows\n", "# 0012 32 bit integer 28 number of columns\n", "# 0016 unsigned byte ?? pixel\n", "# 0017 unsigned byte ?? pixel\n", "# ........\n", "# xxxx unsigned byte ?? pixel" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we try to match this to our actual `train-images-idx3-ubyte.gz` archive:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "b'\\x00\\x00\\x08\\x03\\x00\\x00\\xea`\\x00\\x00\\x00\\x1c\\x00\\x00\\x00\\x1c'\n", "[0, 0, 8, 3, 0, 0, 234, 96, 0, 0, 0, 28, 0, 0, 0, 28]\n", "16\n", "b'\\x00\\x00\\x00\\x1c'\n", "[0, 0, 0, 28]\n", "28\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.]\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.]\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.]\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.]\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.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 3. 18. 18. 18. 126. 136. 175. 26. 166. 255. 247. 127. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 30. 36. 94. 154. 170. 253. 253. 253. 253. 253. 225. 172. 253. 242. 195. 64. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 49. 238. 253. 253. 253. 253. 253. 253. 253. 253. 251. 93. 82. 82. 56. 39. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 18. 219. 253. 253. 253. 253. 253. 198. 182. 247. 241. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 80. 156. 107. 253. 253. 205. 11. 0. 43. 154. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 14. 1. 154. 253. 90. 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. 139. 253. 190. 2. 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. 11. 190. 253. 70. 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. 35. 241. 225. 160. 108. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 81. 240. 253. 253. 119. 25. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 45. 186. 253. 253. 150. 27. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 16. 93. 252. 253. 187. 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. 249. 253. 249. 64. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 46. 130. 183. 253. 253. 207. 2. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 39. 148. 229. 253. 253. 253. 250. 182. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 24. 114. 221. 253. 253. 253. 253. 201. 78. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 0. 0. 23. 66. 213. 253. 253. 253. 253. 198. 81. 2. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 0. 0. 18. 171. 219. 253. 253. 253. 253. 195. 80. 9. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 55. 172. 226. 253. 253. 253. 253. 244. 133. 11. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [ 0. 0. 0. 0. 136. 253. 253. 253. 212. 135. 132. 16. 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.]\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.]\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.]]\n" ] } ], "source": [ "img_file = gzip.open('data/train-images-idx3-ubyte.gz')\n", "\n", "header = img_file.read(16) # Read the first 16 bytes\n", "\n", "print(header) # As bytes\n", "print(list(header)) # As integers\n", "print(len(list(header))) # 16 integers over 16 bytes\n", "\n", "print(header[8:12]) # Number of rows\n", "print(list(header[8:12])) # To integers\n", "\n", "image_size = int.from_bytes(header[8:12], byteorder='big')\n", "print(image_size)\n", "\n", "sample_1_bytes = img_file.read(image_size * image_size * 1)\n", "sample_1 = np.frombuffer(sample_1_bytes, dtype=np.uint8).astype(np.float32)\n", "\n", "np.set_printoptions(linewidth=np.inf) # Disable line wrapping on array print\n", "\n", "print(sample_1.reshape(image_size, image_size)) # Reshape 1D array into 2D" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similar logic applies for labels. We got a *5* here in case." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Prepare dataset" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below is a function we use to prepare the labeled dataset." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "def prepare_dataset(N_SAMPLES=100):\n", " \"\"\"Prepare a dataset of hand-written digits as images.\n", "\n", " :param N_SAMPLES: Number of MNIST samples to retrieve, defaults to 100.\n", " :type N_SAMPLES: int\n", "\n", " :return: Set of sample features.\n", " :rtype: tuple[:class:`numpy.ndarray`]\n", "\n", " :return: Set of single-digit sample label.\n", " :rtype: tuple[:class:`numpy.ndarray`]\n", " \"\"\"\n", " # Process MNIST images\n", " img_file = gzip.open('data/train-images-idx3-ubyte.gz')\n", "\n", " header = img_file.read(16)\n", " image_size = int.from_bytes(header[8:12], byteorder='big')\n", " buf = img_file.read(image_size * image_size * N_SAMPLES)\n", " X_features = np.frombuffer(buf, dtype=np.uint8).astype(np.float32)\n", " X_features = X_features.reshape(N_SAMPLES, image_size, image_size, 1)\n", "\n", " # Process MNIST labels\n", " label_file = gzip.open('data/train-labels-idx1-ubyte.gz')\n", "\n", " header = label_file.read(8)\n", " buf = label_file.read(image_size * image_size * N_SAMPLES)\n", " Y_label = np.frombuffer(buf, dtype=np.uint8)\n", "\n", " # Prepare X-Y pairwise dataset\n", " dataset = list(zip(X_features, Y_label))\n", "\n", " # Shuffle dataset\n", " random.shuffle(dataset)\n", "\n", " # Separate X-Y pairs\n", " X_features, Y_label = zip(*dataset)\n", "\n", " return X_features, Y_label" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's check the function." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "X_features, Y_label = prepare_dataset(N_SAMPLES=5)\n", "\n", "for features, label in zip(X_features, Y_label):\n", " plt.imshow(features, cmap='gray')\n", " plt.title('Digit = label = %s' % label)\n", " plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are ready to proceed with the training of a network based on those data." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Live examples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The function ``prepare_dataset()`` presented herein is used in the following live examples:\n", "\n", "* Notebook at`EpyNN/epynnlive/captcha_mnist/train.ipynb` or following [this link](train.ipynb). \n", "* Regular python code at `EpyNN/epynnlive/captcha_mnist/train.py`." ] } ], "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.9.2" } }, "nbformat": 4, "nbformat_minor": 4 }