From 7c4de6d88664d2ea1b084f316a11896dde3e1150 Mon Sep 17 00:00:00 2001 From: aktersnurra Date: Tue, 23 Jun 2020 22:39:54 +0200 Subject: latest --- .flake8 | 2 +- README.md | 6 + poetry.lock | 50 +++- pyproject.toml | 7 + src/notebooks/01-look-at-emnist.ipynb | 180 +++++-------- src/notebooks/tqdm.ipynb | 280 +++++++++++++++++++++ src/text_recognizer/character_predictor.py | 26 ++ src/text_recognizer/datasets/__init__.py | 2 +- src/text_recognizer/datasets/data_loader.py | 15 ++ src/text_recognizer/datasets/emnist_dataset.py | 177 +++++++++---- .../datasets/emnist_essentials.json | 1 + src/text_recognizer/models/__init__.py | 1 + src/text_recognizer/models/base.py | 230 +++++++++++++++++ src/text_recognizer/models/character_model.py | 71 ++++++ src/text_recognizer/models/util.py | 19 ++ src/text_recognizer/networks/lenet.py | 93 +++++++ src/text_recognizer/networks/mlp.py | 81 ++++++ src/text_recognizer/tests/__init__.py | 1 + src/text_recognizer/tests/support/__init__.py | 2 + .../tests/support/create_emnist_support_files.py | 33 +++ src/text_recognizer/tests/support/emnist/8.png | Bin 0 -> 498 bytes src/text_recognizer/tests/support/emnist/U.png | Bin 0 -> 524 bytes src/text_recognizer/tests/support/emnist/e.png | Bin 0 -> 563 bytes .../tests/test_character_predictor.py | 26 ++ src/text_recognizer/util.py | 51 ++++ src/training/run_experiment.py | 1 + src/training/train.py | 230 +++++++++++++++++ src/training/util.py | 19 ++ 28 files changed, 1437 insertions(+), 167 deletions(-) create mode 100644 src/notebooks/tqdm.ipynb create mode 100644 src/text_recognizer/character_predictor.py create mode 100644 src/text_recognizer/datasets/data_loader.py create mode 100644 src/text_recognizer/datasets/emnist_essentials.json create mode 100644 src/text_recognizer/models/base.py create mode 100644 src/text_recognizer/models/character_model.py create mode 100644 src/text_recognizer/models/util.py create mode 100644 src/text_recognizer/networks/lenet.py create mode 100644 src/text_recognizer/networks/mlp.py create mode 100644 src/text_recognizer/tests/__init__.py create mode 100644 src/text_recognizer/tests/support/__init__.py create mode 100644 src/text_recognizer/tests/support/create_emnist_support_files.py create mode 100644 src/text_recognizer/tests/support/emnist/8.png create mode 100644 src/text_recognizer/tests/support/emnist/U.png create mode 100644 src/text_recognizer/tests/support/emnist/e.png create mode 100644 src/text_recognizer/tests/test_character_predictor.py create mode 100644 src/text_recognizer/util.py create mode 100644 src/training/run_experiment.py create mode 100644 src/training/train.py create mode 100644 src/training/util.py diff --git a/.flake8 b/.flake8 index ff25eb1..23e3b65 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,6 @@ [flake8] select = ANN,B,B9,BLK,C,D,DAR,E,F,I,S,W -ignore = E203,E501,W503 +ignore = E203,E501,W503,ANN101,F401,D202,S310,S101 max-line-length = 120 max-complexity = 10 application-import-names = text_recognizer,tests diff --git a/README.md b/README.md index 7ddc4ef..4f4aa3a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ # Text Recognizer Implementing the text recognizer project from the course ["Full Stack Deep Learning Course"](https://fullstackdeeplearning.com/march2019) in PyTorch in order to learn best practices when building a deep learning project. I have expanded on this project by adding additional feature and ideas given by Claudio Jolowicz in ["Hypermodern Python"](https://cjolowicz.github.io/posts/hypermodern-python-01-setup/). + + +## Setup +--- + +TBC diff --git a/poetry.lock b/poetry.lock index 94c0a91..348987b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -930,6 +930,17 @@ optional = false python-versions = "*" version = "7.352.0" +[[package]] +category = "main" +description = "Wrapper package for OpenCV python bindings." +name = "opencv-python" +optional = false +python-versions = "*" +version = "4.2.0.34" + +[package.dependencies] +numpy = ">=1.11.1" + [[package]] category = "main" description = "Core utilities for Python packages" @@ -1634,6 +1645,17 @@ optional = false python-versions = ">= 3.5" version = "6.0.4" +[[package]] +category = "main" +description = "Fast, Extensible Progress Meter" +name = "tqdm" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*" +version = "4.46.1" + +[package.extras] +dev = ["py-make (>=0.1.0)", "twine", "argopt", "pydoc-markdown"] + [[package]] category = "dev" description = "Traitlets Python config system" @@ -1814,7 +1836,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["jaraco.itertools", "func-timeout"] [metadata] -content-hash = "baea2d4b995e2da9a1f07764142a9fef50bee4b61f2e041c8a05001f25cbc878" +content-hash = "4b4b531a4a45f81cf30cfdd45f34ef07a980689b5af2c99671e34c9ff9158836" python-versions = "^3.7" [metadata.files] @@ -2257,6 +2279,28 @@ numpy = [ nvidia-ml-py3 = [ {file = "nvidia-ml-py3-7.352.0.tar.gz", hash = "sha256:390f02919ee9d73fe63a98c73101061a6b37fa694a793abf56673320f1f51277"}, ] +opencv-python = [ + {file = "opencv_python-4.2.0.34-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:e3c57d6579e5bf85f564d6d48d8ee89868b92879a9232b9975d072c346625e92"}, + {file = "opencv_python-4.2.0.34-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:aa3ca1f54054e1c6439fdf1edafa2a2b940a9eaac04a7b422a1cba9b2d7b9690"}, + {file = "opencv_python-4.2.0.34-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:31d634dea1b47c231b88d384f90605c598214d0c596443c9bb808e11761829f5"}, + {file = "opencv_python-4.2.0.34-cp35-cp35m-win32.whl", hash = "sha256:78cc89ebc808886eb190626ee71ab65e47f374121975f86e4d5f7c0e3ce6bed9"}, + {file = "opencv_python-4.2.0.34-cp35-cp35m-win_amd64.whl", hash = "sha256:7c7ba11720d01cb572b4b6945d115cb103462c0a28996b44d4e540d06e6a90fd"}, + {file = "opencv_python-4.2.0.34-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6fa8fac14dd5af4819d475f74af12d65fbbfa391d3110c3a972934a5e6507c24"}, + {file = "opencv_python-4.2.0.34-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a37ee82f1b8ed4b4645619c504311e71ce845b78f40055e78d71add5fab7da82"}, + {file = "opencv_python-4.2.0.34-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:dcb8da8c5ebaa6360c8555547a4c7beb6cd983dd95ba895bb78b86cc8cf3de2b"}, + {file = "opencv_python-4.2.0.34-cp36-cp36m-win32.whl", hash = "sha256:ef89cbf332b9a735d8a82e9ff79cc743eeeb775ad1cd7100bc2aa2429b496f07"}, + {file = "opencv_python-4.2.0.34-cp36-cp36m-win_amd64.whl", hash = "sha256:f45c1c3cdda1857bedd4dfe0bbd49c9419af0cc57f33490341edeae97d18f037"}, + {file = "opencv_python-4.2.0.34-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c0087b428cef9a32d977390656d91b02245e0e91f909870492df7e39202645dd"}, + {file = "opencv_python-4.2.0.34-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:fb3c855347310788e4286b867997be354c55535597966ed5dac876d9166013a4"}, + {file = "opencv_python-4.2.0.34-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d87e506ab205799727f0efa34b3888949bf029a3ada5eb000ff632606370ca6e"}, + {file = "opencv_python-4.2.0.34-cp37-cp37m-win32.whl", hash = "sha256:b9de3dd956574662712da8e285f0f54327959a4e95b96a2847d3c3f5ee7b96e2"}, + {file = "opencv_python-4.2.0.34-cp37-cp37m-win_amd64.whl", hash = "sha256:d8a55585631f9c9eca4b1a996e9732ae023169cf2f46f69e4518d67d96198226"}, + {file = "opencv_python-4.2.0.34-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5fdfc0bed37315f27d30ae5ae9bad47ec0a0a28c323739d39c8177b7e0929238"}, + {file = "opencv_python-4.2.0.34-cp38-cp38-manylinux1_i686.whl", hash = "sha256:068928b9907b3d3acd53b129062557d6b0b8b324bfade77f028dbe4dfe482bf2"}, + {file = "opencv_python-4.2.0.34-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0e7c91718351449877c2d4141abd64eee1f9c8701bcfaf4e8627bd023e303368"}, + {file = "opencv_python-4.2.0.34-cp38-cp38-win32.whl", hash = "sha256:1ab92d807427641ec45d28d5907426aa06b4ffd19c5b794729c74d91cd95090e"}, + {file = "opencv_python-4.2.0.34-cp38-cp38-win_amd64.whl", hash = "sha256:e2206bb8c17c0f212f1f356d82d72dd090ff4651994034416da9bf0c29732825"}, +] packaging = [ {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, @@ -2618,6 +2662,10 @@ tornado = [ {file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"}, {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"}, ] +tqdm = [ + {file = "tqdm-4.46.1-py2.py3-none-any.whl", hash = "sha256:07c06493f1403c1380b630ae3dcbe5ae62abcf369a93bbc052502279f189ab8c"}, + {file = "tqdm-4.46.1.tar.gz", hash = "sha256:cd140979c2bebd2311dfb14781d8f19bd5a9debb92dcab9f6ef899c987fcf71f"}, +] traitlets = [ {file = "traitlets-4.3.3-py2.py3-none-any.whl", hash = "sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44"}, {file = "traitlets-4.3.3.tar.gz", hash = "sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7"}, diff --git a/pyproject.toml b/pyproject.toml index a1eff2e..3afeee7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,8 @@ torchvision = "^0.6.0" torchsummary = "^1.5.1" loguru = "^0.5.0" matplotlib = "^3.2.1" +opencv-python = "^4.2.0" +tqdm = "^4.46.1" [tool.poetry.dev-dependencies] pytest = "^5.4.2" @@ -50,8 +52,13 @@ jupyter = "^1.0.0" [tool.coverage.report] fail_under = 50 + [tool.poetry.scripts] download-emnist = "text_recognizer.datasets.emnist_dataset:download_emnist" +create-emnist-support-files = "text_recognizer.tests.support.create_emnist_support_files:create_emnist_support_files" +# mlp = "text_recognizer.networks.mlp:test" +# lenet = "text_recognizer.networks.lenet:test" + [build-system] requires = ["poetry>=0.12"] build-backend = "poetry.masonry.api" diff --git a/src/notebooks/01-look-at-emnist.ipynb b/src/notebooks/01-look-at-emnist.ipynb index 403d4a7..870679b 100644 --- a/src/notebooks/01-look-at-emnist.ipynb +++ b/src/notebooks/01-look-at-emnist.ipynb @@ -2,18 +2,9 @@ "cells": [ { "cell_type": "code", - "execution_count": 35, + "execution_count": 1, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - } - ], + "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2\n", @@ -21,8 +12,8 @@ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", + "from PIL import Image\n", "from importlib.util import find_spec\n", - "from torchvision.transforms import ToTensor\n", "if find_spec(\"text_recognizer\") is None:\n", " import sys\n", " sys.path.append('..')" @@ -30,226 +21,181 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ - " from text_recognizer.datasets.emnist_dataset import fetch_dataloader" + "from text_recognizer.datasets.emnist_dataset import fetch_data_loader, fetch_emnist_dataset, load_emnist_mapping" ] }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ - "from torchvision.datasets import EMNIST" + "dataset = fetch_emnist_dataset(\"byclass\", True, True)" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 25, "metadata": {}, "outputs": [], "source": [ - "data_dir = \"/home/akternurra/Documents/projects/quest-for-general-artifical-intelligence/projects/text-recognizer/data\"" + "dl = fetch_data_loader(\"byclass\", True, True, shuffle=True, batch_size=9)" ] }, { "cell_type": "code", - "execution_count": 106, + "execution_count": 52, "metadata": {}, "outputs": [], "source": [ - "dl = fetch_dataloader(root=data_dir, train=True, split=\"byclass\", download=False, batch_size=1, transform=ToTensor())" + "classes = load_emnist_mapping()" ] }, { "cell_type": "code", - "execution_count": 123, + "execution_count": 55, "metadata": {}, "outputs": [], "source": [ - "dataset = EMNIST(\n", - " root=data_dir,\n", - " split=\"byclass\",\n", - " train=True,\n", - " download=False,\n", - " transform=ToTensor())" - ] - }, - { - "cell_type": "code", - "execution_count": 119, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "697932" - ] - }, - "execution_count": 119, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(dataset)" + "def display_dl_images(dl, batch_size, classes):\n", + " fig = plt.figure(figsize=(9, 9))\n", + " batch = next(iter(dl))\n", + " for i in range(batch_size):\n", + " x, y = batch[0][i], batch[1][i]\n", + " ax = fig.add_subplot(3, 3, i + 1)\n", + " x = x.squeeze(0).numpy()\n", + " ax.imshow(x, cmap='gray')\n", + " ax.set_xticks([])\n", + " ax.set_yticks([])\n", + " ax.set_title(classes[int(y)])" ] }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ - "data = next(iter(dl))" + "def display_images(dataset, classes, shift=0):\n", + " fig = plt.figure(figsize=(9, 9))\n", + " for i in range(9):\n", + " x, y = dataset[i + shift]\n", + " ax = fig.add_subplot(3, 3, i + 1)\n", + " x = x.squeeze(0).numpy()\n", + " ax.imshow(x, cmap='gray')\n", + " ax.set_xticks([])\n", + " ax.set_yticks([])\n", + " ax.set_title(classes[int(y)])" ] }, { "cell_type": "code", - "execution_count": 75, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ - "emnist_essentials = {\"mapping\": [[0, \"0\"], [1, \"1\"], [2, \"2\"], [3, \"3\"], [4, \"4\"], [5, \"5\"], [6, \"6\"], [7, \"7\"], [8, \"8\"], [9, \"9\"], [10, \"A\"], [11, \"B\"], [12, \"C\"], [13, \"D\"], [14, \"E\"], [15, \"F\"], [16, \"G\"], [17, \"H\"], [18, \"I\"], [19, \"J\"], [20, \"K\"], [21, \"L\"], [22, \"M\"], [23, \"N\"], [24, \"O\"], [25, \"P\"], [26, \"Q\"], [27, \"R\"], [28, \"S\"], [29, \"T\"], [30, \"U\"], [31, \"V\"], [32, \"W\"], [33, \"X\"], [34, \"Y\"], [35, \"Z\"], [36, \"a\"], [37, \"b\"], [38, \"c\"], [39, \"d\"], [40, \"e\"], [41, \"f\"], [42, \"g\"], [43, \"h\"], [44, \"i\"], [45, \"j\"], [46, \"k\"], [47, \"l\"], [48, \"m\"], [49, \"n\"], [50, \"o\"], [51, \"p\"], [52, \"q\"], [53, \"r\"], [54, \"s\"], [55, \"t\"], [56, \"u\"], [57, \"v\"], [58, \"w\"], [59, \"x\"], [60, \"y\"], [61, \"z\"]], \"input_shape\": [28, 28]}\n" + "classes = load_emnist_mapping()" ] }, { "cell_type": "code", - "execution_count": 78, + "execution_count": 56, "metadata": {}, "outputs": [ { "data": { + "image/png": "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\n", "text/plain": [ - "'0'" + "
" ] }, - "execution_count": 78, "metadata": {}, - "output_type": "execute_result" + "output_type": "display_data" } ], "source": [ - "emnist_essentials[\"mapping\"][0][-1]" + "display_images(dataset, classes)" ] }, { "cell_type": "code", - "execution_count": 124, + "execution_count": 57, "metadata": {}, "outputs": [ { "data": { - "image/png": "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sce6LKqFadOy7WodNZVdddVVFd03au6tRZNauYbBTb311ltVP3YzirbXLrc997p161wW1Wsket0qfS074rnnnnPZhRde6LLofe/JJ5902SuvvOKyVatWhcemKRMAAKBCTCgAAEBmTCgAAEBmTCgAAEBm7XbNmNk1ko6TtCSlNLaUXSzpHyV9sP/xN1JKLD+XQ++++67LFixY4LKo6WjSpEkuO/74410WNWrNnTs3HE/U6FUPzVDHu+yyS0VZ9L2PGsjqpRavedS0t9tuu1X9OHlS7xp+5513XBat0itJb7/9tst69+7d6WNHr29Hti+PrF271mWPPfaYy3r16uWyaJvzNWvWuKyrNF+WU8kZimslHRXk30spjSv9yu2bMFByrahjFNu1ooaRY+1OKFJKD0ry0zOgQKhjFB01jLzL0kNxjpnNNrNrzGxguRuZ2WQzm2lmMzMcC6iVduuYGkbOUcPIhc5OKH4qaTtJ4yS1SvpOuRumlKaklManlPwWl0BjVVTH1DByjBpGbnRqpcyU0uIPvjazqyXdVrURldGtW7cwjxp1osaYrtosEz3vqMHojjvucNmECRNc1q9fP5f179+/k6NrrEbUcRYnnHCCy6IGsttvv91ljWqGrZWoaW/XXXdtwEgaq5Y1HG3Z/dRTT4W3ffXVV102dOjQio4zcKA/qTJu3DiXjR492mXRluRSvE16lC1btqySIaJCnTpDYWYbr006SdKc6gwHqB/qGEVHDSNPKrls9HpJB0saYmYLJV0k6WAzGycpSWqRdGYNxwhkRh2j6Khh5F27E4qU0ilB/MsajAWoGeoYRUcNI+9YKRMAAGSWy+3LBw0a5LK//du/DW/bo0cPl0Vbdt9zzz0ue++99zoxuuKLGlmHDBniss0339xlNLzWR/Qabbnlli7bsGGDy2bNmlWTMeVJ1GAXrQa63Xbb1WM4TSlq5G1tbQ1ve++997ps7NixLuvZs6fLBg8e7LLDDz/cZRdddJHLrrzyynA80TjfeOMNl0V1hM7jDAUAAMiMCQUAAMiMCQUAAMiMCQUAAMiMCQUAAMisMFd5fPGLXwxv+5GPfMRlr7/+ussuu+wylz344IMui7qDo27nqLteyt8VD9ESxdFSt5/85CddFj2XRx991GXRVQV5+z4UTbTM8OTJk10WLXl855131mRMeRJ1569ataoBI+la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\n", + "image/png": "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9v3vf99lt9xyi8tUMxypk5eX5zLV2jbT30i45557XHbeeee5rF+/fi5T357Zu3evy5YvXy7X8/jjj7ts69atLjt27Jh8PqqGw4cPu2zatGmxn//000+7LDs722UdOnRw2bXXXusydV0n+nth2bJlLtu8ebN8bCbjDgEAAGAgAAAADAQAAMAYCAAAgKVpqVAVCH/1q1+5rFmzZi578cUXXTZ16tTYr63KUlOmTHGZOq9bFVJeffVVl6lS4Z49e+R61NbFqgyjtpx9+OGHXabOFK9Z018GqmhoZrZ27VqZo2KpLWPVtWpmtmPHDpcVFxe7LO622oraAjvRduBLly512dGjR8v82qg6CgsLZf7KK6+4rEuXLi4bM2aMy5o2beoy9ZmpPlsTbZWtCoRFRUXysZmMOwQAAICBAAAAMBAAAABjIAAAAJampUJ1JnXr1q1dpgogauer0uwopcpSDz30UOznf12yu6+pX6MqL86ePdtlqjQzbtw4l1144YUuU2fTm5ndfPPNsdaIiqeuVTNd/CwoKHCZKuXGLVqpkuL+/fvlelRhlmsG30QV9p588kmXtWnTxmUjR450mSqBK6p8aGZ22WWXuWzXrl0uU7vDJtr9MB1xhwAAADAQAAAABgIAAGAMBAAAwNKgVKhKTLfffrvL1FGtW7Zscdm8efNcpo4gLo1MOJZV/RpnzJjhss8//9xlb7/9tstUacyMMlg6SXRdq93fyvsabty4sct69uwpH6uO5l63bp3LuLbwTXbu3OkyVeLr27evyzp16uSy0lxv7du3d5k6UlkdSU6pEAAAZBQGAgAAwEAAAAAYCAAAgKVBqbBWrVou+853vuMytdPUv/71L5dRTPpmeXl5Ljty5IjL1BHUZqU7MhTlR/2+q7KemVmfPn1cpkqAStwCrro+Bg0aJB975513uuzuu+922bZt21x2+PDhWOtB1af+Djj77LNdlpOT4zJVkt66davLWrZsGfu1M6ksGBd3CAAAAAMBAABgIAAAAMZAAAAALA1Khbm5uS7r1atXrOc+++yzLkt0JCyOU+U0pD91JLgqVJmZnX/++S5r0KCBy1SZVB2TrK4Z9b5NdMTsOeec4zK1m9yyZctc9umnn7rs6NGjLqPYWvWpwt/YsWNdpq7NVatWuezHP/6xy2644Qb52meddZbL1A6vmV405A4BAABgIAAA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\n", "text/plain": [ "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], "source": [ - "fig = plt.figure(figsize=(9, 9))\n", - "for i in range(9):\n", - " x, y = dataset[i]\n", - " ax = fig.add_subplot(3, 3, i + 1)\n", - " ax.imshow(x.reshape(28, 28).T, cmap='gray')\n", - " ax.set_title(emnist_essentials[\"mapping\"][int(y)][-1])" + "display_dl_images(dl, 9, classes)" ] }, { "cell_type": "code", - "execution_count": 125, + "execution_count": 58, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - ":4: MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance.\n", - " ax = fig.add_subplot(3, 3, i % 9 + 1)\n" - ] - }, { "data": { - "image/png": "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kstasfksL2pVw1GzZbSSameaIAcNGuSyqI4qFa1MGTVGStKll17qsuh1L1rt9Z133nFZtEJotHrs5MmTw/F8/etfd9maNWvC2xZZVUcozGzwTt+eI2l+bYYDNA51jKKjhpEnlZw2erekUyQNMLPlkr4l6RQzGy0pSWqTdHEdxwhkRh2j6Khh5F2HE4qU0gVBfGsdxgLUDXWMoqOGkXeslAkAADLrMpcvj5qJDjjgAJedddZZLoua3MqJGtCi1eEeffRRl0WXfr733ntd9ud//ucuO+aYY8LxDBkyxGV77723y6KGpT/84Q8ua6WmzFYQNd2ee+65Lrv66qtdNnz48PAxo4bhn/70py6bPn26y7jkfTFFr1tLliyp+P5RI++AAQNctnr1apcNHjzYZWPHjnXZN7/5TZdFr29S/LyI9udb3/qWyxYtWuSyW265xWVHHXWUy84///xwPH37+rN5/+Ef/qGibUeXPo/271Of+pTLDjnkkHA80f5Ez/vO4ggFAADIjAkFAADIjAkFAADIjAkFAADIjAkFAADIrMuc5RF12UbLTQ8dOjTTdnbs2OGyJ5980mU333yzy1544QWXRUvDHnvssS7r169fpUMMz9SYPXu2y6KObDRPtDzy4Ycf7rIrr7zSZVG397Jly8LtTJs2zWW33367y95+++3w/mgN0dlp0RkHUnymRnRWRnQWwymnnOKygw46yGXRWSPlRGcb3XbbbS677777XBad8fLYY4+5LDrLIzr7QpI++9nPuiw6y+rxxx93WXQJhGgp8PHjx7ts4MCB4XheeeUVlz300EMui/49+zAcoQAAAJkxoQAAAJkxoQAAAJkxoQAAAJl1mabMnj17uixqiunVq1em7URNlL/97W9dNm/ePJe98cYbLuvTp4/LDjzwQJd179690iGGjVVvvvmmy6KmLDRPtDx61ID50Y9+1GVRA2XUfClJ119/vcui+kBri5qyV65cGd42avqNGhGjJr/osgiVeuutt8I8uoxBtNx09LzYbTf//+yHH37YZZ///OddVm45+27durksauocNWpUeP9KRL/HqMFUkkaMGOGyqOm7szhCAQAAMmNCAQAAMmNCAQAAMmNCAQAAMuuwG8bMhkr6qaRBkpKkqSmlfzKzfpJ+Lmm4pDZJ56WUNtRvqNlEDSvRamOdaW6MvPbaay6bPn26y6LV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AAAgsy59+fKokTHKokbLkSNHho8ZrTIYrVJ4xBFHuKx///4VZVGTWrnLfb/zzjsu+/d//3eXRQ1tTz75pMteffVVl23YsMFl27ZtC8eD6u29994ui+rtyiuvdNlRRx3lsqiOynn33Xdd9tprr7ns+eefd9myZctcdvLJJ7ts+PDh4bb79u3rsmjF1gsvvNBljz/+uMtWrFgRbgco56yzznLZjTfe2ISR5BtHKAAAQGZMKAAAQGZMKAAAQGZMKAAAQGaFb8qMmiijVfiGDh3qsqOP9qduR81r++yzj8tOPfXUcDwf/ehHKxpPuZUtK8+d/XsAACAASURBVLF+/XqXRQ2UUryK5fTp010WNc7RWNkYUXPksGHDXBZdtv5LX/qSy6Lmxs408i5dutRld955p8tmzJjhsqhpN6qjWbNmueyKK64Ix3P88ce77L333nNZtIpr9FwBOqt3797NHkIhcIQCAABkxoQCAABkxoQCAABkxoQCAABkVpimzGiVQEm6/PLLXRatmBc1uUWXfo6aJaPLL5draIsa0KJVBqNGz8iaNWtcdumll7rsvvvuC+8fXU4a+bLffvu57Fvf+pbLPv/5z7usZ8+eFW0jqsFHH300vG10qfNoxcmoMbJfv34uO/vss102efJkl0WXXZfihtJolc5f/OIXLov2G0B9cIQCAABkxoQCAABkxoQCAABkxoQCAABk1mFTppndJulMSWtSSkeWsn6Sfi5puKQ2SeellPw1rGvomGOOCfOo4euQQw5xWdREGa0OuXXrVpdt3rzZZdHlviVp48aNLovGHo07auh8+OGHXRatMkjz5YfLQx336NEjzE866SSXnX766S6rtAEzaiKOVkf97ne/G94/quHDDjvMZZ/85Cdd9olPfMJlJ554osuiRtRyl1OP9id6DkTP51aShxoGPkwlRyimSTptl2yKpCdSSiMlPVH6HsizaaKOUWzTRA0jxzqcUKSUZkl6fZd4vKTbS1/fLmlCjccF1BR1jKKjhpF31a5DMSiltLL09SpJg8rd0MwmSZpU5XaAeqqojqlh5Bg1jNzIvLBVSimZmX+T8z9/PlXSVEn6sNsBzfRhdUwNowioYTRbtWd5rDazwZJU+uyXcwTyjzpG0VHDyI1qj1DMkDRR0nWlzw/UbERlLFy4MMy///3vu+zII4902ZtvvumyqFN806ZN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evXq5bL58+M/wezZs122du3aisbY6opYx3kSPaeieosag6NVC6PLWEtxg94RRxzhsl/+8pcumzdvnstaaTXPvNRwVAsvvviiyxYsWOCys88+22VRLUTNkoMGDQrHc+yxx7pswoQJLjv55JNdFjVgRs2S77zzjstmzZoVjqetrc1lrbjicYcTCjO7W9IpkgaY2XJJ35J0ipmNlpQktUm6uI5jBDKjjlF01DDyrsMJRUrJn/Mo3VqHsQB1Qx2j6Khh5B0rZQIAgMyYUAAAgMxa8vLl0cp8UdNitKpfdCndaJXNqHGnnKjhMWpK22uvvVy23377uSxapTNaeVOSHn74YZddc801LnvttddcFjUdIV8++9nPumzlypUuK1cfkai2oya3SPT8+da3vuWyaNzRKrOS1K9fP5e99957LosusX7WWWe5LGoSRe1FjYxR82YkWp04eh0usV31WAAACq9JREFU1xx/yimnuCxq6oxehyMbNmxw2YoVK1z2xz/+Mbx/pftddByhAAAAmTGhAAAAmTGhAAAAmTGhAAAAmTGhAAAAmbXkWR5RR+4LL7zgsqVLl7ps7733dlnPnj1dVm6p6qg7OcoilS5/3b17d5dFnfCSdN5557ks6mx+5JFHXHbvvfe6bMuWLS7rist2N0N09sVVV13lssGDB7ss63LT0bLwUdf92LFjXXbCCSe4rNLljaV4uebp06e77I477nDZ669zte8iimorWo77tNNOC+8fLal94IEHVrTtd99912W33HKLy6LXzDlz4muvcZYHAABAhZhQAACAzJhQAACAzJhQAACAzFqyKTNqgImWHo6W4+7Tp4/LRowY4bJyjZZRg2KlTZmRqJkuWia7nP33399lH//4xyu679NPP+2yaFnnqFETtRc1LX7lK19x2Y9//GOXRUsUR7Uuxc1vUSNwVOvRc+/FF190WdRA+atf/SocT3T/qHEOrSNqyoyWdb/sssvC+0fN9VEzelTDL7/8ssv+9V//1WWLFi1yWVd/LeQIBQAAyIwJBQAAyIwJBQAAyKzDCYWZDTWzX5nZi2a2wMwuL+X9zGymmS0qffZvvAI5QA2jFVDHyLtKmjK3SboipfScme0j6Vkzmynpv0l6IqV0nZlNkTRF0tfrN9TKRY1h69evd9m1117rsuOOO85lf/d3f+eyww8/PNx2jx49KhlixY2aa9ascdn3v//9iu4rxSspHnLIIS6Lmjeff/55l0UrFL7yyisVj6dJClfDlYpWgD3++OMrum/UfClJxxxzjMseeughly1btsxlF198scueeuopl9FUWZWWreNKRK+ZvXv3zvSYa9euddlNN93ksqhRs6s3YEY6PEKRUlqZUnqu9PVmSQslDZE0XtLtpZvdLmlCvQYJZEENoxVQx8i7Tp02ambDJR0j6XeSBqWU3j+HcJWkQWXuM0nSpOqHCNQONYxW0Nk6pobRCBU3ZZpZL0n3SpqcUvrAog6p/WTe8ApRKaWpKaUxKaUxmUYKZEQNoxVUU8fUMBqhogmFmXVXewHflVK6rxSvNrPBpZ8PluTf7AdyghpGK6COkWcdvuVh7Z0wt0pamFK6YacfzZA0UdJ1pc8P1GWENRKtiBY1Ey5fvtxl0Up9V155Zbid//Jf/ovLDj74YJdFl2+ODBw40GVRk2hn7h81N+21114u+8QnPuGy6HfW1tbmsjxdrrdVarhS27Ztq+h2UaOyJPXs2dNlUc08++yzLouaRGnArI2uVMeVNq1Hr+uduW208m/UjP7ee+9VvJ2urJIeihMkXShpnpm9/5u+Su3F+3/N7CJJSyWdV58hAplRw2gF1DFyrcMJRUrpKUnlpoufru1wgNqjhtEKqGPkHStlAgCAzJhQAACAzFry8uWVipp0otXPosvUPvLII+FjRg1x0Wpu0aV4o0bN6LLRBx54YLjtSKXNn9Hlgg866CCXDRs2zGVZLs+O5hkwYECYf+ELX3BZ1JR2zTXXuCxaeRDorM40W0beeecdl7322msui1Ydfumll2o+nq6CIxQAACAzJhQAACAzJhQAACAzJhQAACCzLt2UWam3337bZf/2b/8W3nbmzJkue/DBB112/vnnu2zkyJEVZVGjZjlRk2jUYBQ13c2fP99lf/rTnyp6POTfhRdeGOann366y6JLlS9cuLDmY0LriF573njjDZdFDZTRyr3R68yGDRvCbT/88MMue+yxx1x2//33u4zLklePIxQAACAzJhQAACAzJhQAACAzJhQAACAzmjKrVK5xZ82aNS6LGn9mz57tsv33399ln/60v+ZPtPJmZ0SXFn/zzTddNn36dJetWrWqosdDvkSrYp500knhbXv06OGy3/zmNy7bvn179oGhZUWXBo9eUyLRa1z0OhM1jkvS008/7bJNmza5jAbM2uIIBQAAyIwJBQAAyIwJBQAAyIwJBQAAyKzDCYWZDTWzX5nZi2a2wMwuL+VXm9kKM3u+9HFG/YcLdB41jKKjhlEE1tGyyWY2WNLglNJzZraPpGclTZB0nqQ3U0o/qHhjZqzRXNKtWzeXRUtqR2d+7L577U/OiZbJjbq0oyW6G7j09rMppTGdvVNXq+HddvP/Txg7dqzLfvCDeLc3b97ssjPPPNNl0ZL06FCXqWEzc1l0BtHgwYNdVulrXHTmhiS9/vrrLuOspJopW8Md/tVSSislrSx9vdnMFkoaUtvxAfVDDaPoqGEUQad6KMxsuKRjJP2uFF1qZnPN7DYz61vmPpPMbI6Zzck0UqAGqGEUHTWMvKp4QmFmvSTdK2lySukNST+SNELSaLXPnK+P7pdSmppSGlPNYT6glqhhFB01jDyraEJhZt3VXsR3pZTuk6SU0uqU0vaU0g5JP5Z0XP2GCWRDDaPoqGHkXYc9FNbeWXOrpIUppRt2ygeX3teTpHMkxWugIhQ1CEVZW1tbA0bT2rpaDUdLFD/55JMu+8QnPhHeP2qypaGtuYpYw1EdRUtd8xrXOipppT1B0oWS5pnZ86XsKkkXmNloSUlSm6SL6zJCIDtqGEVHDSP3OjxttKYbK8Apd8i1qk65q6VWquFyp+ZxhKKuqGEUXdkaZqVMAACQGRMKAACQWe2XXARQCNHqqABQLY5QAACAzJhQAACAzJhQAACAzJhQAACAzBrdlLlO0tLS1wNK37cC9qUxhjV7AKKGiyKv+0MN108r7YuU3/0pW8MNXdjqAxs2m9PsBV5qhX3pmlrpd9VK+yK13v7USyv9nlppX6Ri7g9veQAAgMyYUAAAgMyaOaGY2sRt1xr70jW10u+qlfZFar39qZdW+j210r5IBdyfpvVQAACA1sFbHgAAILOGTyjM7DQze9nMFpvZlEZvPyszu83M1pjZ/J2yfmY208wWlT73beYYK2VmQ83sV2b2opktMLPLS3kh96dRqOH8oIarV+Q6pobzqaETCjPrJumHkk6XNErSBWY2qpFjqIFpkk7bJZsi6YmU0khJT5S+L4Jtkq5IKY2S9HFJl5T+HkXdn7qjhnOHGq5CC9TxNFHDudPoIxTHSVqcUnolpfSepHskjW/wGDJJKc2S9Pou8XhJt5e+vl3ShIYOqkoppZUppedKX2+WtFDSEBV0fxqEGs4Rarhqha5jajifGj2hGCLp1Z2+X17Kim5QSmll6etVkgY1czDVMLPhko6R9Du1wP7UETWcU9Rwp7RiHRf+b170GqYps8ZS+2kzhTp1xsx6SbpX0uSU0hs7/6yI+4Nsivg3p4axsyL+zVuhhhs9oVghaehO3x9YyoputZkNlqTS5zVNHk/FzKy72ov4rpTSfaW4sPvTANRwzlDDVWnFOi7s37xVarjRE4rfSxppZgebWQ9J50ua0eAx1MMMSRNLX0+U9EATx1IxMzNJt0pamFK6YacfFXJ/GoQazhFquGqtWMeF/Ju3VA2nlBr6IekMSX+U9CdJf9/o7ddg/HdLWilpq9rfd7xIUn+1d+EukvS4pH7NHmeF+3Ki2g+jzZX0fOnjjKLuTwN/b9RwTj6o4Uy/u8LWMTWczw9WygQAAJnRlAkAADJjQgEAADJjQgEAADJjQgEAADJjQgEAADJjQgEAADJjQgEAADJjQgEAADL7f6JlPvTmWtEOAAAAAElFTkSuQmCC\n", + "image/png": "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l11WXV0tnw8kopoA404LVI2CF154oXzs2LFjXfad73zHZX369HHZ7NmzXbZ8+XKX0VQIAABSAgUBAACgIAAAABQEAADAKAgAAIBxlwGQtgoKCmT+wx/+0GXnnnuuyz777DOXLViwwGWq+1l1cquxx2b6DocPPvjAZRs3bpTPR8uj7gDo3bu3y9So4OHDh8c6Rm5urssmTZokH9u3b1+XJbrL50T9+/d3WceOHV1WXl4e6/UaE1cIAAAABQEAAKAgAAAARkEAAACMpkIgLbRv395lP/nJT+RjBw4c6LKVK1e67K677nLZRx995LIoilymmgoXLlwo13PHHXe47JxzznHZ1q1bXcY44+YjhOCy7t27y8dOmDDBZdOnT3dZfn6+yzp37lyH1R0Xt1EwETXSe+fOnS7LyclxGU2FAAAgJVAQAAAACgIAAEBBAAAAjKZCIOV069bNZb/4xS9cppoHzcx+/vOfx8qqqqpcphq/1KS16667zmVqkpyZ2X333eey73//+y5jemF6UueMava7/vrrXTZt2jT5mur5rVu3jrWeuJM11bpVA20iNTU1LisqKnLZ888/7zLVQJsKuEIAAAAoCAAAAAUBAAAwCgIAAGA0FQIpRzVUjR071mXr16+Xz3/55ZddduDAAZeppiq1nayaaHjFFVe4bPPmzXI9qiHyxRdfdNmePXvk85Ha1Pn60EMPuUxtj52dnR37OKqJT51zW7ZscdmYMWNcphoNE9m7d6/Lli1b5rJ169a5bPfu3S47cuRI7GM3Ja4QAAAACgIAAEBBAAAAjIIAAABYAzQVZmZmuqygoMBlQ4cOlc9X09KeffZZl6ktJIF0165dO5dNnDjRZb169XLZww8/LF9TTfdT0w9VM9hvf/tbl6lJhaopKlGTlpoct2bNGpfVZkocUseVV17psvo2EKqtgJ977jmXLVq0yGVt27Z12eDBg12WaOtlRTW8/uu//qvLSktLXaaaClMVVwgAAAAFAQAAoCAAAABGQQAAAKwBmgrVlqdPPfWUyzp06BD7NW+55RaXTZgwwWWff/557NcEUpFqtFINUKpR6oEHHpCvec8997isY8eOLsvKynLZr3/9a5f96U9/ctkFF1zgsvHjx8v1KDQQpic13VI1jKvzVVENp2ZmS5cuddnPfvYzl+3YscNl/fr1c5maXlibpkL1/jn77LNdtnbtWpel6lRChSsEAACAggAAAFAQAAAAoyAAAADWAE2FZWVlLps6darLRo8eLZ8/ZcoUlw0bNsxlhYWFLjv33HNdpiZcKRkZ+kvv27evyyZNmuSy3Nxcl6kGmVdeecVlRUVFLqPJqmVS26qqSZ3q/aOap8zMKioqXKa2iVXn5iOPPOKyvLw8l919990u279/v1zPV199JXOkH/U5pT5z436eJXqcOl+rq6tdlpOT47Jt27a57L333nPZ8OHDY6zwuO3bt8c6zuHDh2O/ZiriCgEAAKAgAAAAFAQAAMAoCAAAgFEQAAAAa4C7DFSX6B/+8IdYmZnZL37xC5ctW7bMZWo8ZkFBgcvmzZvnMjVS9d5775XrOeOMM1ym9qyP66677nLZP/7jP7rshRdekM8/evRonY+N1Kd+vn/84x9dpu5gGTVqlHzN4uJil61atcplX375pctUJ/eIESNcpu7Gefrpp+V61HhZNB9Llixxmboz69RTT3VZ69at5Wuqz0h1R9onn3zisnfeecdlXbt2dZkaw5zoLgE1SlkdO53GFCtcIQAAABQEAACAggAAABgFAQAAsAZoKqyvqqoql82fP99laszkj370I5f17t3bZT/4wQ9clmgvbNUkeejQIZdt3brVZZ06dXJZt27dXDZz5kyXJRr7+uqrr8r8RKo5p0OHDi5T3++amppYx0DTUOebOg/inhu1oUZ6q/eeOtcTncPp3miFv27hwoUue/DBB12mGqwHDhwoX7Nt27YuU42sJ598ssvGjh3rMnUOqs/MRJ+FapSy+ixNd1whAAAAFAQAAICCAAAAGAUBAACwFGgqVNTUvhkzZrhs2LBhLlMTDdVEKjXNysxs9uzZLvv4449dppoK8/PzXVZYWOgyNbHr17/+tVzP2rVrZX4i9f25+OKLXaYaYZ5//nmX/exnP5PHUZPsALRcarqfmhhbUlLiMjV9MFE+YMAAl2VlZblMNSSqTMnNzZW5amBXn+P333+/y3bu3Bnr2KmAKwQAAICCAAAAUBAAAACjIAAAAJaiTYUNveXvs88+6zLVJGJmVl5eXufjbNiwwWVXXXWVy9T2tj169JCvuXz58ljHVtt7qi1z1XQu1QjzxhtvyOOsWLHCZWq6I1oedb6hZVLNx2vWrHHZ+vXr5fPVtFq1jf0555zjMtVsrmRmZrosLy9PPlZ9Pk+cONFlqolcfS2piisEAACAggAAAFAQAAAAoyAAAACWok2F9VFUVOSym2++2WUHDx5siuXY6tWrXXbrrbe6TE1nNNPbNKvmrY0bN7ps2rRpLlMNlv3793fZr371K7meq6++Otax0bypc7C4uDj2YwEzPeXQTDcgqqmtc+bMcVnHjh1jHVtt4f3AAw/Ix373u991WefOnV2mJuXSVAgAANIKBQEAAKAgAAAAFAQAAMDSvKmwpqbGZW+//bbLmqqBMK6VK1e67NChQ/Kx2dnZLtu1a5fLZs2a5bI//elPLluyZInLVFOh2srZzGzEiBEuo6mw+VDT29SWsKpRUDXQJnosUFvq8159FqpMUef6qlWr5GMnTJjgshCCy1q1Su/fsdN79QAAoEFQEAAAAAoCAABAQQAAACxFmworKipctmnTJpcdOHDAZYsXL26UNTUk9bU88cQT8rH/8i//4rJnnnnGZb///e9dpraRvvvuu112+eWXu0xN4TIzO//88122YMECl7ElcnoaOHCgyy6++GKX7d+/32WVlZWNsiagMcSdNGimmwWbY7MsVwgAAAAFAQAAoCAAAABGQQAAAIyCAAAAWIreZVBeXu6yc88912XqLoNE+2unEtWBP3v2bPlY1bk9d+5clyUafXyiPXv2uKysrMxl3bt3l8+/6qqrXPbQQw+5TN0pgtSiOqd/9KMfuUzdeVBSUuKyvXv3NszCgAaWlZXlMjWO+LzzzpPPV+8VdRdXut95wBUCAABAQQAAACgIAACAURAAAABL0aZCZffu3cleQqMqLS2V+axZsxr0OGpP8WuuucZliUYp//a3v3UZDYTpSTVajRs3zmVqTPHDDz/sMnVuofnLyGiaf0binl+tW7d22RlnnOGy22+/3WWJmqkV1URbXFwc+/mpiCsEAACAggAAAFAQAAAAoyAAAACWRk2FaDyff/65yy677DL5WDWdC+mpZ8+esbJ169a5bOXKlY2yJqS2tm3buuyWW25xWW5ubr2Ooya0zps3z2Vbt251WUFBgctuuOEGlw0aNMhlIQS5nurqapcVFha67P3335fPTxdcIQAAABQEAACAggAAABgFAQAAMJoKkQDNg81fmzZtXKa2eX333Xdd9uWXXzbKmpA61MS/Sy+91GUzZ850mZqCWRvl5eUuO3jwoMvUlFQ1RTM/P99l6utL9LmnGmsf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\n", "text/plain": [ "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], "source": [ - "fig = plt.figure(figsize=(9, 9))\n", - "for i in range(9, 19):\n", - " x, y = dataset[i]\n", - " ax = fig.add_subplot(3, 3, i % 9 + 1)\n", - " ax.imshow(x.reshape(28, 28).T, cmap='gray')\n", - " ax.set_title(emnist_essentials[\"mapping\"][int(y)][-1])" + "display_dl_images(dl, 9, classes)" ] }, { "cell_type": "code", - "execution_count": 126, + "execution_count": 59, "metadata": {}, "outputs": [ { "data": { - "image/png": "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i6bZrly5MnzMa665xmXLly+vaD0fhCMUAAAgMzYUAAAgMzYUAAAgMzYUAAAgs626KTNqyKm0AbNcU+buu+/usqixMuvktUrV+tLiUfNnv379XHbkkUeG948maNKUWX9RbZWblBldlvyJJ55w2WuvveayaNprVDPRc5RrEo2azaLmz1tvvdVltZ5QiNrr1auXy372s5+57PDDD3fZQw89FD7mLbfc4rJjjjnGZUOHDnVZ1JQZ/bci+pmKprVK0g477OCyqDHyS1/6ksuOO+44lw0YMMBlO+64o8sWLlwYruepp55y2X333eeyqAn/g3CEAgAAZMaGAgAAZMaGAgAAZMaGAgAAZNZqU6aZXSvpWElLU0pDSlkvSTdJGihpnqSTU0pv1m+ZbWNmLttpp51cNnLkSJedc845Lttzzz1dVu7y5ZWKGiOjBrKoyWfJkiUuK9fYOGfOUQMtkgAAEUhJREFUnIqyaD29e/d22SmnnOKyqKnqE5/4RLieaELosmXLwtvWUhHruJai2rrpppvC25533nku+8IXvuCyI444wmV9+vRxWdZpr9Gllr/61a+67Oabb67oeYqqvdZw9P4RvTdHjZFRw64kHXLIIS7r1q2by6Kmwzff9N++pUuXuixqjIyajSXpsMMOc1k0ffPv//7vXRZNsFyzZo3LoonM7777brieN954w2VtbcCMVHKEYqKko7bIxkm6P6W0u6T7S18DeTZR1DGKbaKoYeRYqxuKlNJUSVsORj9B0qTSnydJGlXjdQE1RR2j6Khh5F21cyj6pJQWlf68WJI/zlliZmMlja3yeYB6qqiOqWHkGDWM3Mg82CqllMys7IcvKaUJkiZI0gfdDmimD6pjahhFQA2j2ao9y2OJmfWVpNLvvmMFyD/qGEVHDSM3qj1CcaukMZIuLf3++5qtqI2iDvK9997bZdHZG1EncXQ2SHTWSDlRR/rrr7/ushkzZrhs3rx5LotGp06dOtVlq1atCtezevVql0UdwlGndTTytRadwDmSmzpuhl/+8pdhPmjQIJedfPLJLotGrkfd8DvvvLPLPvShD7ms3Jjse+65x2WTJ092WfSztxUoVA1HZ0FEZ35Ft4veh6M6KpfPnTvXZVOmTHHZY4895rJo1Pvtt9/usnJneXzyk590WfReOnv2bJf927/9m8ui9+sf/ehHLiv3M/XWW2+F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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgQAAAILCAYAAACXVIRDAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAgAElEQVR4nO3deZRV5Znv8ee1mMcqitECCgFRKSaVpQJBiUgISCOo9zrg0N1ZKzdxuCZtIrejtMZlJ4J2SEIbbBNXomArRhSCiImywqh2IgqCEkWhinkopqqCmoB9/9CsNj6/3e6ihnNO1fezlmt1/7LPOS9V+2wet89+3hBFkQEAgKbtjFQvAAAApB4FAQAAoCAAAAAUBAAAwCgIAACAURAAAACjIAAAAEZBUCdCCJ1CCC+FEI6FEIpCCDemek1AEiGE+SGEX38huyyEcDCE0CNV6wJqIoRQ9oV/ToYQ5qR6XZmmWaoX0Eg8ZmZVZtbNzIaZ2dIQwoYoit5P7bKAL3WXmb0fQhgXRdFrIYRWZvZLM7s7iqI9KV4bkEgURe3++n+HENqZ2V4z+23qVpSZApMKayeE0NbMDpvZoCiKPvosm2dmu6Io+n8pXRyQQAjhf5nZLDMbZGb3mdmwKIompHZVwOkJIdxqZvebWb+Iv+BqhDsEtTfAzE78tRj4zAYzuyxF6wFqJIqi34YQrjezZ81slH16lwvIVLea2dMUAzVHQVB77cys5AvZUTNrn4K1AKfrNjP7xMzujaJoR6oXA5yOEEK+ffovY99I9VoyEU2FtVdmZh2+kHUws9IUrAU4LVEU7TOzYjOj7wWZ7GYzWxNF0bZULyQTURDU3kdm1iyEcPbnsqHGhRUAGtotZvZUqheRqSgIaimKomNm9qKZPRhCaBtCGGVmV5nZvNSuDACajhDCSDPLM54uOG0UBHXjNjNrbWb77dPGrG/zyCEANKhbzezFKIr4z7WniccOAQAAdwgAAAAFAQAAMAoCAABgFAQAAMAoCAAAgNVwdHEIgUcSUBvFURR1SeUCOIdRS5zDyHSx5zB3CNCQilK9AKCWOIeR6WLPYQoCAABAQQAAACgIAACA1bCpEED9CyG4jBHjQGbKpO8zdwgAAAAFAQAAoCAAAABGQQAAAIymwnrXqlUrl3Xv3t1lzZrpX8WJEydctmfPHpdVVVW5LF0bV/DfWrZs6bJLLrnEZdu2bXPZ9u3b62VNAP7WGWf4f3fOyspy2cCBA132j//4jy5btGiRy1auXOmyU6dOJV1ineAOAQAAoCAAAAAUBAAAwCgIAACA0VRYp5o3b+6y/v37u2zcuHEua9eunXzPsrIyly1evNhl+/btc1l5ebnLGrpJBf+zc845x2U//vGPXfbqq6+6bNasWfI9Kyoqar+wOqQaa1UzZUlJictojM1MqgmvJhP71OtrQ31227ZtXaau4WZmX/nKV1w2ZMgQl02dOtVlAwYMcFlxcbHLVq9e7TKaCgEAQIOjIAAAABQEAACAggAAABgFAQAAMJ4yOG1du3Z1mXqiYObMmS674IILXBY3uliNJB4zZozLPvroI5etWrXKZRs3bnRZUVGRy+jurnvqdzx27FiXDR482GUtWrRw2fz58+XnbN269TRWV3udOnWS+Te/+U2X9ejRw2WzZ892WWFhYa3XhbrTpUsXl+Xk5Ljsn//5n11WUFDgsp07d8rPOe+881xW108eqCe74p4yUOd2bdZT13+WupKeqwIAAA2KggAAAFAQAAAACgIAAGA0FTpqxKVqIPzWt77lsiuuuMJlF110kctUg1hcE59qcpkwYYLLvv71r7vsqquuctnatWtdNn36dJft379frgf1TzUc9erVy2VDhw6Vr1eNeA0xArVz584yv+WWW1zWs2dPl6lmyH//93932cmTJ09jdagp1Uj32GOPuUyN8M3Pz3eZGletGqzN0rfp7vPU3xWKuran6wj59P+pAwCAekdBAAAAKAgAAAAFAQAAsCbcVJiVlSVz1fgyYsQIl6n9sc8++2yXqabAmjSZqEmFlZWVLmvdurXL1DS4YcOGuax79+4uo6mw7p04ccJly5cvd9mtt97qMjW5beTIkfJz/vCHP7js2LFjSZaYmPr+qOYyM7Pc3FyXlZeXu2z79u0uY2Jm6qimQtWoHDfdL4m45kF1PVTXwoqKCpepa/ihQ4dcppq7jxw5Itej/ox5eXmJjlPfvcWLF7tMXR8aGncIAAAABQEAAKAgAAAARkEAAACsETYVJm3+GD58uHz9oEGDXHbTTTe5rE+fPi5TDTKqKUpNktu0aZNcz5o1a1ymmk+++tWvukxNNBwwYIDLxo0b57IPPvhAricdGl8aky1btrjstddec5lqKrz66qvl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ms3MWrdu7bIDBw64TI1snjVrlsv+9Kc/JXo/pJfevXu7TJ1bZvopHfWkwM6dO13WUE/fAP8TNWpYXTfVE1vqev/000+7TD1REEVR0iU2StwhAAAAFAQAAICCAAAAGAUBAACwemoqVI1wffr0kceec845LlONTWrv9nXr1rls3759X75Aix+lrBoi8/LyXKaaIfv27esy1filGizViGMz/bN48803XbZ+/fpEx+3du9dlTb2RJt2oc+Gmm25y2eWXXy5fr36fr7/+ustUA+6JEyeSLBGoE3Fj6tVY4euvvz7R62fPnu2yRx991GVc9zzuEAAAAAoCAABAQQAAAIyCAAAAWD01FapGODVp0ExPAVSNfapR8fDhw4mOU/toZ2dny/UUFBS47I477nCZmhzXrl07l6k/i/pZqGY/M7OVK1e67Ec/+pHLdu/e7bLaTmhEaqim08mTJ7usTZs28vVq8uT8+fNdVlRUdBqrA+qOaio3M/ve977nMtVAWF1d7TLVgM4EzmS4QwAAACgIAAAABQEAADAKAgAAYPXUVFhVVeWyXbt2yWPfe+89l6mphqox8OGHH3aZajLp1auXy+ImZKnGwNzcXJepSYdq22bV4PXEE0+47I9//KNcz/vvv++ygwcPuoypW5npjDN8Ta6mYKpz+NSpU/I9V69enShT5ytQX9Q194c//KE8dtCgQS5T5/vLL7/ssrlz57qMCZzJcIcAAABQEAAAAAoCAABgFAQAAMDqqalQNbhVVFTIY9V2xer1auLfsGHDEr22bdu2Lovb/lg1eSX985SWlrpszZo1LlMNXps3b5brOXToUKL1IDOp8001VKnJmqq51MzsueeeS3wsUB+ysrJcNmnSpERZ3Os3bNjgst/85jcuo4Hw9HGHAAAAUBAAAAAKAgAAYBQEAADA6qmpUIlr4lPNdGpb1u7du7tMNQsqanqhamY001MWN23a5LI333zTZVu3bnXZ2rVrXVZcXOyyuKlzaHpUo6E6P1TDqhlTCZF6arrr9ddf7zLVPGimGwO/+93vukxdh3H6uEMAAAAoCAAAAAUBAAAwCgIAAGANOKmwpKREHvvkk0+6rLCw0GVq++MOHTokWo/67JUrV8pjy8rKXHb48OFEmWr8olkQNaXO16NHj7osrqFKTbcEGtINN9zgsvHjx7ssrtl16dKlLlPne2Vl5Wms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\n", "text/plain": [ "
" ] }, - "metadata": { - "needs_background": "light" - }, + "metadata": {}, "output_type": "display_data" } ], "source": [ - "fig = plt.figure(figsize=(9, 9))\n", - "for i in range(20, 29):\n", - " x, y = dataset[i]\n", - " ax = fig.add_subplot(3, 3, i % 9 + 1)\n", - " ax.imshow(x.reshape(28, 28).T, cmap='gray')\n", - " ax.set_title(emnist_essentials[\"mapping\"][int(y)][-1])" + "display_dl_images(dl, 9, classes)" ] }, { "cell_type": "code", - "execution_count": 127, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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Stkbo5555hmXrV27NvNxUFvDhg1z2SWXXOKyk08+2WXdunXLfJyotvM03kb1/5Of/MRlV1xxRXj/O++802VlmFxYdtHrTPR6JMUNk1EdRV+3J5980mXRa1TepsxoPW+//bbL7ruveb3Z0ffZTTfd5LJVq1a5bPbs2S6LPrdSPDm3FjhDAQAAcmNDAQAAcmNDAQAAcmNDAQAAcmNDAQAAcivNuzwGDRoU5tHo7WiEdfQujwMOOMBle+21l8uijto1a9aE69ljjz1cdtxxx7ls6NChLuvZs6fLou78qFt5xYoV4Xq22WabMN/U1KlTXRaNba327hbUVjSufezYsS476aSTXJb1a75u3bowf/nll1328MMPuyz6nurRo4fLojVG72j6zne+E65nxowZLps2bZrLqM3a6t27t8uid9B1xIIFC1z2+OOPd/rxqo2QjsZQR++Ei+5ftHcQRe/e+Pd//3eXRe+MafTIcM5QAACA3NhQAACA3NhQAACA3NhQAACA3ErTlBk1qUlxI2M0pjsaI/v973/fZdF412gcatT0I8VNaR0Ze7ypqEEoapqbOHFieP+vfvWrLhswYIDLouYdmtyKpVevXi7beuutO/14s2bNCvOzzz7bZc8995zLou+LaPT8888/77JLL73UZbvuumu4nvPOO89l3/3ud122cOHC8P6oHTPLnEevH0uXLs2URaJ6+5d/+Zfwtl/5yldcNnz48Ez3nzdvXqb1NFOeUfj1xBkKAACQGxsKAACQGxsKAACQGxsKAACQW7tNmWY2VNKNkgZJSpImpJR+bmb9JN0uabik2ZJOSSktq9dCqzWhRBMiowmAUVNnNAkur6zNSVGz5bvvvuuyBx54wGXRlLRqDW1RQ2jUUFpt0mYrKEoN5xV9jaI6imo9qsFFixaFx1m8eLHLsjaBRc29r7zyisuiKazDhg0LH/OYY45xWdSEfM8992RaT1nVs46jZvRo6m90u2qimrn//vtdNnfu3MyPualqzej33Xefy6LX5mrN9eicLNWxXtL5KaXdJO0n6Wwz203SBZIeTSmNlPRo5WOgiKhhtALqGIXW7oYipTQvpTSl8ueVkl6SNETSiZJuqNzsBkl+YD9QANQwWgF1jKLr0BwKMxsuaS9Jz0galFL66A2789V2Gi66z3hJ4zu/RKB2qGG0go7WMTWMRsj8AzEz6yHp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MxQAACA3NhQAACA3NhQAACA3NhQAACA3mjIhKft7nc3MZX369HFZr169wuMsXbrUZcuWLcuyRLS4qN4kqX///i4744wzXDZ27FiXTZ/u5ztdffXVLps9e7bLouZNoDN69OjhsokTJ7ps1KhRLovqP7Ljjju6bMaM8Ar2+tnPfpbpMTuKMxQAACA3NhQAACA3NhQAACA3NhQAACA3NhQAACA33uVRY/369cuUNVPUcTxixAiX7bTTTi6L3r2x++67u2zQoEHhsb///e+77LHHHnMZo5BbR/TOoAEDBrjswAMPDO9/6KGHumzcuHGZHhsLzMkAACAASURBVDMaURwd59e//rXLfv7zn4fref/998MciF4zJem0005z2f777++yaBz33LlzXRa98yOqyzfffDNcT71whgIAAOTGhgIAAOTGhgIAAOSWq4fCzGZLWilpg6T1KaV9arEooJGoY5QdNYwiqEVT5uEppcU1eJxSGThwYJh/7Wtfc9mXvvQll0XNN40SHTtq1Iyyrl27ZjrGq6++2vGFNddmWceNsN1227nsRz/6kcu++MUvhvePmpqzfv9svfXWLtt5551dFo3yfvHFF8PHvP/++1324YcfZlpPnVHDDbTnnnu67MEHHwxvG/17sXDhQpf9x3/8h8tuvvlml1177bUuGzZsmMteeOGFcD31wo88AABAbnk3FEnS783sOTMbH93AzMab2WQzm5zzWEC9fGwdU8MoAWoYTZf3vPtBKaW5ZjZQ0sNm9nJKadLGN0gpTZA0QZLMjOECKKKPrWNqGCVADaPpcp2hSCnNrfy+UNJdkvatxaKARqKOUXbUMIqg02cozKy7pC1SSisrf/68pEtrtrIC6dKli8uOO+648LZnnnmmy4YMGVLzNeURNZBFWTStctmyZS6LprFdffXV4bH//Oc/ZzpOo2xOddwsUVPlIYcc4rJqjc5ZrVmzxmXz5893WTTtdejQoS6L1ihJjzzyiMtWr16dZYl1QQ3XX/RvwHnnneeyahOCP/jgA5ddcMEFLosafj/xiU+4LJrIuWHDhvDYjZTnRx6DJN1VGau7paRbU0pxiytQXNQxyo4aRiF0ekORUnpdkn/fDFAi1DHKjhpGUfC2UQAAkBsbCgAAkBuXL88gairr06dPeNtoumTUkDNv3jyXrVu3zmXRpZ+jBqFqokadadOmuWz6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O4a3jb5/xo0b57Ljjz/eZb169XJZ9C6PHj16uKzauzweeughl5199tku62gNc4YCAADkxoYCAADkxoYCAADklquHwsxmS1opaYOk9SmlfWqxKKCRqGOUHTWMIqhFU+bhKaXFNXicUqnWFBY16hx88MEuO+uss1wWNVZGTZXR6O1oRHc1AwYMcNmIESNcdvjhh7vstddec9nSpUtd9j//8z/hsdetW5dlic2w2dVxVKtSXF/HHHOMy8477zyXRY2a0TjuyIYNG8J85cqVLlu7dq3LovHZUfNa1BAdfT8PGzYsXM+YMWNc9sADD7isCU2Zm10N10PUHNy3b1+XnXbaaS6LGi2luLEyem3P+r0SieqtWpNo9HxqgR95AACA3PJuKJKk35vZc2Y2PrqBmY03s8lmNjnnsYB6+dg6poZRAtQwmi7vjzwOSinNNbOBkh42s5dTSn8xvCClNEHSBEkyM/9mb6D5PraOqWGUADWMpst1hiKlNLfy+0JJd0natxaLAhqJOkbZUcMogk6foTCz7pK2SCmtrPz585IurdnKCiS6Hn3UuCbFTWBRU+ZBBx3kst69e7ssmrBW6ymB1R5zm222cdmQIUNcduSRR7rspZdeCo+zfPlylzVzouDmUsdRw280wVKS9t9/f5dF9Ro190bfK2vWrHHZO++847IpU6aE63niiSdctmzZMpdNnuzP5h966KEu+9GPfuSyqFGzLDaXGo4az6s1zu65554uGz16tMui6cTRtMqoiTGq/2qi17homvDrr7/usrvvvttlUaPytGnTXBZNQJakRYsWZVpjR+X5kccgSXdVXkC2lHRrSunB3CsCGos6RtlRwyiETm8oUkqvS/LbQKBEqGOUHTWMouBtowAAIDc2FAAAIDcuX76JqKksami76KKLwvvvscceLhs+fLjL8jSBRc08UZOOJL333nsu23777V0WTYeLmqCiZtQvfelLLrv11lvD9USXTucyz7UV1duPf/xjlx111FHh/aNm3Khpd/369S6bM2eOy26++WaXTZw40WVvvfVWuJ6otqPLjUeTP6OJmpHo8aqtZ+rUqS6jhmsreu259tprXfblL385vH+eZvaorqMJv7NmzXLZvffeGz7mU0895bLnn3/eZdHlxlevXh0+ZhFxhgIAAOTGhgIAAOTGhgIAAOTGhgIAAOS2WTdlbrvtti7bYYcdXPaDH/zAZSeffHL4mNHlZ6NGz0jU2LVkyRKXRZdKfvzxx8PHnDdvnsu++93vuiy6zG00HW727NkuixrxosYmKW5+Q+cNHDjQZWeccYbLoul/1S55H11GPJrgd9ddd7ls0qRJLnv00Udd9v7774fHzipqlI4uJx1l3bt3d9lrr73msl//+tfhsaPnQ1NmbUUTML/4xS+6LGog7oiowf0Xv/iFy95++22X3X///S6r1sgbHacVa4YzFAAAIDc2FAAAIDc2FAAAIDc2FAAAILeWbMqMmiC32morl40cOdJlY8aMcdl+++3nsqj5stqxI9EEv2iqZTSV78EH/YUEX3nllfA4eZqW3n33XZf9+c9/dlk0BS6aiCnRlJlH1EQZTSk988wzM903ahSTpIceeshlUYPiI4884rJoql/e5rNoOutVV13lssMPP9xl0aXTb7/9dpddQ5tC1QAAE5hJREFUffXVLosakKX8DaX4S9EEywMOOMBl0eXCq73eRq8zS5cuddk999zjsgsvvNBl0es1r2UeZygAAEBubCgAAEBubCgAAEBubCgAAEBu7TZlmtl1ko6XtDClNKqS9ZN0u6ThkmZLOiWltKx+y+yYaMra/vvv77LvfOc7Lhs8eLDLOtIMFImad6ZMmeKyyZMnuyxqcvvsZz/rsi984QvhsYcOHeqyfffdN7ztpu644w6XRU1M0eTO6HK/zVTGOt5UVHNRw2KURRYvXhzm0eXGn3nmGZdlvTR4Xj179nTZoEGDXPaf//mfLosahp988kmXLVq0yGVFa7prhRqOdO3aNVOW9+sRTbGcOXOmy77+9a+77A9/+IPLXnjhBZcVrWYaLcsZiuslHb1JdoGkR1NKIyU9WvkYKLLrRR2j3K4XNYwCa3dDkVKaJGnT99ucKOmGyp9vkHRSjdcF1BR1jLKjhlF0nZ1DMSil9NFVp+ZL8ucfK8xsvKTxnTwOUE+Z6pgaRoFRwyiM3IOtUkrJzKr+4CilNEHSBEn6uNsBzfRxdUwNowyoYTRbZ9/lscDMBktS5feFtVsS0DDUMcqOGkZhdPYMxURJp0u6rPK7b/1vkGgE9t/8zd+4bOzYsS4bPXq0y7K+e6Mj7/KI7Lrrri4bMmSIy7bddluXRZ3E77zzTnic6DGjkdqvvfaay372s5+5LBrxXbR3dHRAYeq4s6IR59FI7S239N/qAwcODB/z8ssvd9nzzz/vsqjLfdq0aS6LxrXPmzfPZdVGgUe1/eUvf9llCxYsyPSYeUeBF0yparh///4uO/fcc10WjY+PRnR35F0Ve+65p8uy/hsQXRbhK1/5isuid8FtTto9Q2Fmt0l6WtKuZva2mZ2htuL9nJm9IumoysdAYVHHKDtqGEXX7hmKlNKpVf7qyBqvBagb6hhlRw2j6JiUCQAAcmNDAQAAcsv9ttFm69Wrl8v22GMPl0UjtRvVgBnp3bu3y6LnEh07GhO8bFk8bTd6zKlTp7rsueeec9ncuXNdVq1xDvW3fv16l911110uixrNTjnlFJdtvfXW4XFGjBjhsmic/QknnOCy5cuXuywaefzHP/7RZZMmTQrX8+ijj7ps9uzZ4W1RHFFD+VlnneWyb33rWy7bZpttMh2jWkN4VIdRY2X070L0fdG9e3eXRY3B9957b7ieFmsEroozFAAAIDc2FAAAIDc2FAAAIDc2FAAAIDdr5PXb88yQj6akSdKJJ57osmuvvdZl2223ncu6dOnS2eU0TNSIFzVGrly5Mrz/gw8+6LJ//dd/dVk0jfD999/PssRGei6ltE8zF1C06yBETbsDBgxw2Wmnneay/fffP3zMUaNGuaxv376ZsmgiZySq6zlz5oS3/fWvf+2yaJpn9JgFtNnU8De/+U2XXXrppS6LGh43bNjgsv/+7/92WTRRU5KWLFnisuj17KijjnLZT3/6U5cNHz7cZVFzfPS9U+22JVa1hjlDAQAAcmNDAQAAcmNDAQAAcmNDAQAAcivNpMxqTZlZG8iiBsxoylrU3Lh27VqXRZdNl6pPH9xUdPnmaLrbY4895rLo8uOrVq0KjxNNUnzzzTdd1sjmXNRO9HVbuHChy3784x+7rNr3VPS90qdPH5cNHTrUZYcffrjLoubPgw46yGXRhE5J+v73v++yaPJg1Ey3Zs2a8DFRfz169HBZVHPRBMtHHnnEZRdffLHLXn755U6urs19993nskMOOcRl55xzjsui74loArLUck2ZVXGGAgAA5MaGAgAA5MaGAgAA5NbuhsLMrjOzhWb24kbZJWY218ymVn4dW99lAvlQxyg7ahhFl6Up83pJV0u6cZP8pymlq2q+og6KmnyyXm48ujz3/fff77L/+q//clk0jbBaHjWQPf744y6LmjKj5s1ql+yNlGR6YCNcrwLXcTNUu6RylEdNZVE2bdo0l910000uO+aYY1wWNV9KcbPmySef7LLbbrvNZS12mfPrVaIavuaaa1wWfY2i16jodS+aEJxXNJEz66XGo39nyjB9uZ7aPUORUpokaWkD1gLUDXWMsqOGUXR5eii+YWbTKqfh/Ps0gXKgjlF21DAKobMbimsl7SxpjKR5kvyb3CvMbLyZTTazyZ08FlAvmeqYGkaBUcMojE5tKFJKC1JKG1JKH0r6paR9P+a2E1JK+zT7CnvAprLWMTWMoqKGUSSdmpRpZoNTSh91zYyV9OLH3b6oomagZcuWuWzyZL+pr3aZ5qyTMhcsWOCyqNmSpsr6aZU6LpKoXqPJnb/97W9dNnr06PAxoymFvXr1clnWS6e3kiLX8NKlvt0jypoper3eZZddXBY1/0dTaqPpsZI0a9asTPcvu3a/A83sNkmHSepvZm9L+oGkw8xsjKQkabaks+q4RiA36hhlRw2j6NrdUKSUTg3iX9VhLUDdUMcoO2oYRcekTAAAkBsbCgAAkFvpu5iiqWZZm12iJq7o8rPR9LP58+eHj9mKjTZAra1du9Zlq1atasJKUE3Xrl1dtscee4S33XvvvV02ceJEl0VNmc1sPO/Xr5/LDjzwQJdFTZlPP/20y5566qnwOJvLvwucoQAAALmxoQAAALmxoQAAALmxoQAAALmxoQAAALmV5l0e1a5R/+KLftJsND57u+22c9mQIUNcduqpfnZMNOb3Zz/7WbieefPmuWzRokUu21y6fvH/69atW+Z85cqVLtuwYUPN19Qsffv6i2KOGjUqvG3UYV/t9QC18+lPf9plv/nNb8LbDhw40GVHH320y5588kmXXXPNNS6L3gWUVzRme+edd3bZtttu67Lo9frWW2912fvvv9/J1bUGzlAAAIDc2FAAAIDc2FAAAIDc2FAAAIDcSt+U+dprr7ksaozs3r17pixqFjv44INdNnv27HA9U6dOddkjjzzisg8++CC8/6ai501DWvH179/fZX//938f3nbkyJEui8YWP/zwwy4rQxNYNLo++p6KRh5LcVPm9OnTXfbuu+92YnWQ4s/x9773PZd98pOfzPyYJ598ssuOOuool7300ksu+8Mf/uCy6HWvWqNy1Oh84YUXuuzcc891WdS8uXDhQpc9/vjj4bE3Z5yhAAAAubGhAAAAubGhAAAAubW7oTCzoWb2RzObYWbTzezcSt7PzB42s1cqv/vmA6AAqGG0AuoYRZelKXO9pPNTSlPMrKek58zsYUlflfRoSukyM7tA0gWSvlu/pcZmzpzpsiuuuMJln//85112zDHHuKx3794uGzFihMv+6Z/+KVzPggULXHbPPfe4bMWKFS6Lmo6iSaBRQ1q1yXLRetatW+eyaBJcC01mrGsNRw1tBx10kMvOOeec8P7RlMFDDz3UZTfffLPL7r33XpctWbLEZW+//bbL1q9fH64nj6gZ7lOf+pTLTjvtNJdF02yluDaffvppl0UTcltM3erYzFw2aNCgXPePvm7R1OFvf/vbLtt///1dFtXrE088Ea4n+v4566yzXNajRw+XRa+ZF198scuif3s2d+2eoUgpzUspTan8eaWklyQNkXSipBsqN7tB0kn1WiSQBzWMVkAdo+g69LZRMxsuaS9Jz0galFL66P2Z8yWF21kzGy9pfOeXCNQONYxW0NE6pobRCJmbMs2sh6TfSTovpfQX5+tT27mt8GpXKaUJKaV9Ukr75FopkBM1jFbQmTqmhtEImTYUZtZVbQV8S0rpzkq8wMwGV/5+sCQ/+QMoCGoYrYA6RpFZe5fRtrZumxskLU0pnbdRfqWkJRs1AvVLKX2nncdqyDW7o0lnUbNl1JR52GGHuSya6jd48ODw2Ftu6X+KFDUsRaKvxfLly10WNZ+tWrUqfMzHHnvMZdFEweg4t99+u8uWLl3qsno091XxXGf+h1XvGo6aMr/4xS+67Nprrw0fM2vz25o1a1w2f/58l0Vfo9tuu81lUW1I2SdORt9Txx9/vMvGjh3rsl133dVl0fetFE8pPOCAA1z2+uuvh/cvmE7VsFS7Oo5qOJpm+n//7/912XHHHRc+ZteuXaPjuKy9f286qiON41Hj+qxZs1z21a9+1WUzZsxwWdTcvpmoWsNZeigOlHSapBfM7KO50hdKukzSHWZ2hqQ3JZ1Si5UCdUANoxVQxyi0djcUKaU/Sar2X+wja7scoPaoYbQC6hhFx6RMAACQGxsKAACQW2kuX94R0aXBo+mB0ZS1qKFt8eLFLjv88MPDY/fp08dlUQNn1IAWNTFF0wOjY1RrjOzXr5/LVq9e7bLoku/PPvtspjVGTXO1br4qsmjC6VNPPeWyaKqlFDdwRl+3aArl8OHDM2Wf/vSnXRZNBJSyN5tFjXjbb7+9y6J1R/UR1ZEUX8r9zTffzLJEZBQ1N5555pkui74WUvwaN2zYMJdlbVCPRN9nb7zxRnjbf/3Xf3VZ1IQcNTVHzc/IhjMUAAAgNzYUAAAgNzYUAAAgNzYUAAAgt3YnZdb0YA2alJlHNPUwaqCsNikzapiMGjijy/NGTUzR5X6jZrju3buH64mmGb711lsumzZtmstee+01l0VNq9EEyKzTFjuo01MGayVrDUfNZwMGDAhve+CBB7osmgQZTZwcOnRopmNHE1wbJWqSfvnll132s5/9LLz/Aw884LJqDZwlUOoajl6jJKl///4u+8UvfpHpdtH3xaJFi1w2ZcoUl91www0uk6SHH374/2vvDl6sKuMwjj8P4YAwLXSCQSbNCDe6GSEkqJUrc6NtIhfhIqhFgUIbqU1/QLmLoFB0IbVRyG2J0EYkEzV1KKdISiY1QxxFKevX4p7g6nmHuXPPveee98z3Axfv/c1cz/ue+zD8uPc97y3VWGw5MAtmmHcoAABAZTQUAACgMhoKAABQGQ0FAACojEWZNUgtiFu1alWpllpYmXpuaqHlunXrksfetGlTqXb+/PlSbWZmplRLLTBNjSe1WCr1VcEDkM2CtqVILQReuXJlqbZ169ZSbXp6ulRL5SP1tdNjY2PJ8aTqqd0zU4uD7927V6qdOnWqVEstwEwt1JTSizoz1soMp6T+VqQyMzk5WaqldnFN5SC1eyaGjkWZAABgeGgoAABAZTQUAACgMhoKAABQ2aINhe21tk/avmz7ku09Rf0D29dsnytu24c/XGDpyDByR4aRg0Wv8rC9RtKaiDhr+0lJ30naKelVSXcj4sOeD7ZMr/JISa3sT9VSUiulx8fHk7+bWvF/+/btUu3u3bul2kJXATxufn6+VBvS1UN9rZBvS4Z7zUwqH1NTU6XaQplJbYV869atUm1iYqJUu3r1aqmW2q499f/VecXZCC3rDKMVFszwohv8R8ScpLni/rztGUnlv05AQ5Fh5I4MIwdLWkNhe72kzZJOF6V3bF+wfdB2eWOFznPetH3G9plKIwUGgAwjd2QYTdVzQ2F7XNJRSXsj4o6kTyQ9J2lanc75o9TzIuLTiHh+1Ju5AGQYuSPDaLKeGgrbK9QJ8ZGIOCZJEXE9Iv6JiH8lfSZpy/CGCVRDhpE7MoymW3QNhW1LOiBpJiL2d9XXFJ/rSdIrki4OZ4jtlNoyttdtZB8+fFiq3b9/P/m7N2/eXNrAujx48KDv5zZJWzLca2ZS+Zidne35OJ3T9ajUgslefw/VtSXDaLdFGwpJL0p6XdL3ts8Vtfck7bI9LSkk/SLpraGMEKiODCN3ZBiNx5eDISfL5ouVRol3KIaKDCN3fDkYAAAYHhoKAABQWS9rKAAsI71+bMHHGwC68Q4FAACojIYCAABURkMBAAAqo6EAAACV1b0o8w9J/3+/8VPF4zZgLvV4ZtQDEBnORVPnQ4aHp01zkZo7nwUzXOvGVo8c2D4z6g1eBoW5LE9tOldtmovUvvkMS5vOU5vmIuU5Hz7yAAAAldFQAACAykbZUHw6wmMPGnNZntp0rto0F6l98xmWNp2nNs1FynA+I1tDAQAA2oOPPAAAQGW1NxS2t9n+wfas7X11H78q2wdt37B9sau22vZXtq8U/64a5Rh7ZXut7ZO2L9u+ZHtPUc9yPnUhw81BhvuXc47JcDPV2lDYfkLSx5JelrRR0i7bG+scwwAckrTtsdo+SSciYoOkE8XjHDyU9G5EbJT0gqS3i9cj1/kMHRluHDLchxbk+JDIcOPU/Q7FFkmzEfFzRPwl6QtJO2oeQyUR8Y2kPx8r75B0uLh/WNLOWgfVp4iYi4izxf15STOSppTpfGpChhuEDPct6xyT4Waqu6GYkvRr1+PfilruJiNirrj/u6TJUQ6mH7bXS9os6bRaMJ8hIsMNRYaXpI05zv41zz3DLMocsOhcNpPVpTO2xyUdlbQ3Iu50/yzH+aCaHF9zMoxuOb7mbchw3Q3FNUlrux4/XdRyd932Gkkq/r0x4vH0zPYKdUJ8JCKOFeVs51MDMtwwZLgvbcxxtq95WzJcd0PxraQNtp+1PSbpNUnHax7DMByXtLu4v1vSlyMcS89sW9IBSTMRsb/rR1nOpyZkuEHIcN/amOMsX/NWZTgiar1J2i7pR0k/SXq/7uMPYPyfS5qT9Lc6nzu+IWlCnVW4VyR9LWn1qMfZ41xeUudttAuSzhW37bnOp8bzRoYbciPDlc5dtjkmw828sVMmAACojEWZAACgMhoKAABQGQ0FAACojIYCAABURkMBAAAqo6EAAACV0VAAAIDKaCgAAEBl/wHqdr9l+pcc3wAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "fig = plt.figure(figsize=(9, 9))\n", - "for i in range(30, 39):\n", - " x, y = dataset[i]\n", - " ax = fig.add_subplot(3, 3, i % 9 + 1)\n", - " ax.imshow(x.reshape(28, 28).T, cmap='gray')\n", - " ax.set_title(emnist_essentials[\"mapping\"][int(y)][-1])" + "for i, j in enumerate([5, 7, 9]):\n", + " x, y = dataset[j]\n", + " ax = fig.add_subplot(3, 3, i + 1)\n", + " x = x.numpy().reshape(28, 28).swapaxes(0, 1)\n", + " ax.imshow(x, cmap='gray')\n", + " ax.set_xticks([])\n", + " ax.set_yticks([])\n", + " ax.set_title(classes[int(y)])" ] }, { diff --git a/src/notebooks/tqdm.ipynb b/src/notebooks/tqdm.ipynb new file mode 100644 index 0000000..4b55d9b --- /dev/null +++ b/src/notebooks/tqdm.ipynb @@ -0,0 +1,280 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from tqdm.notebook import trange, tqdm\n", + "from time import sleep" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "metrics = {\"loss\": 0.0, \"accuracy\": 0.0}" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e02253811497426483b5492663f276ee", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, description='Epoch', max=10.0, style=ProgressStyle(description_width='…" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, max=10.0), HTML(value='')))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, max=10.0), HTML(value='')))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, max=10.0), HTML(value='')))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, max=10.0), HTML(value='')))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, max=10.0), HTML(value='')))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(FloatProgress(value=0.0, max=10.0), HTML(value='')))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "for j in trange(10, unit=\"epoch\", initial=5,\n", + " bar_format=\"{desc}: {n_fmt}/{total_fmt} {bar} {remaining}{postfix}\",\n", + " desc=\"Epoch\"):\n", + " with tqdm(\n", + " total=10,\n", + " leave=False,\n", + " initial=0,\n", + " unit=\"step\",\n", + " bar_format=\"{n_fmt}/{total_fmt} {bar} {remaining} {rate_inv_fmt}{postfix}\",\n", + " ) as t:\n", + " for i in range(10):\n", + " sleep(0.1)\n", + " metrics[\"loss\"] = 0.9 * i\n", + " metrics[\"accuracy\"] = 100 / (i + 1)\n", + " t.set_postfix(**metrics)\n", + " t.update()\n", + " if j + 5 == 10:\n", + " break\n", + "# for j in tqdm(range(100), desc='2nd loop', leave=False, bar_format=\"{n_fmt}/{total_fmt} {bar} {remaining} {rate_inv_fmt}{postfix}\"):\n", + "# sleep(0.1)\n", + "# t.set_postfix(**metrics)\n", + "# t.update()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "from datetime import datetime" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'0616_231817'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "datetime.now().strftime(\"%m%d_%H%M%S\")" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "from loguru import logger" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "a = 2" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2020-06-16 23:44:24.228 | DEBUG | __main__::1 - hej 2\n" + ] + } + ], + "source": [ + "logger.debug(f\"hej {a}\", format=\"{time:YYYY-MM-DD at HH:mm:ss} : {level} : {message}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "PosixPath('agaga/afaf')" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Path(\"agaga\") / \"afaf\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/src/text_recognizer/character_predictor.py b/src/text_recognizer/character_predictor.py new file mode 100644 index 0000000..69ef896 --- /dev/null +++ b/src/text_recognizer/character_predictor.py @@ -0,0 +1,26 @@ +"""CharacterPredictor class.""" + +from typing import Tuple, Union + +import numpy as np + +from text_recognizer.models import CharacterModel +from text_recognizer.util import read_image + + +class CharacterPredictor: + """Recognizes the character in handwritten character images.""" + + def __init__(self) -> None: + """Intializes the CharacterModel and load the pretrained weights.""" + self.model = CharacterModel() + self.model.load_weights() + self.model.eval() + + def predict(self, image_or_filename: Union[np.ndarray, str]) -> Tuple[str, float]: + """Predict on a single images contianing a handwritten character.""" + if isinstance(image_or_filename, str): + image = read_image(image_or_filename, grayscale=True) + else: + image = image_or_filename + return self.model.predict_on_image(image) diff --git a/src/text_recognizer/datasets/__init__.py b/src/text_recognizer/datasets/__init__.py index cbaf1d9..929cfb9 100644 --- a/src/text_recognizer/datasets/__init__.py +++ b/src/text_recognizer/datasets/__init__.py @@ -1,2 +1,2 @@ """Dataset modules.""" -# from .emnist_dataset import fetch_dataloader +from .data_loader import fetch_data_loader diff --git a/src/text_recognizer/datasets/data_loader.py b/src/text_recognizer/datasets/data_loader.py new file mode 100644 index 0000000..fd55934 --- /dev/null +++ b/src/text_recognizer/datasets/data_loader.py @@ -0,0 +1,15 @@ +"""Data loader collection.""" + +from typing import Dict + +from torch.utils.data import DataLoader + +from text_recognizer.datasets.emnist_dataset import fetch_emnist_data_loader + + +def fetch_data_loader(data_loader_args: Dict) -> DataLoader: + """Fetches the specified PyTorch data loader.""" + if data_loader_args.pop("name").lower() == "emnist": + return fetch_emnist_data_loader(data_loader_args) + else: + raise NotImplementedError diff --git a/src/text_recognizer/datasets/emnist_dataset.py b/src/text_recognizer/datasets/emnist_dataset.py index 204faeb..f9c8ffa 100644 --- a/src/text_recognizer/datasets/emnist_dataset.py +++ b/src/text_recognizer/datasets/emnist_dataset.py @@ -1,72 +1,155 @@ """Fetches a PyTorch DataLoader with the EMNIST dataset.""" + +import json from pathlib import Path -from typing import Callable +from typing import Callable, Dict, List, Optional -import click from loguru import logger +import numpy as np +from PIL import Image from torch.utils.data import DataLoader from torchvision.datasets import EMNIST +from torchvision.transforms import Compose, ToTensor + + +DATA_DIRNAME = Path(__file__).resolve().parents[3] / "data" +ESSENTIALS_FILENAME = Path(__file__).resolve().parents[0] / "emnist_essentials.json" + + +class Transpose: + """Transposes the EMNIST image to the correct orientation.""" + + def __call__(self, image: Image) -> np.ndarray: + """Swaps axis.""" + return np.array(image).swapaxes(0, 1) + + +def save_emnist_essentials(emnsit_dataset: EMNIST) -> None: + """Extract and saves EMNIST essentials.""" + labels = emnsit_dataset.classes + labels.sort() + mapping = [(i, str(label)) for i, label in enumerate(labels)] + essentials = { + "mapping": mapping, + "input_shape": tuple(emnsit_dataset[0][0].shape[:]), + } + logger.info("Saving emnist essentials...") + with open(ESSENTIALS_FILENAME, "w") as f: + json.dump(essentials, f) -@click.command() -@click.option("--split", "-s", default="byclass") -def download_emnist(split: str) -> None: +def download_emnist() -> None: """Download the EMNIST dataset via the PyTorch class.""" - data_dir = Path(__file__).resolve().parents[3] / "data" - logger.debug(f"Data directory is: {data_dir}") - EMNIST(root=data_dir, split=split, download=True) + logger.info(f"Data directory is: {DATA_DIRNAME}") + dataset = EMNIST(root=DATA_DIRNAME, split="byclass", download=True) + save_emnist_essentials(dataset) -def fetch_dataloader( - root: str, +def load_emnist_mapping() -> Dict: + """Load the EMNIST mapping.""" + with open(str(ESSENTIALS_FILENAME)) as f: + essentials = json.load(f) + return dict(essentials["mapping"]) + + +def _sample_to_balance(dataset: EMNIST, seed: int = 4711) -> None: + """Because the dataset is not balanced, we take at most the mean number of instances per class.""" + np.random.seed(seed) + x = dataset.data + y = dataset.targets + num_to_sample = int(np.bincount(y.flatten()).mean()) + all_sampled_inds = [] + for label in np.unique(y.flatten()): + inds = np.where(y == label)[0] + sampled_inds = np.unique(np.random.choice(inds, num_to_sample)) + all_sampled_inds.append(sampled_inds) + ind = np.concatenate(all_sampled_inds) + x_sampled = x[ind] + y_sampled = y[ind] + dataset.data = x_sampled + dataset.targets = y_sampled + + +def fetch_emnist_dataset( split: str, train: bool, - download: bool, - transform: Callable = None, - target_transform: Callable = None, + sample_to_balance: bool = False, + transform: Optional[Callable] = None, + target_transform: Optional[Callable] = None, +) -> EMNIST: + """Fetch the EMNIST dataset.""" + if transform is None: + transform = Compose([Transpose(), ToTensor()]) + + dataset = EMNIST( + root=DATA_DIRNAME, + split="byclass", + train=train, + download=False, + transform=transform, + target_transform=target_transform, + ) + + if sample_to_balance and split == "byclass": + _sample_to_balance(dataset) + + return dataset + + +def fetch_emnist_data_loader( + splits: List[str], + sample_to_balance: bool = False, + transform: Optional[Callable] = None, + target_transform: Optional[Callable] = None, batch_size: int = 128, shuffle: bool = False, num_workers: int = 0, cuda: bool = True, -) -> DataLoader: - """Down/load the EMNIST dataset and return a PyTorch DataLoader. +) -> Dict[DataLoader]: + """Fetches the EMNIST dataset and return a PyTorch DataLoader. Args: - root (str): Root directory of dataset where EMNIST/processed/training.pt and EMNIST/processed/test.pt - exist. - split (str): The dataset has 6 different splits: byclass, bymerge, balanced, letters, digits and mnist. - This argument specifies which one to use. - train (bool): If True, creates dataset from training.pt, otherwise from test.pt. - download (bool): If true, downloads the dataset from the internet and puts it in root directory. If - dataset is already downloaded, it is not downloaded again. - transform (Callable): A function/transform that takes in an PIL image and returns a transformed version. - E.g, transforms.RandomCrop. - target_transform (Callable): A function/transform that takes in the target and transforms it. - batch_size (int): How many samples per batch to load (the default is 128). - shuffle (bool): Set to True to have the data reshuffled at every epoch (the default is False). - num_workers (int): How many subprocesses to use for data loading. 0 means that the data will be loaded in - the main process (default: 0). - cuda (bool): If True, the data loader will copy Tensors into CUDA pinned memory before returning them. + splits (List[str]): One or both of the dataset splits "train" and "val". + sample_to_balance (bool): If true, resamples the unbalanced if the split "byclass" is selected. + Defaults to False. + transform (Optional[Callable]): A function/transform that takes in an PIL image and returns a + transformed version. E.g, transforms.RandomCrop. Defaults to None. + target_transform (Optional[Callable]): A function/transform that takes in the target and transforms + it. + Defaults to None. + batch_size (int): How many samples per batch to load. Defaults to 128. + shuffle (bool): Set to True to have the data reshuffled at every epoch. Defaults to False. + num_workers (int): How many subprocesses to use for data loading. 0 means that the data will be + loaded in the main process. Defaults to 0. + cuda (bool): If True, the data loader will copy Tensors into CUDA pinned memory before returning + them. Defaults to True. Returns: - DataLoader: A PyTorch DataLoader with emnist characters. + Dict: A dict containing PyTorch DataLoader(s) with emnist characters. """ - dataset = EMNIST( - root=root, - split=split, - train=train, - download=download, - transform=transform, - target_transform=target_transform, - ) + data_loaders = {} - data_loader = DataLoader( - dataset=dataset, - batch_size=batch_size, - shuffle=shuffle, - num_workers=num_workers, - pin_memory=cuda, - ) + for split in ["train", "val"]: + if split in splits: + + if split == "train": + train = True + else: + train = False + + dataset = fetch_emnist_dataset( + split, train, sample_to_balance, transform, target_transform + ) + + data_loader = DataLoader( + dataset=dataset, + batch_size=batch_size, + shuffle=shuffle, + num_workers=num_workers, + pin_memory=cuda, + ) + + data_loaders[split] = data_loader - return data_loader + return data_loaders diff --git a/src/text_recognizer/datasets/emnist_essentials.json b/src/text_recognizer/datasets/emnist_essentials.json new file mode 100644 index 0000000..2a0648a --- /dev/null +++ b/src/text_recognizer/datasets/emnist_essentials.json @@ -0,0 +1 @@ +{"mapping": [[0, "0"], [1, "1"], [2, "2"], [3, "3"], [4, "4"], [5, "5"], [6, "6"], [7, "7"], [8, "8"], [9, "9"], [10, "A"], [11, "B"], [12, "C"], [13, "D"], [14, "E"], [15, "F"], [16, "G"], [17, "H"], [18, "I"], [19, "J"], [20, "K"], [21, "L"], [22, "M"], [23, "N"], [24, "O"], [25, "P"], [26, "Q"], [27, "R"], [28, "S"], [29, "T"], [30, "U"], [31, "V"], [32, "W"], [33, "X"], [34, "Y"], [35, "Z"], [36, "a"], [37, "b"], [38, "c"], [39, "d"], [40, "e"], [41, "f"], [42, "g"], [43, "h"], [44, "i"], [45, "j"], [46, "k"], [47, "l"], [48, "m"], [49, "n"], [50, "o"], [51, "p"], [52, "q"], [53, "r"], [54, "s"], [55, "t"], [56, "u"], [57, "v"], [58, "w"], [59, "x"], [60, "y"], [61, "z"]], "input_shape": [28, 28]} diff --git a/src/text_recognizer/models/__init__.py b/src/text_recognizer/models/__init__.py index aa26de6..d265dcf 100644 --- a/src/text_recognizer/models/__init__.py +++ b/src/text_recognizer/models/__init__.py @@ -1 +1,2 @@ """Model modules.""" +from .character_model import CharacterModel diff --git a/src/text_recognizer/models/base.py b/src/text_recognizer/models/base.py new file mode 100644 index 0000000..736af7b --- /dev/null +++ b/src/text_recognizer/models/base.py @@ -0,0 +1,230 @@ +"""Abstract Model class for PyTorch neural networks.""" + +from abc import ABC, abstractmethod +from pathlib import Path +import shutil +from typing import Callable, Dict, Optional, Tuple + +from loguru import logger +import torch +from torch import nn +from torchsummary import summary + +from text_recognizer.dataset.data_loader import fetch_data_loader + +WEIGHT_DIRNAME = Path(__file__).parents[1].resolve() / "weights" + + +class Model(ABC): + """Abstract Model class with composition of different parts defining a PyTorch neural network.""" + + def __init__( + self, + network_fn: Callable, + network_args: Dict, + data_loader_args: Optional[Dict] = None, + metrics: Optional[Dict] = None, + criterion: Optional[Callable] = None, + criterion_args: Optional[Dict] = None, + optimizer: Optional[Callable] = None, + optimizer_args: Optional[Dict] = None, + lr_scheduler: Optional[Callable] = None, + lr_scheduler_args: Optional[Dict] = None, + device: Optional[str] = None, + ) -> None: + """Base class, to be inherited by predictors for specific type of data. + + Args: + network_fn (Callable): The PyTorch network. + network_args (Dict): Arguments for the network. + data_loader_args (Optional[Dict]): Arguments for the data loader. + metrics (Optional[Dict]): Metrics to evaluate the performance with. Defaults to None. + criterion (Optional[Callable]): The criterion to evaulate the preformance of the network. + Defaults to None. + criterion_args (Optional[Dict]): Dict of arguments for criterion. Defaults to None. + optimizer (Optional[Callable]): The optimizer for updating the weights. Defaults to None. + optimizer_args (Optional[Dict]): Dict of arguments for optimizer. Defaults to None. + lr_scheduler (Optional[Callable]): A PyTorch learning rate scheduler. Defaults to None. + lr_scheduler_args (Optional[Dict]): Dict of arguments for learning rate scheduler. Defaults to + None. + device (Optional[str]): Name of the device to train on. Defaults to None. + + """ + + # Fetch data loaders. + if data_loader_args is not None: + self._data_loaders = fetch_data_loader(**data_loader_args) + dataset_name = self._data_loaders.items()[0].dataset.__name__ + else: + dataset_name = "" + self._data_loaders = None + + self.name = f"{self.__class__.__name__}_{dataset_name}_{network_fn.__name__}" + + # Extract the input shape for the torchsummary. + self._input_shape = network_args.pop("input_shape") + + if metrics is not None: + self._metrics = metrics + + # Set the device. + if self.device is None: + self._device = torch.device( + "cuda:0" if torch.cuda.is_available() else "cpu" + ) + else: + self._device = device + + # Load network. + self._network = network_fn(**network_args) + + # To device. + self._network.to(self._device) + + # Set criterion. + self._criterion = None + if criterion is not None: + self._criterion = criterion(**criterion_args) + + # Set optimizer. + self._optimizer = None + if optimizer is not None: + self._optimizer = optimizer(self._network.parameters(), **optimizer_args) + + # Set learning rate scheduler. + self._lr_scheduler = None + if lr_scheduler is not None: + self._lr_scheduler = lr_scheduler(self._optimizer, **lr_scheduler_args) + + @property + def input_shape(self) -> Tuple[int, ...]: + """The input shape.""" + return self._input_shape + + def eval(self) -> None: + """Sets the network to evaluation mode.""" + self._network.eval() + + def train(self) -> None: + """Sets the network to train mode.""" + self._network.train() + + @property + def device(self) -> str: + """Device where the weights are stored, i.e. cpu or cuda.""" + return self._device + + @property + def metrics(self) -> Optional[Dict]: + """Metrics.""" + return self._metrics + + @property + def criterion(self) -> Optional[Callable]: + """Criterion.""" + return self._criterion + + @property + def optimizer(self) -> Optional[Callable]: + """Optimizer.""" + return self._optimizer + + @property + def lr_scheduler(self) -> Optional[Callable]: + """Learning rate scheduler.""" + return self._lr_scheduler + + @property + def data_loaders(self) -> Optional[Dict]: + """Dataloaders.""" + return self._data_loaders + + @property + def network(self) -> nn.Module: + """Neural network.""" + return self._network + + @property + def weights_filename(self) -> str: + """Filepath to the network weights.""" + WEIGHT_DIRNAME.mkdir(parents=True, exist_ok=True) + return str(WEIGHT_DIRNAME / f"{self.name}_weights.pt") + + def summary(self) -> None: + """Prints a summary of the network architecture.""" + summary(self._network, self._input_shape, device=self.device) + + def _get_state(self) -> Dict: + """Get the state dict of the model.""" + state = {"model_state": self._network.state_dict()} + if self._optimizer is not None: + state["optimizer_state"] = self._optimizer.state_dict() + return state + + def load_checkpoint(self, path: Path) -> int: + """Load a previously saved checkpoint. + + Args: + path (Path): Path to the experiment with the checkpoint. + + Returns: + epoch (int): The last epoch when the checkpoint was created. + + """ + if not path.exists(): + logger.debug("File does not exist {str(path)}") + + checkpoint = torch.load(str(path)) + self._network.load_state_dict(checkpoint["model_state"]) + + if self._optimizer is not None: + self._optimizer.load_state_dict(checkpoint["optimizer_state"]) + + epoch = checkpoint["epoch"] + + return epoch + + def save_checkpoint( + self, path: Path, is_best: bool, epoch: int, val_metric: str + ) -> None: + """Saves a checkpoint of the model. + + Args: + path (Path): Path to the experiment folder. + is_best (bool): If it is the currently best model. + epoch (int): The epoch of the checkpoint. + val_metric (str): Validation metric. + + """ + state = self._get_state_dict() + state["is_best"] = is_best + state["epoch"] = epoch + + path.mkdir(parents=True, exist_ok=True) + + logger.debug("Saving checkpoint...") + filepath = str(path / "last.pt") + torch.save(state, filepath) + + if is_best: + logger.debug( + f"Found a new best {val_metric}. Saving best checkpoint and weights." + ) + self.save_weights() + shutil.copyfile(filepath, str(path / "best.pt")) + + def load_weights(self) -> None: + """Load the network weights.""" + logger.debug("Loading network weights.") + weights = torch.load(self.weights_filename)["model_state"] + self._network.load_state_dict(weights) + + def save_weights(self) -> None: + """Save the network weights.""" + logger.debug("Saving network weights.") + torch.save({"model_state": self._network.state_dict()}, self.weights_filename) + + @abstractmethod + def mapping(self) -> Dict: + """Mapping from network output to class.""" + ... diff --git a/src/text_recognizer/models/character_model.py b/src/text_recognizer/models/character_model.py new file mode 100644 index 0000000..1570344 --- /dev/null +++ b/src/text_recognizer/models/character_model.py @@ -0,0 +1,71 @@ +"""Defines the CharacterModel class.""" +from typing import Callable, Dict, Optional, Tuple + +import numpy as np +import torch +from torch import nn +from torchvision.transforms import ToTensor + +from text_recognizer.datasets.emnist_dataset import load_emnist_mapping +from text_recognizer.models.base import Model +from text_recognizer.networks.mlp import mlp + + +class CharacterModel(Model): + """Model for predicting characters from images.""" + + def __init__( + self, + network_fn: Callable, + network_args: Dict, + data_loader_args: Optional[Dict] = None, + metrics: Optional[Dict] = None, + criterion: Optional[Callable] = None, + criterion_args: Optional[Dict] = None, + optimizer: Optional[Callable] = None, + optimizer_args: Optional[Dict] = None, + lr_scheduler: Optional[Callable] = None, + lr_scheduler_args: Optional[Dict] = None, + device: Optional[str] = None, + ) -> None: + """Initializes the CharacterModel.""" + + super().__init__( + network_fn, + data_loader_args, + network_args, + metrics, + criterion, + optimizer, + device, + ) + self.emnist_mapping = self.mapping() + self.eval() + + def mapping(self) -> Dict: + """Mapping between integers and classes.""" + mapping = load_emnist_mapping() + return mapping + + def predict_on_image(self, image: np.ndarray) -> Tuple[str, float]: + """Character prediction on an image. + + Args: + image (np.ndarray): An image containing a character. + + Returns: + Tuple[str, float]: The predicted character and the confidence in the prediction. + + """ + if image.dtype == np.uint8: + image = (image / 255).astype(np.float32) + + # Conver to Pytorch Tensor. + image = ToTensor(image) + + prediction = self.network(image) + index = torch.argmax(prediction, dim=1) + confidence_of_prediction = prediction[index] + predicted_character = self.emnist_mapping[index] + + return predicted_character, confidence_of_prediction diff --git a/src/text_recognizer/models/util.py b/src/text_recognizer/models/util.py new file mode 100644 index 0000000..905fe7b --- /dev/null +++ b/src/text_recognizer/models/util.py @@ -0,0 +1,19 @@ +"""Utility functions for models.""" + +import torch + + +def accuracy(outputs: torch.Tensor, labels: torch.Tensro) -> float: + """Short summary. + + Args: + outputs (torch.Tensor): The output from the network. + labels (torch.Tensor): Ground truth labels. + + Returns: + float: The accuracy for the batch. + + """ + _, predicted = torch.max(outputs.data, dim=1) + acc = (predicted == labels).sum().item() / labels.shape[0] + return acc diff --git a/src/text_recognizer/networks/lenet.py b/src/text_recognizer/networks/lenet.py new file mode 100644 index 0000000..71d247f --- /dev/null +++ b/src/text_recognizer/networks/lenet.py @@ -0,0 +1,93 @@ +"""Defines the LeNet network.""" +from typing import Callable, Optional, Tuple + +import torch +from torch import nn + + +class Flatten(nn.Module): + """Flattens a tensor.""" + + def forward(self, x: int) -> torch.Tensor: + """Flattens a tensor for input to a nn.Linear layer.""" + return torch.flatten(x, start_dim=1) + + +class LeNet(nn.Module): + """LeNet network.""" + + def __init__( + self, + channels: Tuple[int, ...], + kernel_sizes: Tuple[int, ...], + hidden_size: Tuple[int, ...], + dropout_rate: float, + output_size: int, + activation_fn: Optional[Callable] = None, + ) -> None: + """The LeNet network. + + Args: + channels (Tuple[int, ...]): Channels in the convolutional layers. + kernel_sizes (Tuple[int, ...]): Kernel sizes in the convolutional layers. + hidden_size (Tuple[int, ...]): Size of the flattend output form the convolutional layers. + dropout_rate (float): The dropout rate. + output_size (int): Number of classes. + activation_fn (Optional[Callable]): The non-linear activation function. Defaults to + nn.ReLU(inplace). + + """ + super().__init__() + + if activation_fn is None: + activation_fn = nn.ReLU(inplace=True) + + self.layers = [ + nn.Conv2d( + in_channels=channels[0], + out_channels=channels[1], + kernel_size=kernel_sizes[0], + ), + activation_fn, + nn.Conv2d( + in_channels=channels[1], + out_channels=channels[2], + kernel_size=kernel_sizes[1], + ), + activation_fn, + nn.MaxPool2d(kernel_sizes[2]), + nn.Dropout(p=dropout_rate), + Flatten(), + nn.Linear(in_features=hidden_size[0], out_features=hidden_size[1]), + activation_fn, + nn.Dropout(p=dropout_rate), + nn.Linear(in_features=hidden_size[1], out_features=output_size), + ] + + self.layers = nn.Sequential(*self.layers) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + """The feedforward.""" + return self.layers(x) + + +# def test(): +# x = torch.randn([1, 1, 28, 28]) +# channels = [1, 32, 64] +# kernel_sizes = [3, 3, 2] +# hidden_size = [9216, 128] +# output_size = 10 +# dropout_rate = 0.2 +# activation_fn = nn.ReLU() +# net = LeNet( +# channels=channels, +# kernel_sizes=kernel_sizes, +# dropout_rate=dropout_rate, +# hidden_size=hidden_size, +# output_size=output_size, +# activation_fn=activation_fn, +# ) +# from torchsummary import summary +# +# summary(net, (1, 28, 28), device="cpu") +# out = net(x) diff --git a/src/text_recognizer/networks/mlp.py b/src/text_recognizer/networks/mlp.py new file mode 100644 index 0000000..2a41790 --- /dev/null +++ b/src/text_recognizer/networks/mlp.py @@ -0,0 +1,81 @@ +"""Defines the MLP network.""" +from typing import Callable, Optional + +import torch +from torch import nn + + +class MLP(nn.Module): + """Multi layered perceptron network.""" + + def __init__( + self, + input_size: int, + output_size: int, + hidden_size: int, + num_layers: int, + dropout_rate: float, + activation_fn: Optional[Callable] = None, + ) -> None: + """Initialization of the MLP network. + + Args: + input_size (int): The input shape of the network. + output_size (int): Number of classes in the dataset. + hidden_size (int): The number of `neurons` in each hidden layer. + num_layers (int): The number of hidden layers. + dropout_rate (float): The dropout rate at each layer. + activation_fn (Optional[Callable]): The activation function in the hidden layers, (default: + nn.ReLU()). + + """ + super().__init__() + + if activation_fn is None: + activation_fn = nn.ReLU(inplace=True) + + self.layers = [ + nn.Linear(in_features=input_size, out_features=hidden_size), + activation_fn, + ] + + for _ in range(num_layers): + self.layers += [ + nn.Linear(in_features=hidden_size, out_features=hidden_size), + activation_fn, + ] + + if dropout_rate: + self.layers.append(nn.Dropout(p=dropout_rate)) + + self.layers.append(nn.Linear(in_features=hidden_size, out_features=output_size)) + + self.layers = nn.Sequential(*self.layers) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + """The feedforward.""" + x = torch.flatten(x, start_dim=1) + return self.layers(x) + + +# def test(): +# x = torch.randn([1, 28, 28]) +# input_size = torch.flatten(x).shape[0] +# output_size = 10 +# hidden_size = 128 +# num_layers = 5 +# dropout_rate = 0.25 +# activation_fn = nn.GELU() +# net = MLP( +# input_size=input_size, +# output_size=output_size, +# hidden_size=hidden_size, +# num_layers=num_layers, +# dropout_rate=dropout_rate, +# activation_fn=activation_fn, +# ) +# from torchsummary import summary +# +# summary(net, (1, 28, 28), device="cpu") +# +# out = net(x) diff --git a/src/text_recognizer/tests/__init__.py b/src/text_recognizer/tests/__init__.py new file mode 100644 index 0000000..18ff212 --- /dev/null +++ b/src/text_recognizer/tests/__init__.py @@ -0,0 +1 @@ +"""Test modules for the text text recognizer.""" diff --git a/src/text_recognizer/tests/support/__init__.py b/src/text_recognizer/tests/support/__init__.py new file mode 100644 index 0000000..a265ede --- /dev/null +++ b/src/text_recognizer/tests/support/__init__.py @@ -0,0 +1,2 @@ +"""Support file modules.""" +from .create_emnist_support_files import create_emnist_support_files diff --git a/src/text_recognizer/tests/support/create_emnist_support_files.py b/src/text_recognizer/tests/support/create_emnist_support_files.py new file mode 100644 index 0000000..5dd1a81 --- /dev/null +++ b/src/text_recognizer/tests/support/create_emnist_support_files.py @@ -0,0 +1,33 @@ +"""Module for creating EMNIST test support files.""" +from pathlib import Path +import shutil + +from text_recognizer.datasets.emnist_dataset import ( + fetch_emnist_dataset, + load_emnist_mapping, +) +from text_recognizer.util import write_image + +SUPPORT_DIRNAME = Path(__file__).parents[0].resolve() / "emnist" + + +def create_emnist_support_files() -> None: + """Create support images for test of CharacterPredictor class.""" + shutil.rmtree(SUPPORT_DIRNAME, ignore_errors=True) + SUPPORT_DIRNAME.mkdir() + + dataset = fetch_emnist_dataset(split="byclass", train=False) + mapping = load_emnist_mapping() + + for index in [5, 7, 9]: + image, label = dataset[index] + if len(image.shape) == 3: + image = image.squeeze(0) + image = image.numpy() + label = mapping[int(label)] + print(index, label) + write_image(image, str(SUPPORT_DIRNAME / f"{label}.png")) + + +if __name__ == "__main__": + create_emnist_support_files() diff --git a/src/text_recognizer/tests/support/emnist/8.png b/src/text_recognizer/tests/support/emnist/8.png new file mode 100644 index 0000000..faa29aa Binary files /dev/null and b/src/text_recognizer/tests/support/emnist/8.png differ diff --git a/src/text_recognizer/tests/support/emnist/U.png b/src/text_recognizer/tests/support/emnist/U.png new file mode 100644 index 0000000..304eaec Binary files /dev/null and b/src/text_recognizer/tests/support/emnist/U.png differ diff --git a/src/text_recognizer/tests/support/emnist/e.png b/src/text_recognizer/tests/support/emnist/e.png new file mode 100644 index 0000000..a03ecd4 Binary files /dev/null and b/src/text_recognizer/tests/support/emnist/e.png differ diff --git a/src/text_recognizer/tests/test_character_predictor.py b/src/text_recognizer/tests/test_character_predictor.py new file mode 100644 index 0000000..7c094ef --- /dev/null +++ b/src/text_recognizer/tests/test_character_predictor.py @@ -0,0 +1,26 @@ +"""Test for CharacterPredictor class.""" +import os +from pathlib import Path +import unittest + +from text_recognizer.character_predictor import CharacterPredictor + +SUPPORT_DIRNAME = Path(__file__).parents[0].resolve() / "support" / "emnist" + +os.environ["CUDA_VISIBLE_DEVICES"] = "" + + +class TestCharacterPredictor(unittest.TestCase): + """Tests for the CharacterPredictor class.""" + + def test_filename(self) -> None: + """Test that CharacterPredictor correctly predicts on a single image, for serveral test images.""" + predictor = CharacterPredictor() + + for filename in SUPPORT_DIRNAME.glob("*.png"): + pred, conf = predictor.predict(str(filename)) + print( + f"Prediction: {pred} at confidence: {conf} for image with character {filename.stem}" + ) + self.assertEqual(pred, filename.stem) + self.assertGreater(conf, 0.7) diff --git a/src/text_recognizer/util.py b/src/text_recognizer/util.py new file mode 100644 index 0000000..52fa1e4 --- /dev/null +++ b/src/text_recognizer/util.py @@ -0,0 +1,51 @@ +"""Utility functions for text_recognizer module.""" +import os +from pathlib import Path +from typing import Union +from urllib.request import urlopen + +import cv2 +import numpy as np + + +def read_image(image_uri: Union[Path, str], grayscale: bool = False) -> np.ndarray: + """Read image_uri.""" + + def read_image_from_filename(image_filename: str, imread_flag: int) -> np.ndarray: + return cv2.imread(str(image_filename), imread_flag) + + def read_image_from_url(image_url: str, imread_flag: int) -> np.ndarray: + if image_url.lower().startswith("http"): + url_response = urlopen(str(image_url)) + image_array = np.array(bytearray(url_response.read()), dtype=np.uint8) + return cv2.imdecode(image_array, imread_flag) + else: + raise ValueError( + "Url does not start with http, therfore not safe to open..." + ) from None + + imread_flag = cv2.IMREAD_GRAYSCALE if grayscale else cv2.IMREAD_COLOR + local_file = os.path.exsits(image_uri) + try: + image = None + if local_file: + image = read_image_from_filename(image_uri, imread_flag) + else: + image = read_image_from_url(image_uri, imread_flag) + assert image is not None + except Exception as e: + raise ValueError(f"Could not load image at {image_uri}: {e}") + return image + + +def rescale_image(image: np.ndarray) -> np.ndarray: + """Rescale image from [0, 1] to [0, 255].""" + if image.max() <= 1.0: + image = 255 * (image - image.min()) / (image.max() - image.min()) + return image + + +def write_image(image: np.ndarray, filename: Union[Path, str]) -> None: + """Write image to file.""" + image = rescale_image(image) + cv2.imwrite(str(filename), image) diff --git a/src/training/run_experiment.py b/src/training/run_experiment.py new file mode 100644 index 0000000..8033f47 --- /dev/null +++ b/src/training/run_experiment.py @@ -0,0 +1 @@ +"""Script to run experiments.""" diff --git a/src/training/train.py b/src/training/train.py new file mode 100644 index 0000000..783de02 --- /dev/null +++ b/src/training/train.py @@ -0,0 +1,230 @@ +"""Training script for PyTorch models.""" + +from datetime import datetime +from pathlib import Path +from typing import Callable, Dict, Optional + +from loguru import logger +import numpy as np +import torch +from tqdm import tqdm, trange +from training.util import RunningAverage + +torch.backends.cudnn.benchmark = True +np.random.seed(4711) +torch.manual_seed(4711) +torch.cuda.manual_seed(4711) + + +EXPERIMENTS_DIRNAME = Path(__file__).parents[0].resolve() / "experiments" + + +class Trainer: + """Trainer for training PyTorch models.""" + + # TODO implement wandb. + + def __init__( + self, + model: Callable, + epochs: int, + val_metric: str = "accuracy", + checkpoint_path: Optional[Path] = None, + ) -> None: + """Initialization of the Trainer. + + Args: + model (Callable): A model object. + epochs (int): Number of epochs to train. + val_metric (str): The validation metric to evaluate the model on. Defaults to "accuracy". + checkpoint_path (Optional[Path]): The path to a previously trained model. Defaults to None. + + """ + self.model = model + self.epochs = epochs + self.checkpoint_path = checkpoint_path + self.start_epoch = 0 + + if self.checkpoint_path is not None: + self.start_epoch = self.model.load_checkpoint(self.checkpoint_path) + + self.val_metric = val_metric + self.best_val_metric = 0.0 + logger.add(self.model.name + "_{time}.log") + + def train(self) -> None: + """Training loop.""" + # TODO add summary + # Set model to traning mode. + self.model.train() + + # Running average for the loss. + loss_avg = RunningAverage() + + data_loader = self.model.data_loaders["train"] + + with tqdm( + total=len(data_loader), + leave=False, + unit="step", + bar_format="{n_fmt}/{total_fmt} {bar} {remaining} {rate_inv_fmt}{postfix}", + ) as t: + for data, targets in data_loader: + + data, targets = ( + data.to(self.model.device), + targets.to(self.model.device), + ) + + # Forward pass. + # Get the network prediction. + output = self.model.predict(data) + + # Compute the loss. + loss = self.model.criterion(output, targets) + + # Backward pass. + # Clear the previous gradients. + self.model.optimizer.zero_grad() + + # Compute the gradients. + loss.backward() + + # Perform updates using calculated gradients. + self.model.optimizer.step() + + # Update the learning rate scheduler. + if self.model.lr_scheduler is not None: + self.model.lr_scheduler.step() + + # Compute metrics. + loss_avg.update(loss.item()) + output = output.data.cpu() + targets = targets.data.cpu() + metrics = { + metric: round(self.model.metrics[metric](output, targets), 4) + for metric in self.model.metrics + } + metrics["loss"] = round(loss_avg(), 4) + + # Update Tqdm progress bar. + t.set_postfix(**metrics) + t.update() + + def evaluate(self) -> Dict: + """Evaluation loop. + + Returns: + Dict: A dictionary of evaluation metrics. + + """ + # Set model to eval mode. + self.model.eval() + + # Running average for the loss. + data_loader = self.model.data_loaders["val"] + + # Running average for the loss. + loss_avg = RunningAverage() + + # Summary for the current eval loop. + summary = [] + + with tqdm( + total=len(data_loader), + leave=False, + unit="step", + bar_format="{n_fmt}/{total_fmt} {bar} {remaining} {rate_inv_fmt}{postfix}", + ) as t: + for data, targets in data_loader: + data, targets = ( + data.to(self.model.device), + targets.to(self.model.device), + ) + + # Forward pass. + # Get the network prediction. + output = self.model.predict(data) + + # Compute the loss. + loss = self.model.criterion(output, targets) + + # Compute metrics. + loss_avg.update(loss.item()) + output = output.data.cpu() + targets = targets.data.cpu() + metrics = { + metric: round(self.model.metrics[metric](output, targets), 4) + for metric in self.model.metrics + } + metrics["loss"] = round(loss.item(), 4) + + summary.append(metrics) + + # Update Tqdm progress bar. + t.set_postfix(**metrics) + t.update() + + # Compute mean of all metrics. + metrics_mean = { + metric: np.mean(x[metric] for x in summary) for metric in summary[0] + } + metrics_str = " - ".join(f"{k}: {v}" for k, v in metrics_mean.items()) + logger.debug(metrics_str) + + return metrics_mean + + def run(self) -> None: + """Training and evaluation loop.""" + # Create new experiment. + EXPERIMENTS_DIRNAME.mkdir(parents=True, exist_ok=True) + experiment = datetime.now().strftime("%m%d_%H%M%S") + experiment_dir = EXPERIMENTS_DIRNAME / self.model.network.__name__ / experiment + + # Create log and model directories. + log_dir = experiment_dir / "log" + model_dir = experiment_dir / "model" + + # Make sure the log directory exists. + log_dir.mkdir(parents=True, exist_ok=True) + + logger.add( + str(log_dir / "train.log"), + format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}", + ) + + logger.debug( + f"Running an experiment called {self.model.network.__name__}/{experiment}." + ) + + # Pŕints a summary of the network in terminal. + self.model.summary() + + # Run the training loop. + for epoch in trange( + total=self.epochs, + initial=self.start_epoch, + leave=True, + bar_format="{desc}: {n_fmt}/{total_fmt} {bar} {remaining}{postfix}", + desc="Epoch", + ): + # Perform one training pass over the training set. + self.train() + + # Evaluate the model on the validation set. + val_metrics = self.evaluate() + + # If the model has a learning rate scheduler, compute a step. + if self.model.lr_scheduler is not None: + self.model.lr_scheduler.step() + + # The validation metric to evaluate the model on, e.g. accuracy. + val_metric = val_metrics[self.val_metric] + is_best = val_metric >= self.best_val_metric + + # Save checkpoint. + self.model.save_checkpoint(model_dir, is_best, epoch, self.val_metric) + + if self.start_epoch > 0 and epoch + self.start_epoch == self.epochs: + logger.debug(f"Trained the model for {self.epochs} number of epochs.") + break diff --git a/src/training/util.py b/src/training/util.py new file mode 100644 index 0000000..132b2dc --- /dev/null +++ b/src/training/util.py @@ -0,0 +1,19 @@ +"""Utility functions for training neural networks.""" + + +class RunningAverage: + """Maintains a running average.""" + + def __init__(self) -> None: + """Initializes the parameters.""" + self.steps = 0 + self.total = 0 + + def update(self, val: float) -> None: + """Updates the parameters.""" + self.total += val + self.steps += 1 + + def __call__(self) -> float: + """Computes the running average.""" + return self.total / float(self.steps) -- cgit v1.2.3-70-g09d2