summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/notebooks/00-testing-stuff-out.ipynb (renamed from src/notebooks/Untitled.ipynb)208
-rw-r--r--src/notebooks/01-look-at-emnist.ipynb398
-rw-r--r--src/notebooks/01b-dataset_normalization.ipynb148
-rw-r--r--src/notebooks/02a-sentence-generator.ipynb98
-rw-r--r--src/notebooks/02b-emnist-lines-dataset.ipynb413
-rw-r--r--src/notebooks/tqdm.ipynb280
-rw-r--r--src/text_recognizer/character_predictor.py5
-rw-r--r--src/text_recognizer/datasets/__init__.py24
-rw-r--r--src/text_recognizer/datasets/emnist_dataset.py279
-rw-r--r--src/text_recognizer/datasets/emnist_lines_dataset.py326
-rw-r--r--src/text_recognizer/datasets/sentence_generator.py81
-rw-r--r--src/text_recognizer/datasets/util.py11
-rw-r--r--src/text_recognizer/models/base.py84
-rw-r--r--src/text_recognizer/models/character_model.py32
-rw-r--r--src/text_recognizer/tests/test_character_predictor.py14
-rw-r--r--src/text_recognizer/weights/CharacterModel_Emnist_LeNet_weights.ptbin14483400 -> 14485305 bytes
-rw-r--r--src/text_recognizer/weights/CharacterModel_Emnist_MLP_weights.ptbin1702233 -> 1704096 bytes
-rw-r--r--src/training/callbacks/__init__.py20
-rw-r--r--src/training/callbacks/base.py231
-rw-r--r--src/training/callbacks/early_stopping.py106
-rw-r--r--src/training/callbacks/lr_schedulers.py97
-rw-r--r--src/training/callbacks/wandb_callbacks.py93
-rw-r--r--src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/config.yml48
-rw-r--r--src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/model/best.ptbin14483400 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/model/last.ptbin14483400 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/config.yml48
-rw-r--r--src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/model/best.ptbin14483400 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/model/last.ptbin14483400 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_124928/config.yml43
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141139/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/model/best.ptbin1901268 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/model/last.ptbin1901268 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/model/best.ptbin1901268 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/model/last.ptbin1901268 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/model/best.ptbin1901268 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/model/last.ptbin1901268 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_145028/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_150212/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_150301/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_150317/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/model/best.ptbin1901268 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/model/last.ptbin1901268 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_151408/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_153144/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_153207/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/model/best.ptbin1702142 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/model/last.ptbin1702142 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/model/best.ptbin1702142 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/model/last.ptbin1702142 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/model/best.ptbin1702142 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/model/last.ptbin1702142 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/config.yml46
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/model/best.ptbin1702114 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/model/last.ptbin1702114 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/config.yml46
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/model/best.ptbin1702114 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/model/last.ptbin1702114 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/config.yml46
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/model/best.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/model/last.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/config.yml46
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/model/best.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/model/last.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/config.yml46
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/model/best.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/model/last.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191111/config.yml46
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/config.yml46
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/model/best.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/model/last.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/config.yml42
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/model/best.ptbin1135058 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/model/last.ptbin1135058 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/config.yml42
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/model/best.ptbin1135058 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/model/last.ptbin1135058 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/config.yml47
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/model/best.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/model/last.ptbin1702135 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/config.yml49
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/model/best.ptbin1702233 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/model/last.ptbin1702249 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_213125/config.yml49
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/config.yml49
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/model/best.ptbin1702233 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/model/last.ptbin1702233 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/config.yml49
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/model/best.ptbin1702233 -> 0 bytes
-rw-r--r--src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/model/last.ptbin1702233 -> 0 bytes
-rw-r--r--src/training/experiments/sample.yml43
-rw-r--r--src/training/experiments/sample_experiment.yml34
-rw-r--r--src/training/prepare_experiments.py18
-rw-r--r--src/training/run_experiment.py45
-rw-r--r--src/training/train.py237
-rw-r--r--src/wandb/settings4
102 files changed, 2617 insertions, 2205 deletions
diff --git a/src/notebooks/Untitled.ipynb b/src/notebooks/00-testing-stuff-out.ipynb
index 97c523d..49ca4c4 100644
--- a/src/notebooks/Untitled.ipynb
+++ b/src/notebooks/00-testing-stuff-out.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
@@ -11,9 +11,20 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 13,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "torch.optim.lr_scheduler.StepLR"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
"getattr(torch.optim.lr_scheduler, \"StepLR\")"
]
@@ -38,7 +49,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
@@ -47,7 +58,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
@@ -60,6 +71,13 @@
"execution_count": null,
"metadata": {},
"outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
"source": [
"b = torch.randn(2)"
]
@@ -84,7 +102,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
@@ -94,11 +112,22 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 21,
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "tensor(1.1283)"
+ ]
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
"source": [
- "output"
+ "torch.tensor(output.item())"
]
},
{
@@ -854,32 +883,175 @@
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
- "from loguru import logger"
+ "class ModeKeys:\n",
+ " \"\"\"Mode keys for CallbackList.\"\"\"\n",
+ "\n",
+ " TRAIN = \"train\"\n",
+ " VALIDATION = \"validation\""
]
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = ModeKeys()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'train'"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "m.TRAIN"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([1.00000000e-05, 1.26485522e-05, 1.59985872e-05, 2.02358965e-05,\n",
+ " 2.55954792e-05, 3.23745754e-05, 4.09491506e-05, 5.17947468e-05,\n",
+ " 6.55128557e-05, 8.28642773e-05, 1.04811313e-04, 1.32571137e-04,\n",
+ " 1.67683294e-04, 2.12095089e-04, 2.68269580e-04, 3.39322177e-04,\n",
+ " 4.29193426e-04, 5.42867544e-04, 6.86648845e-04, 8.68511374e-04,\n",
+ " 1.09854114e-03, 1.38949549e-03, 1.75751062e-03, 2.22299648e-03,\n",
+ " 2.81176870e-03, 3.55648031e-03, 4.49843267e-03, 5.68986603e-03,\n",
+ " 7.19685673e-03, 9.10298178e-03, 1.15139540e-02, 1.45634848e-02,\n",
+ " 1.84206997e-02, 2.32995181e-02, 2.94705170e-02, 3.72759372e-02,\n",
+ " 4.71486636e-02, 5.96362332e-02, 7.54312006e-02, 9.54095476e-02,\n",
+ " 1.20679264e-01, 1.52641797e-01, 1.93069773e-01, 2.44205309e-01,\n",
+ " 3.08884360e-01, 3.90693994e-01, 4.94171336e-01, 6.25055193e-01,\n",
+ " 7.90604321e-01, 1.00000000e+00])"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "np.logspace(-5, 0, base=10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
"metadata": {},
"outputs": [
{
- "ename": "AttributeError",
- "evalue": "'Logger' object has no attribute 'DEBUG'",
+ "data": {
+ "text/plain": [
+ "0.018420699693267165"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "np.random.choice(np.logspace(-5, 0, base=10))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "ModuleNotFoundError",
+ "evalue": "No module named 'tqdm.auto.tqdm'; 'tqdm.auto' is not a package",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-18-e1360ed6a5af>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mlogger\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mDEBUG\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mAttributeError\u001b[0m: 'Logger' object has no attribute 'DEBUG'"
+ "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m<ipython-input-20-68e3c8bf3e1f>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mtqdm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mauto\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtqdm\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mtqdm_auto\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'tqdm.auto.tqdm'; 'tqdm.auto' is not a package"
+ ]
+ }
+ ],
+ "source": [
+ "import tqdm.auto.tqdm as tqdm_auto"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "tqdm.notebook.tqdm_notebook"
+ ]
+ },
+ "execution_count": 19,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tqdm.auto.tqdm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def test():\n",
+ " for i in range(9):\n",
+ " pass\n",
+ " print(i)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "8\n"
]
}
],
"source": [
- "logger.DEBUG"
+ "test()"
]
},
{
diff --git a/src/notebooks/01-look-at-emnist.ipynb b/src/notebooks/01-look-at-emnist.ipynb
index 870679b..044040c 100644
--- a/src/notebooks/01-look-at-emnist.ipynb
+++ b/src/notebooks/01-look-at-emnist.ipynb
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 1,
+ "execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@@ -13,6 +13,7 @@
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from PIL import Image\n",
+ "import torch\n",
"from importlib.util import find_spec\n",
"if find_spec(\"text_recognizer\") is None:\n",
" import sys\n",
@@ -21,34 +22,330 @@
},
{
"cell_type": "code",
- "execution_count": 21,
+ "execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
- "from text_recognizer.datasets.emnist_dataset import fetch_data_loader, fetch_emnist_dataset, load_emnist_mapping"
+ "from text_recognizer.datasets import EmnistDataLoaders"
]
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
- "dataset = fetch_emnist_dataset(\"byclass\", True, True)"
+ "data_loaders = EmnistDataLoaders(splits=[\"val\"], sample_to_balance=True,\n",
+ " subsample_fraction = None,\n",
+ " transform = None,\n",
+ " target_transform = None,\n",
+ " batch_size = 1,\n",
+ " shuffle = True,\n",
+ " num_workers = 0,\n",
+ " cuda = False,\n",
+ " seed = 4711)"
]
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Dataset EMNIST\n",
+ " Number of datapoints: 55908\n",
+ " Root location: /home/akternurra/Documents/projects/quest-for-general-artifical-intelligence/projects/text-recognizer/data\n",
+ " Split: Test\n",
+ " StandardTransform\n",
+ "Transform: Compose(\n",
+ " <text_recognizer.datasets.util.Transpose object at 0x7fc764a10eb0>\n",
+ " ToTensor()\n",
+ " )"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "data_loaders"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from text_recognizer.datasets import EmnistDataset"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "dataset = EmnistDataset()\n",
+ "dataset.load_emnist_dataset()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "torch.Size([3, 28, 28])"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dataset.data[[1, 2, 3]].shape"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "tensor([18, 36, 0, ..., 28, 0, 5])"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dataset.targets"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "{0: '0',\n",
+ " 1: '1',\n",
+ " 2: '2',\n",
+ " 3: '3',\n",
+ " 4: '4',\n",
+ " 5: '5',\n",
+ " 6: '6',\n",
+ " 7: '7',\n",
+ " 8: '8',\n",
+ " 9: '9',\n",
+ " 10: 'A',\n",
+ " 11: 'B',\n",
+ " 12: 'C',\n",
+ " 13: 'D',\n",
+ " 14: 'E',\n",
+ " 15: 'F',\n",
+ " 16: 'G',\n",
+ " 17: 'H',\n",
+ " 18: 'I',\n",
+ " 19: 'J',\n",
+ " 20: 'K',\n",
+ " 21: 'L',\n",
+ " 22: 'M',\n",
+ " 23: 'N',\n",
+ " 24: 'O',\n",
+ " 25: 'P',\n",
+ " 26: 'Q',\n",
+ " 27: 'R',\n",
+ " 28: 'S',\n",
+ " 29: 'T',\n",
+ " 30: 'U',\n",
+ " 31: 'V',\n",
+ " 32: 'W',\n",
+ " 33: 'X',\n",
+ " 34: 'Y',\n",
+ " 35: 'Z',\n",
+ " 36: 'a',\n",
+ " 37: 'b',\n",
+ " 38: 'c',\n",
+ " 39: 'd',\n",
+ " 40: 'e',\n",
+ " 41: 'f',\n",
+ " 42: 'g',\n",
+ " 43: 'h',\n",
+ " 44: 'i',\n",
+ " 45: 'j',\n",
+ " 46: 'k',\n",
+ " 47: 'l',\n",
+ " 48: 'm',\n",
+ " 49: 'n',\n",
+ " 50: 'o',\n",
+ " 51: 'p',\n",
+ " 52: 'q',\n",
+ " 53: 'r',\n",
+ " 54: 's',\n",
+ " 55: 't',\n",
+ " 56: 'u',\n",
+ " 57: 'v',\n",
+ " 58: 'w',\n",
+ " 59: 'x',\n",
+ " 60: 'y',\n",
+ " 61: 'z',\n",
+ " 62: ' ',\n",
+ " 63: '!',\n",
+ " 64: '\"',\n",
+ " 65: '#',\n",
+ " 66: '&',\n",
+ " 67: \"'\",\n",
+ " 68: '(',\n",
+ " 69: ')',\n",
+ " 70: '*',\n",
+ " 71: '+',\n",
+ " 72: ',',\n",
+ " 73: '-',\n",
+ " 74: '.',\n",
+ " 75: '/',\n",
+ " 76: ':',\n",
+ " 77: ';',\n",
+ " 78: '?',\n",
+ " 79: '_'}"
+ ]
+ },
+ "execution_count": 17,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dataset.mapping"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "tensor([18, 36, 0, ..., 28, 0, 5])"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "dataset.targets"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "np.random.randint(0, len(data_loader(\"val\").dataset.data), 4)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
- "dl = fetch_data_loader(\"byclass\", True, True, shuffle=True, batch_size=9)"
+ "data_loader(\"val\").dataset.targets[np.random.randint(0, len(data_loader(\"val\").dataset.data), 4)].numpy()[0]"
]
},
{
"cell_type": "code",
- "execution_count": 52,
+ "execution_count": null,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [],
+ "source": [
+ "len(data_loader(\"val\"))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = data_loader(\"val\").dataset.data[np.random.randint(0, len(data_loader(\"val\").dataset.data), 4)]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "\"accuracy\" in \"val_accuracy\""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x[0].dtype"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = x[0].type(\"torch.FloatTensor\") / 255"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "x = x.numpy().reshape(28, 28).swapaxes(0, 1)\n",
+ "plt.imshow(x, cmap='gray')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Fix below with new data loader"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -57,7 +354,7 @@
},
{
"cell_type": "code",
- "execution_count": 55,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -76,7 +373,7 @@
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -94,7 +391,26 @@
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "a = None"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if a:\n",
+ " print(\"afaf\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
"metadata": {},
"outputs": [],
"source": [
@@ -103,80 +419,36 @@
},
{
"cell_type": "code",
- "execution_count": 56,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- "<Figure size 648x648 with 9 Axes>"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"display_images(dataset, classes)"
]
},
{
"cell_type": "code",
- "execution_count": 57,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "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": [
- "<Figure size 648x648 with 9 Axes>"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"display_dl_images(dl, 9, classes)"
]
},
{
"cell_type": "code",
- "execution_count": 58,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "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": [
- "<Figure size 648x648 with 9 Axes>"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"display_dl_images(dl, 9, classes)"
]
},
{
"cell_type": "code",
- "execution_count": 59,
+ "execution_count": null,
"metadata": {},
- "outputs": [
- {
- "data": {
- "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": [
- "<Figure size 648x648 with 9 Axes>"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
+ "outputs": [],
"source": [
"display_dl_images(dl, 9, classes)"
]
diff --git a/src/notebooks/01b-dataset_normalization.ipynb b/src/notebooks/01b-dataset_normalization.ipynb
new file mode 100644
index 0000000..9421816
--- /dev/null
+++ b/src/notebooks/01b-dataset_normalization.ipynb
@@ -0,0 +1,148 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "from PIL import Image\n",
+ "import torch\n",
+ "from importlib.util import find_spec\n",
+ "if find_spec(\"text_recognizer\") is None:\n",
+ " import sys\n",
+ " sys.path.append('..')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from text_recognizer.datasets import EmnistDataLoader"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_loaders = EmnistDataLoader(splits=[\"train\"], sample_to_balance=True,\n",
+ " subsample_fraction = None,\n",
+ " transform = None,\n",
+ " target_transform = None,\n",
+ " batch_size = 512,\n",
+ " shuffle = True,\n",
+ " num_workers = 0,\n",
+ " cuda = False,\n",
+ " seed = 4711)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "loader = data_loaders(\"train\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "mean = 0.\n",
+ "std = 0.\n",
+ "nb_samples = 0.\n",
+ "for data in loader:\n",
+ " data, _ = data\n",
+ " batch_samples = data.size(0)\n",
+ " data = data.view(batch_samples, data.size(1), -1)\n",
+ " mean += data.mean(2).sum(0)\n",
+ " std += data.std(2).sum(0)\n",
+ " nb_samples += batch_samples\n",
+ "\n",
+ "mean /= nb_samples\n",
+ "std /= nb_samples"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "tensor([0.1731])"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "mean"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "tensor([0.3247])"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "std"
+ ]
+ },
+ {
+ "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/notebooks/02a-sentence-generator.ipynb b/src/notebooks/02a-sentence-generator.ipynb
new file mode 100644
index 0000000..99aa56a
--- /dev/null
+++ b/src/notebooks/02a-sentence-generator.ipynb
@@ -0,0 +1,98 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "from PIL import Image\n",
+ "import torch\n",
+ "from importlib.util import find_spec\n",
+ "if find_spec(\"text_recognizer\") is None:\n",
+ " import sys\n",
+ " sys.path.append('..')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from text_recognizer.datasets import SentenceGenerator"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "<class 'str'>\n"
+ ]
+ }
+ ],
+ "source": [
+ "sentence_generator = SentenceGenerator(32)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'broad___________________________'"
+ ]
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "sentence_generator.generate()"
+ ]
+ },
+ {
+ "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/notebooks/02b-emnist-lines-dataset.ipynb b/src/notebooks/02b-emnist-lines-dataset.ipynb
new file mode 100644
index 0000000..e0bc2c8
--- /dev/null
+++ b/src/notebooks/02b-emnist-lines-dataset.ipynb
@@ -0,0 +1,413 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%load_ext autoreload\n",
+ "%autoreload 2\n",
+ "\n",
+ "%matplotlib inline\n",
+ "import matplotlib.pyplot as plt\n",
+ "import numpy as np\n",
+ "from PIL import Image\n",
+ "import torch\n",
+ "from importlib.util import find_spec\n",
+ "if find_spec(\"text_recognizer\") is None:\n",
+ " import sys\n",
+ " sys.path.append('..')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 53,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from text_recognizer.datasets import EmnistDataset, EmnistLinesDataset, Transpose, construct_image_from_string, get_samples_by_character"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "emnist_train = EmnistDataset(train=True, sample_to_balance=True)\n",
+ "emnist_val = EmnistDataset(train=False, sample_to_balance=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 54,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "emnist_lines = EmnistLinesDataset(train=True, emnist=emnist_train)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 55,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "2020-08-03 21:23:17.973 | DEBUG | text_recognizer.datasets.emnist_lines_dataset:_load_data:113 - EmnistLinesDataset loading data from HDF5...\n"
+ ]
+ }
+ ],
+ "source": [
+ "emnist_lines._load_or_generate_data()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 56,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def convert_y_label_to_string(y, emnist_lines=emnist_lines):\n",
+ " return ''.join([emnist_lines.mapping[i] for i in y])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 57,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(tensor([[[0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " ...,\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.],\n",
+ " [0., 0., 0., ..., 0., 0., 0.]]]),\n",
+ " tensor([ 4, 1, 2, 62, 32, 40, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,\n",
+ " 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79],\n",
+ " dtype=torch.uint8))"
+ ]
+ },
+ "execution_count": 57,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "emnist_lines[0]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 59,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "412 We____________________________\n",
+ "new_______________________________\n",
+ "decided___________________________\n",
+ "indictment the 10000 bond was_____\n",
+ "of possessions and living plays___\n",
+ "Lillys____________________________\n",
+ "life______________________________\n",
+ "in circles making_________________\n",
+ "enlist____________________________\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 1440x1440 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "\n",
+ "\n",
+ "num_samples_to_plot = 9\n",
+ "\n",
+ "for i in range(num_samples_to_plot):\n",
+ " plt.figure(figsize=(20, 20))\n",
+ " data, target = emnist_lines[i]\n",
+ " sentence = convert_y_label_to_string(target.numpy()) \n",
+ " print(sentence)\n",
+ " plt.title(sentence)\n",
+ " plt.imshow(data.squeeze(0), cmap='gray')\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(tensor([[[0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0078, 0.0157, 0.0157, 0.0157, 0.0157, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0118, 0.1333,\n",
+ " 0.3020, 0.4902, 0.4980, 0.4902, 0.4431, 0.1294, 0.0039, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0039, 0.0863, 0.3725,\n",
+ " 0.6235, 0.8431, 0.8510, 0.8431, 0.7922, 0.3529, 0.0314, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0118, 0.0314, 0.1843, 0.6235, 0.9098,\n",
+ " 0.9686, 0.9961, 0.9961, 0.9961, 0.9922, 0.8549, 0.3098, 0.0118,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0314, 0.3098, 0.4941, 0.8157, 0.9569, 0.9137,\n",
+ " 0.8706, 0.8863, 0.9804, 0.9961, 0.9961, 0.9843, 0.6667, 0.0824,\n",
+ " 0.0078, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0039, 0.1373, 0.6235, 0.8118, 0.9569, 0.9098, 0.6824,\n",
+ " 0.5804, 0.6784, 0.9451, 0.9961, 0.9961, 0.9961, 0.7961, 0.1255,\n",
+ " 0.0157, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0039,\n",
+ " 0.0275, 0.1843, 0.6431, 0.9608, 0.9686, 0.8118, 0.3725, 0.1765,\n",
+ " 0.3451, 0.8275, 0.9804, 0.9961, 1.0000, 0.9961, 0.8510, 0.1451,\n",
+ " 0.0157, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.1294,\n",
+ " 0.3529, 0.8118, 0.9647, 0.9059, 0.7647, 0.2314, 0.0353, 0.3216,\n",
+ " 0.6667, 0.9843, 0.9843, 0.9882, 0.9961, 0.9961, 0.8706, 0.2039,\n",
+ " 0.0431, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0392, 0.4980,\n",
+ " 0.8118, 0.9804, 0.8549, 0.3725, 0.1843, 0.0196, 0.0157, 0.4392,\n",
+ " 0.7922, 0.9216, 0.5804, 0.7490, 0.9216, 0.9843, 0.9647, 0.6235,\n",
+ " 0.3098, 0.0118, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0039, 0.1412, 0.6863,\n",
+ " 0.9098, 0.9176, 0.6235, 0.1412, 0.0392, 0.0000, 0.0078, 0.3216,\n",
+ " 0.6745, 0.8627, 0.2863, 0.5686, 0.8431, 0.8902, 0.9647, 0.8118,\n",
+ " 0.4941, 0.0314, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0039, 0.1373, 0.6392, 0.9569,\n",
+ " 0.9529, 0.5137, 0.0902, 0.0039, 0.0000, 0.0000, 0.0000, 0.1294,\n",
+ " 0.4314, 0.7098, 0.1412, 0.3686, 0.4980, 0.2667, 0.6980, 0.9490,\n",
+ " 0.7961, 0.1255, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0275, 0.1294, 0.6392, 0.9608, 0.8667,\n",
+ " 0.6392, 0.1294, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0196,\n",
+ " 0.0706, 0.1216, 0.0235, 0.0510, 0.0549, 0.0275, 0.5098, 0.9608,\n",
+ " 0.8471, 0.1451, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0784, 0.3020, 0.8549, 0.9843, 0.6941,\n",
+ " 0.3765, 0.0314, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0078, 0.0118, 0.0000, 0.0039, 0.0039, 0.0431, 0.5529, 0.9647,\n",
+ " 0.8510, 0.1451, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.1490, 0.4980, 0.9765, 0.9529, 0.4510,\n",
+ " 0.1333, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0118, 0.3098, 0.8627, 0.9490,\n",
+ " 0.7922, 0.1255, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0275, 0.3725, 0.6941, 0.9765, 0.6863, 0.1333,\n",
+ " 0.0275, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0784, 0.1843, 0.6902, 0.9490, 0.6392,\n",
+ " 0.3529, 0.0275, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0784, 0.6235, 0.8627, 0.9608, 0.5020, 0.0392,\n",
+ " 0.0039, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0157, 0.2627, 0.4824, 0.8588, 0.8549, 0.3569,\n",
+ " 0.1373, 0.0039, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.1451, 0.8431, 0.9765, 0.8706, 0.2000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0039, 0.0863, 0.3294, 0.7333, 0.8980, 0.7333, 0.3098, 0.0314,\n",
+ " 0.0039, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.1451, 0.8510, 0.9804, 0.8510, 0.1529, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0118, 0.0863,\n",
+ " 0.1843, 0.6235, 0.9059, 0.9490, 0.8549, 0.3098, 0.0157, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.1451, 0.8431, 0.9765, 0.9176, 0.3765, 0.0431,\n",
+ " 0.0196, 0.0157, 0.0157, 0.0314, 0.0627, 0.1059, 0.3255, 0.6706,\n",
+ " 0.8157, 0.9333, 0.8627, 0.6196, 0.3529, 0.0314, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.1255, 0.7922, 0.9529, 0.9686, 0.6431, 0.2039,\n",
+ " 0.1529, 0.1451, 0.1451, 0.1922, 0.2745, 0.3725, 0.6706, 0.9020,\n",
+ " 0.9333, 0.8157, 0.5451, 0.3020, 0.1294, 0.0039, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0275, 0.3725, 0.6824, 0.9725, 0.9647, 0.8706,\n",
+ " 0.8510, 0.8510, 0.8510, 0.8667, 0.8941, 0.9137, 0.9020, 0.7922,\n",
+ " 0.6235, 0.1843, 0.0353, 0.0078, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0784, 0.2549, 0.5412, 0.8000, 0.9137,\n",
+ " 0.9608, 0.9608, 0.8667, 0.8431, 0.7961, 0.5451, 0.3216, 0.1333,\n",
+ " 0.0784, 0.0039, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0078, 0.0353, 0.1333, 0.3216,\n",
+ " 0.4471, 0.4471, 0.2000, 0.1451, 0.1255, 0.0353, 0.0078, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0157, 0.0824,\n",
+ " 0.1255, 0.1255, 0.0353, 0.0157, 0.0157, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000],\n",
+ " [0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000,\n",
+ " 0.0000, 0.0000, 0.0000, 0.0000]]]),\n",
+ " tensor(0))"
+ ]
+ },
+ "execution_count": 44,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "emnist_train[0]"
+ ]
+ },
+ {
+ "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/notebooks/tqdm.ipynb b/src/notebooks/tqdm.ipynb
deleted file mode 100644
index 4b55d9b..0000000
--- a/src/notebooks/tqdm.ipynb
+++ /dev/null
@@ -1,280 +0,0 @@
-{
- "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__:<module>: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
index a773f36..b733a53 100644
--- a/src/text_recognizer/character_predictor.py
+++ b/src/text_recognizer/character_predictor.py
@@ -11,10 +11,9 @@ from text_recognizer.util import read_image
class CharacterPredictor:
"""Recognizes the character in handwritten character images."""
- def __init__(self, network_fn: Type[nn.Module], network_args: Dict) -> None:
+ def __init__(self, network_fn: Type[nn.Module]) -> None:
"""Intializes the CharacterModel and load the pretrained weights."""
- self.model = CharacterModel(network_fn=network_fn, network_args=network_args)
- self.model.load_weights()
+ self.model = CharacterModel(network_fn=network_fn)
self.model.eval()
def predict(self, image_or_filename: Union[np.ndarray, str]) -> Tuple[str, float]:
diff --git a/src/text_recognizer/datasets/__init__.py b/src/text_recognizer/datasets/__init__.py
index 795be90..bfa6a02 100644
--- a/src/text_recognizer/datasets/__init__.py
+++ b/src/text_recognizer/datasets/__init__.py
@@ -1,4 +1,24 @@
"""Dataset modules."""
-from .emnist_dataset import EmnistDataLoader
+from .emnist_dataset import (
+ DATA_DIRNAME,
+ EmnistDataLoaders,
+ EmnistDataset,
+)
+from .emnist_lines_dataset import (
+ construct_image_from_string,
+ EmnistLinesDataset,
+ get_samples_by_character,
+)
+from .sentence_generator import SentenceGenerator
+from .util import Transpose
-__all__ = ["EmnistDataLoader"]
+__all__ = [
+ "construct_image_from_string",
+ "DATA_DIRNAME",
+ "EmnistDataset",
+ "EmnistDataLoaders",
+ "EmnistLinesDataset",
+ "get_samples_by_character",
+ "SentenceGenerator",
+ "Transpose",
+]
diff --git a/src/text_recognizer/datasets/emnist_dataset.py b/src/text_recognizer/datasets/emnist_dataset.py
index b92b57d..525df95 100644
--- a/src/text_recognizer/datasets/emnist_dataset.py
+++ b/src/text_recognizer/datasets/emnist_dataset.py
@@ -1,29 +1,23 @@
-"""Fetches a PyTorch DataLoader with the EMNIST dataset."""
+"""Emnist dataset: black and white images of handwritten characters (Aa-Zz) and digits (0-9)."""
import json
from pathlib import Path
-from typing import Callable, Dict, List, Optional, Type
+from typing import Callable, Dict, List, Optional, Tuple, Type, Union
from loguru import logger
import numpy as np
from PIL import Image
-from torch.utils.data import DataLoader
+import torch
+from torch.utils.data import DataLoader, Dataset
from torchvision.datasets import EMNIST
-from torchvision.transforms import Compose, ToTensor
+from torchvision.transforms import Compose, Normalize, ToTensor
+from text_recognizer.datasets.util import Transpose
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: type = EMNIST) -> None:
"""Extract and saves EMNIST essentials."""
labels = emnsit_dataset.classes
@@ -45,14 +39,187 @@ def download_emnist() -> None:
save_emnist_essentials(dataset)
-def load_emnist_mapping() -> Dict[int, str]:
+def _load_emnist_essentials() -> Dict:
"""Load the EMNIST mapping."""
with open(str(ESSENTIALS_FILENAME)) as f:
essentials = json.load(f)
- return dict(essentials["mapping"])
+ return essentials
+
+
+def _augment_emnist_mapping(mapping: Dict) -> Dict:
+ """Augment the mapping with extra symbols."""
+ # Extra symbols in IAM dataset
+ extra_symbols = [
+ " ",
+ "!",
+ '"',
+ "#",
+ "&",
+ "'",
+ "(",
+ ")",
+ "*",
+ "+",
+ ",",
+ "-",
+ ".",
+ "/",
+ ":",
+ ";",
+ "?",
+ ]
+
+ # padding symbol
+ extra_symbols.append("_")
+
+ max_key = max(mapping.keys())
+ extra_mapping = {}
+ for i, symbol in enumerate(extra_symbols):
+ extra_mapping[max_key + 1 + i] = symbol
+
+ return {**mapping, **extra_mapping}
+
+
+class EmnistDataset(Dataset):
+ """This is a class for resampling and subsampling the PyTorch EMNIST dataset."""
+
+ def __init__(
+ self,
+ train: bool = False,
+ sample_to_balance: bool = False,
+ subsample_fraction: float = None,
+ transform: Optional[Callable] = None,
+ target_transform: Optional[Callable] = None,
+ seed: int = 4711,
+ ) -> None:
+ """Loads the dataset and the mappings.
+
+ Args:
+ train (bool): If True, loads the training set, otherwise the validation set is loaded. Defaults to
+ False.
+ sample_to_balance (bool): Resamples the dataset to make it balanced. Defaults to False.
+ subsample_fraction (float): Description of parameter `subsample_fraction`. Defaults to None.
+ transform (Optional[Callable]): Transform(s) for input data. Defaults to None.
+ target_transform (Optional[Callable]): Transform(s) for output data. Defaults to None.
+ seed (int): Seed number. Defaults to 4711.
+
+ Raises:
+ ValueError: If subsample_fraction is not None and outside the range (0, 1).
+
+ """
+
+ self.train = train
+ self.sample_to_balance = sample_to_balance
+ if subsample_fraction is not None:
+ if not 0.0 < subsample_fraction < 1.0:
+ raise ValueError("The subsample fraction must be in (0, 1).")
+ self.subsample_fraction = subsample_fraction
+ self.transform = transform
+ if self.transform is None:
+ self.transform = Compose([Transpose(), ToTensor()])
+
+ self.target_transform = target_transform
+ self.seed = seed
+
+ # Load dataset infromation.
+ essentials = _load_emnist_essentials()
+ self.mapping = _augment_emnist_mapping(dict(essentials["mapping"]))
+ self.inverse_mapping = {v: k for k, v in self.mapping.items()}
+ self.num_classes = len(self.mapping)
+ self.input_shape = essentials["input_shape"]
+
+ # Placeholders
+ self.data = None
+ self.targets = None
+
+ def __len__(self) -> int:
+ """Returns the length of the dataset."""
+ return len(self.data)
+
+ def __getitem__(
+ self, index: Union[int, torch.Tensor]
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
+ """Fetches samples from the dataset.
+
+ Args:
+ index (Union[int, torch.Tensor]): The indices of the samples to fetch.
+
+ Returns:
+ Tuple[torch.Tensor, torch.Tensor]: Data target tuple.
+
+ """
+ if torch.is_tensor(index):
+ index = index.tolist()
+
+ data = self.data[index]
+ targets = self.targets[index]
+
+ if self.transform:
+ data = self.transform(data)
+
+ if self.target_transform:
+ targets = self.target_transform(targets)
+
+ return data, targets
+
+ def __repr__(self) -> str:
+ """Returns information about the dataset."""
+ return (
+ "EMNIST Dataset\n"
+ f"Num classes: {self.num_classes}\n"
+ f"Mapping: {self.mapping}\n"
+ f"Input shape: {self.input_shape}\n"
+ )
+
+ def _sample_to_balance(self) -> None:
+ """Because the dataset is not balanced, we take at most the mean number of instances per class."""
+ np.random.seed(self.seed)
+ x = self.data
+ y = self.targets
+ num_to_sample = int(np.bincount(y.flatten()).mean())
+ all_sampled_indices = []
+ for label in np.unique(y.flatten()):
+ inds = np.where(y == label)[0]
+ sampled_indices = np.unique(np.random.choice(inds, num_to_sample))
+ all_sampled_indices.append(sampled_indices)
+ indices = np.concatenate(all_sampled_indices)
+ x_sampled = x[indices]
+ y_sampled = y[indices]
+ self.data = x_sampled
+ self.targets = y_sampled
+
+ def _subsample(self) -> None:
+ """Subsamples the dataset to the specified fraction."""
+ x = self.data
+ y = self.targets
+ num_samples = int(x.shape[0] * self.subsample_fraction)
+ x_sampled = x[:num_samples]
+ y_sampled = y[:num_samples]
+ self.data = x_sampled
+ self.targets = y_sampled
+
+ def load_emnist_dataset(self) -> None:
+ """Fetch the EMNIST dataset."""
+ dataset = EMNIST(
+ root=DATA_DIRNAME,
+ split="byclass",
+ train=self.train,
+ download=False,
+ transform=None,
+ target_transform=None,
+ )
+
+ self.data = dataset.data
+ self.targets = dataset.targets
+
+ if self.sample_to_balance:
+ self._sample_to_balance()
+
+ if self.subsample_fraction is not None:
+ self._subsample()
-class EmnistDataLoader:
+class EmnistDataLoaders:
"""Class for Emnist DataLoaders."""
def __init__(
@@ -68,7 +235,7 @@ class EmnistDataLoader:
cuda: bool = True,
seed: int = 4711,
) -> None:
- """Fetches DataLoaders.
+ """Fetches DataLoaders for given split(s).
Args:
splits (List[str]): One or both of the dataset splits "train" and "val".
@@ -88,13 +255,17 @@ class EmnistDataLoader:
them. Defaults to True.
seed (int): Seed for sampling.
+ Raises:
+ ValueError: If subsample_fraction is not None and outside the range (0, 1).
+
"""
self.splits = splits
self.sample_to_balance = sample_to_balance
+
if subsample_fraction is not None:
- assert (
- 0.0 < subsample_fraction < 1.0
- ), " The subsample fraction must be in (0, 1)."
+ if not 0.0 < subsample_fraction < 1.0:
+ raise ValueError("The subsample fraction must be in (0, 1).")
+
self.subsample_fraction = subsample_fraction
self.transform = transform
self.target_transform = target_transform
@@ -105,6 +276,10 @@ class EmnistDataLoader:
self.seed = seed
self._data_loaders = self._fetch_emnist_data_loaders()
+ def __repr__(self) -> str:
+ """Returns information about the dataset."""
+ return self._data_loaders[self.splits[0]].dataset.__repr__()
+
@property
def __name__(self) -> str:
"""Returns the name of the dataset."""
@@ -128,59 +303,6 @@ class EmnistDataLoader:
except KeyError:
raise ValueError(f"Split {split} does not exist.")
- def _sample_to_balance(self, dataset: type = EMNIST) -> EMNIST:
- """Because the dataset is not balanced, we take at most the mean number of instances per class."""
- np.random.seed(self.seed)
- x = dataset.data
- y = dataset.targets
- num_to_sample = int(np.bincount(y.flatten()).mean())
- all_sampled_indices = []
- for label in np.unique(y.flatten()):
- inds = np.where(y == label)[0]
- sampled_indices = np.unique(np.random.choice(inds, num_to_sample))
- all_sampled_indices.append(sampled_indices)
- indices = np.concatenate(all_sampled_indices)
- x_sampled = x[indices]
- y_sampled = y[indices]
- dataset.data = x_sampled
- dataset.targets = y_sampled
-
- return dataset
-
- def _subsample(self, dataset: type = EMNIST) -> EMNIST:
- """Subsamples the dataset to the specified fraction."""
- x = dataset.data
- y = dataset.targets
- num_samples = int(x.shape[0] * self.subsample_fraction)
- x_sampled = x[:num_samples]
- y_sampled = y[:num_samples]
- dataset.data = x_sampled
- dataset.targets = y_sampled
-
- return dataset
-
- def _fetch_emnist_dataset(self, train: bool) -> EMNIST:
- """Fetch the EMNIST dataset."""
- if self.transform is None:
- transform = Compose([Transpose(), ToTensor()])
-
- dataset = EMNIST(
- root=DATA_DIRNAME,
- split="byclass",
- train=train,
- download=False,
- transform=transform,
- target_transform=self.target_transform,
- )
-
- if self.sample_to_balance:
- dataset = self._sample_to_balance(dataset)
-
- if self.subsample_fraction is not None:
- dataset = self._subsample(dataset)
-
- return dataset
-
def _fetch_emnist_data_loaders(self) -> Dict[str, DataLoader]:
"""Fetches the EMNIST dataset and return a Dict of PyTorch DataLoaders."""
data_loaders = {}
@@ -193,10 +315,19 @@ class EmnistDataLoader:
else:
train = False
- dataset = self._fetch_emnist_dataset(train)
+ emnist_dataset = EmnistDataset(
+ train=train,
+ sample_to_balance=self.sample_to_balance,
+ subsample_fraction=self.subsample_fraction,
+ transform=self.transform,
+ target_transform=self.target_transform,
+ seed=self.seed,
+ )
+
+ emnist_dataset.load_emnist_dataset()
data_loader = DataLoader(
- dataset=dataset,
+ dataset=emnist_dataset,
batch_size=self.batch_size,
shuffle=self.shuffle,
num_workers=self.num_workers,
diff --git a/src/text_recognizer/datasets/emnist_lines_dataset.py b/src/text_recognizer/datasets/emnist_lines_dataset.py
new file mode 100644
index 0000000..d49319f
--- /dev/null
+++ b/src/text_recognizer/datasets/emnist_lines_dataset.py
@@ -0,0 +1,326 @@
+"""Emnist Lines dataset: synthetic handwritten lines dataset made from Emnist characters."""
+
+from collections import defaultdict
+from pathlib import Path
+from typing import Callable, Dict, List, Optional, Tuple, Union
+
+import h5py
+from loguru import logger
+import numpy as np
+import torch
+from torch.utils.data import Dataset
+from torchvision.transforms import Compose, Normalize, ToTensor
+
+from text_recognizer.datasets import DATA_DIRNAME, EmnistDataset, SentenceGenerator
+from text_recognizer.datasets.util import Transpose
+
+DATA_DIRNAME = DATA_DIRNAME / "processed" / "emnist_lines"
+ESSENTIALS_FILENAME = (
+ Path(__file__).resolve().parents[0] / "emnist_lines_essentials.json"
+)
+
+
+class EmnistLinesDataset(Dataset):
+ """Synthetic dataset of lines from the Brown corpus with Emnist characters."""
+
+ def __init__(
+ self,
+ emnist: EmnistDataset,
+ train: bool = False,
+ transform: Optional[Callable] = None,
+ target_transform: Optional[Callable] = None,
+ max_length: int = 34,
+ min_overlap: float = 0,
+ max_overlap: float = 0.33,
+ num_samples: int = 10000,
+ seed: int = 4711,
+ ) -> None:
+ """Short summary.
+
+ Args:
+ emnist (EmnistDataset): A EmnistDataset object.
+ train (bool): Flag for the filename. Defaults to False.
+ transform (Optional[Callable]): The transform of the data. Defaults to None.
+ target_transform (Optional[Callable]): The transform of the target. Defaults to None.
+ max_length (int): The maximum number of characters. Defaults to 34.
+ min_overlap (float): The minimum overlap between concatenated images. Defaults to 0.
+ max_overlap (float): The maximum overlap between concatenated images. Defaults to 0.33.
+ num_samples (int): Number of samples to generate. Defaults to 10000.
+ seed (int): Seed number. Defaults to 4711.
+
+ """
+ self.train = train
+ self.emnist = emnist
+
+ self.transform = transform
+ if self.transform is None:
+ self.transform = Compose([ToTensor()])
+
+ self.target_transform = target_transform
+ if self.target_transform is None:
+ self.target_transform = torch.tensor
+
+ self.mapping = self.emnist.mapping
+ self.num_classes = self.emnist.num_classes
+ self.max_length = max_length
+ self.min_overlap = min_overlap
+ self.max_overlap = max_overlap
+ self.num_samples = num_samples
+ self.input_shape = (
+ self.emnist.input_shape[0],
+ self.emnist.input_shape[1] * self.max_length,
+ )
+ self.output_shape = (self.max_length, self.num_classes)
+ self.seed = seed
+
+ # Placeholders for the generated dataset.
+ self.data = None
+ self.target = None
+
+ def __len__(self) -> int:
+ """Returns the length of the dataset."""
+ return len(self.data)
+
+ def __getitem__(
+ self, index: Union[int, torch.Tensor]
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
+ """Fetches data, target pair of the dataset for a given and index or indices.
+
+ Args:
+ index (Union[int, torch.Tensor]): Either a list or int of indices/index.
+
+ Returns:
+ Tuple[torch.Tensor, torch.Tensor]: Data target pair.
+
+ """
+ if torch.is_tensor(index):
+ index = index.tolist()
+
+ # data = np.array([self.data[index]])
+ data = self.data[index]
+ targets = self.targets[index]
+
+ if self.transform:
+ data = self.transform(data)
+
+ if self.target_transform:
+ targets = self.target_transform(targets)
+
+ return data, targets
+
+ def __repr__(self) -> str:
+ """Returns information about the dataset."""
+ return (
+ "EMNIST Lines Dataset\n" # pylint: disable=no-member
+ f"Max length: {self.max_length}\n"
+ f"Min overlap: {self.min_overlap}\n"
+ f"Max overlap: {self.max_overlap}\n"
+ f"Num classes: {self.num_classes}\n"
+ f"Input shape: {self.input_shape}\n"
+ f"Data: {self.data.shape}\n"
+ f"Tagets: {self.targets.shape}\n"
+ )
+
+ @property
+ def data_filename(self) -> Path:
+ """Path to the h5 file."""
+ filename = f"ml_{self.max_length}_o{self.min_overlap}_{self.max_overlap}_n{self.num_samples}.pt"
+ if self.train:
+ filename = "train_" + filename
+ else:
+ filename = "val_" + filename
+ return DATA_DIRNAME / filename
+
+ def _load_or_generate_data(self) -> None:
+ """Loads the dataset, if it does not exist a new dataset is generated before loading it."""
+ np.random.seed(self.seed)
+
+ if not self.data_filename.exists():
+ self._generate_data()
+ self._load_data()
+
+ def _load_data(self) -> None:
+ """Loads the dataset from the h5 file."""
+ logger.debug("EmnistLinesDataset loading data from HDF5...")
+ with h5py.File(self.data_filename, "r") as f:
+ self.data = f["data"][:]
+ self.targets = f["targets"][:]
+
+ def _generate_data(self) -> str:
+ """Generates a dataset with the Brown corpus and Emnist characters."""
+ logger.debug("Generating data...")
+
+ sentence_generator = SentenceGenerator(self.max_length)
+
+ # Load emnist dataset.
+ self.emnist.load_emnist_dataset()
+ samples_by_character = get_samples_by_character(
+ self.emnist.data.numpy(), self.emnist.targets.numpy(), self.emnist.mapping,
+ )
+
+ DATA_DIRNAME.mkdir(parents=True, exist_ok=True)
+ with h5py.File(self.data_filename, "a") as f:
+ data, targets = create_dataset_of_images(
+ self.num_samples,
+ samples_by_character,
+ sentence_generator,
+ self.min_overlap,
+ self.max_overlap,
+ )
+
+ targets = convert_strings_to_categorical_labels(
+ targets, self.emnist.inverse_mapping
+ )
+
+ f.create_dataset("data", data=data, dtype="u1", compression="lzf")
+ f.create_dataset("targets", data=targets, dtype="u1", compression="lzf")
+
+
+def get_samples_by_character(
+ samples: np.ndarray, labels: np.ndarray, mapping: Dict
+) -> defaultdict:
+ """Creates a dictionary with character as key and value as the list of images of that character.
+
+ Args:
+ samples (np.ndarray): Dataset of images of characters.
+ labels (np.ndarray): The labels for each image.
+ mapping (Dict): The Emnist mapping dictionary.
+
+ Returns:
+ defaultdict: A dictionary with characters as keys and list of images as values.
+
+ """
+ samples_by_character = defaultdict(list)
+ for sample, label in zip(samples, labels.flatten()):
+ samples_by_character[mapping[label]].append(sample)
+ return samples_by_character
+
+
+def select_letter_samples_for_string(
+ string: str, samples_by_character: Dict
+) -> List[np.ndarray]:
+ """Randomly selects Emnist characters to use for the senetence.
+
+ Args:
+ string (str): The word or sentence.
+ samples_by_character (Dict): The dictionary of emnist images of each character.
+
+ Returns:
+ List[np.ndarray]: A list of emnist images of the string.
+
+ """
+ zero_image = np.zeros((28, 28), np.uint8)
+ sample_image_by_character = {}
+ for character in string:
+ if character in sample_image_by_character:
+ continue
+ samples = samples_by_character[character]
+ sample = samples[np.random.choice(len(samples))] if samples else zero_image
+ sample_image_by_character[character] = sample.reshape(28, 28).swapaxes(0, 1)
+ return [sample_image_by_character[character] for character in string]
+
+
+def construct_image_from_string(
+ string: str, samples_by_character: Dict, min_overlap: float, max_overlap: float
+) -> np.ndarray:
+ """Concatenates images of the characters in the string.
+
+ The concatination is made with randomly selected overlap so that some portion of the character will overlap.
+
+ Args:
+ string (str): The word or sentence.
+ samples_by_character (Dict): The dictionary of emnist images of each character.
+ min_overlap (float): Minimum amount of overlap between Emnist images.
+ max_overlap (float): Maximum amount of overlap between Emnist images.
+
+ Returns:
+ np.ndarray: The Emnist image of the string.
+
+ """
+ overlap = np.random.uniform(min_overlap, max_overlap)
+ sampled_images = select_letter_samples_for_string(string, samples_by_character)
+ length = len(sampled_images)
+ height, width = sampled_images[0].shape
+ next_overlap_width = width - int(overlap * width)
+ concatenated_image = np.zeros((height, width * length), np.uint8)
+ x = 0
+ for image in sampled_images:
+ concatenated_image[:, x : (x + width)] += image
+ x += next_overlap_width
+ return np.minimum(255, concatenated_image)
+
+
+def create_dataset_of_images(
+ length: int,
+ samples_by_character: Dict,
+ sentence_generator: SentenceGenerator,
+ min_overlap: float,
+ max_overlap: float,
+) -> Tuple[np.ndarray, List[str]]:
+ """Creates a dataset with images and labels from strings generated from the SentenceGenerator.
+
+ Args:
+ length (int): The number of characters for each string.
+ samples_by_character (Dict): The dictionary of emnist images of each character.
+ sentence_generator (SentenceGenerator): A SentenceGenerator objest.
+ min_overlap (float): Minimum amount of overlap between Emnist images.
+ max_overlap (float): Maximum amount of overlap between Emnist images.
+
+ Returns:
+ Tuple[np.ndarray, List[str]]: A list of Emnist images and a list of the strings (labels).
+
+ Raises:
+ RuntimeError: If the sentence generator is not able to generate a string.
+
+ """
+ sample_label = sentence_generator.generate()
+ sample_image = construct_image_from_string(sample_label, samples_by_character, 0, 0)
+ images = np.zeros((length, sample_image.shape[0], sample_image.shape[1]), np.uint8)
+ labels = []
+ for n in range(length):
+ label = None
+ # Try several times to generate before actually throwing an error.
+ for _ in range(10):
+ try:
+ label = sentence_generator.generate()
+ break
+ except Exception: # pylint: disable=broad-except
+ pass
+ if label is None:
+ raise RuntimeError("Was not able to generate a valid string.")
+ images[n] = construct_image_from_string(
+ label, samples_by_character, min_overlap, max_overlap
+ )
+ labels.append(label)
+ return images, labels
+
+
+def convert_strings_to_categorical_labels(
+ labels: List[str], mapping: Dict
+) -> np.ndarray:
+ """Translates a string of characters in to a target array of class int."""
+ return np.array([[mapping[c] for c in label] for label in labels])
+
+
+def create_datasets(
+ max_length: int = 34,
+ min_overlap: float = 0,
+ max_overlap: float = 0.33,
+ num_train: int = 10000,
+ num_val: int = 1000,
+) -> None:
+ """Creates a training an validation dataset of Emnist lines."""
+ emnist_train = EmnistDataset(train=True, sample_to_balance=True)
+ emnist_val = EmnistDataset(train=False, sample_to_balance=True)
+ datasets = [emnist_train, emnist_val]
+ num_samples = [num_train, num_val]
+ for num, train, dataset in zip(num_samples, [True, False], datasets):
+ emnist_lines = EmnistLinesDataset(
+ train=train,
+ emnist=dataset,
+ max_length=max_length,
+ min_overlap=min_overlap,
+ max_overlap=max_overlap,
+ num_samples=num,
+ )
+ emnist_lines._load_or_generate_data()
diff --git a/src/text_recognizer/datasets/sentence_generator.py b/src/text_recognizer/datasets/sentence_generator.py
new file mode 100644
index 0000000..ee86bd4
--- /dev/null
+++ b/src/text_recognizer/datasets/sentence_generator.py
@@ -0,0 +1,81 @@
+"""Downloading the Brown corpus with NLTK for sentence generating."""
+
+import itertools
+import re
+import string
+from typing import Optional
+
+import nltk
+from nltk.corpus.reader.util import ConcatenatedCorpusView
+import numpy as np
+
+from text_recognizer.datasets import DATA_DIRNAME
+
+NLTK_DATA_DIRNAME = DATA_DIRNAME / "raw" / "nltk"
+
+
+class SentenceGenerator:
+ """Generates text sentences using the Brown corpus."""
+
+ def __init__(self, max_length: Optional[int] = None) -> None:
+ """Loads the corpus and sets word start indices."""
+ self.corpus = brown_corpus()
+ self.word_start_indices = [0] + [
+ _.start(0) + 1 for _ in re.finditer(" ", self.corpus)
+ ]
+ self.max_length = max_length
+
+ def generate(self, max_length: Optional[int] = None) -> str:
+ """Generates a word or sentences from the Brown corpus.
+
+ Sample a string from the Brown corpus of length at least one word and at most max_length, padding to
+ max_length with the '_' characters if sentence is shorter.
+
+ Args:
+ max_length (Optional[int]): The maximum number of characters in the sentence. Defaults to None.
+
+ Returns:
+ str: A sentence from the Brown corpus.
+
+ Raises:
+ ValueError: If max_length was not specified at initialization and not given as an argument.
+
+ """
+ if max_length is None:
+ max_length = self.max_length
+ if max_length is None:
+ raise ValueError(
+ "Must provide max_length to this method or when making this object."
+ )
+
+ index = np.random.randint(0, len(self.word_start_indices) - 1)
+ start_index = self.word_start_indices[index]
+ end_index_candidates = []
+ for index in range(index + 1, len(self.word_start_indices)):
+ if self.word_start_indices[index] - start_index > max_length:
+ break
+ end_index_candidates.append(self.word_start_indices[index])
+ end_index = np.random.choice(end_index_candidates)
+ sampled_text = self.corpus[start_index:end_index].strip()
+ padding = "_" * (max_length - len(sampled_text))
+ return sampled_text + padding
+
+
+def brown_corpus() -> str:
+ """Returns a single string with the Brown corpus with all punctuations stripped."""
+ sentences = load_nltk_brown_corpus()
+ corpus = " ".join(itertools.chain.from_iterable(sentences))
+ corpus = corpus.translate({ord(c): None for c in string.punctuation})
+ corpus = re.sub(" +", " ", corpus)
+ return corpus
+
+
+def load_nltk_brown_corpus() -> ConcatenatedCorpusView:
+ """Load the Brown corpus using the NLTK library."""
+ nltk.data.path.append(NLTK_DATA_DIRNAME)
+ try:
+ nltk.corpus.brown.sents()
+ except LookupError:
+ NLTK_DATA_DIRNAME.mkdir(parents=True, exist_ok=True)
+ nltk.download("brown", download_dir=NLTK_DATA_DIRNAME)
+ return nltk.corpus.brown.sents()
diff --git a/src/text_recognizer/datasets/util.py b/src/text_recognizer/datasets/util.py
new file mode 100644
index 0000000..6668eef
--- /dev/null
+++ b/src/text_recognizer/datasets/util.py
@@ -0,0 +1,11 @@
+"""Util functions for datasets."""
+import numpy as np
+from PIL import Image
+
+
+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)
diff --git a/src/text_recognizer/models/base.py b/src/text_recognizer/models/base.py
index b78eacb..84a86ca 100644
--- a/src/text_recognizer/models/base.py
+++ b/src/text_recognizer/models/base.py
@@ -22,7 +22,7 @@ class Model(ABC):
def __init__(
self,
network_fn: Type[nn.Module],
- network_args: Dict,
+ network_args: Optional[Dict] = None,
data_loader: Optional[Callable] = None,
data_loader_args: Optional[Dict] = None,
metrics: Optional[Dict] = None,
@@ -38,7 +38,7 @@ class Model(ABC):
Args:
network_fn (Type[nn.Module]): The PyTorch network.
- network_args (Dict): Arguments for the network.
+ network_args (Optional[Dict]): Arguments for the network. Defaults to None.
data_loader (Optional[Callable]): A function that fetches train and val DataLoader.
data_loader_args (Optional[Dict]): Arguments for the DataLoader.
metrics (Optional[Dict]): Metrics to evaluate the performance with. Defaults to None.
@@ -58,18 +58,14 @@ class Model(ABC):
if data_loader_args is not None:
self._data_loaders = data_loader(**data_loader_args)
dataset_name = self._data_loaders.__name__
+ self._mapping = self._data_loaders.mapping
else:
+ self._mapping = None
dataset_name = "*"
self._data_loaders = None
self._name = f"{self.__class__.__name__}_{dataset_name}_{network_fn.__name__}"
- # Extract the input shape for the torchsummary.
- if isinstance(network_args["input_size"], int):
- self._input_shape = (1,) + tuple([network_args["input_size"]])
- else:
- self._input_shape = (1,) + tuple(network_args["input_size"])
-
if metrics is not None:
self._metrics = metrics
@@ -80,8 +76,13 @@ class Model(ABC):
self._device = device
# Load network.
- self.network_args = network_args
- self._network = network_fn(**self.network_args)
+ self._network = None
+ self._network_args = network_args
+ # If no network arguemnts are given, load pretrained weights if they exist.
+ if self._network_args is None:
+ self.load_weights(network_fn)
+ else:
+ self._network = network_fn(**self._network_args)
# To device.
self._network.to(self._device)
@@ -104,8 +105,17 @@ class Model(ABC):
lr_scheduler_args["steps_per_epoch"] = len(self._data_loaders("train"))
self._lr_scheduler = lr_scheduler(self._optimizer, **lr_scheduler_args)
- # Class mapping.
- self._mapping = None
+ # Extract the input shape for the torchsummary.
+ if isinstance(self._network_args["input_size"], int):
+ self._input_shape = (1,) + tuple([self._network_args["input_size"]])
+ else:
+ self._input_shape = (1,) + tuple(self._network_args["input_size"])
+
+ # Experiment directory.
+ self.model_dir = None
+
+ # Flag for stopping training.
+ self.stop_training = False
@property
def __name__(self) -> str:
@@ -179,8 +189,13 @@ class Model(ABC):
def _get_state_dict(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()
+
+ if self._lr_scheduler is not None:
+ state["scheduler_state"] = self._lr_scheduler.state_dict()
+
return state
def load_checkpoint(self, path: Path) -> int:
@@ -203,54 +218,63 @@ class Model(ABC):
if self._optimizer is not None:
self._optimizer.load_state_dict(checkpoint["optimizer_state"])
+ if self._lr_scheduler is not None:
+ self._lr_scheduler.load_state_dict(checkpoint["scheduler_state"])
+
epoch = checkpoint["epoch"]
return epoch
- def save_checkpoint(
- self, path: Path, is_best: bool, epoch: int, val_metric: str
- ) -> None:
+ def save_checkpoint(self, 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.
+ Raises:
+ ValueError: If the self.model_dir is not set.
+
"""
state = self._get_state_dict()
state["is_best"] = is_best
state["epoch"] = epoch
- state["network_args"] = self.network_args
+ state["network_args"] = self._network_args
- path.mkdir(parents=True, exist_ok=True)
+ if self.model_dir is None:
+ raise ValueError("Experiment directory is not set.")
+
+ self.model_dir.mkdir(parents=True, exist_ok=True)
logger.debug("Saving checkpoint...")
- filepath = str(path / "last.pt")
+ filepath = str(self.model_dir / "last.pt")
torch.save(state, filepath)
if is_best:
logger.debug(
f"Found a new best {val_metric}. Saving best checkpoint and weights."
)
- shutil.copyfile(filepath, str(path / "best.pt"))
+ shutil.copyfile(filepath, str(self.model_dir / "best.pt"))
- def load_weights(self) -> None:
+ def load_weights(self, network_fn: Type[nn.Module]) -> None:
"""Load the network weights."""
- logger.debug("Loading network weights.")
+ logger.debug("Loading network with pretrained weights.")
filename = glob(self.weights_filename)[0]
- weights = torch.load(filename, map_location=torch.device(self._device))[
- "model_state"
- ]
+ if not filename:
+ raise FileNotFoundError(
+ f"Could not find any pretrained weights at {self.weights_filename}"
+ )
+ # Loading state directory.
+ state_dict = torch.load(filename, map_location=torch.device(self._device))
+ self._network_args = state_dict["network_args"]
+ weights = state_dict["model_state"]
+
+ # Initializes the network with trained weights.
+ self._network = network_fn(**self._network_args)
self._network.load_state_dict(weights)
def save_weights(self, path: Path) -> None:
"""Save the network weights."""
logger.debug("Saving the best network weights.")
shutil.copyfile(str(path / "best.pt"), self.weights_filename)
-
- @abstractmethod
- def load_mapping(self) -> None:
- """Loads class mapping from network output to character."""
- ...
diff --git a/src/text_recognizer/models/character_model.py b/src/text_recognizer/models/character_model.py
index 527fc7d..f1dabb7 100644
--- a/src/text_recognizer/models/character_model.py
+++ b/src/text_recognizer/models/character_model.py
@@ -1,12 +1,15 @@
"""Defines the CharacterModel class."""
-from typing import Callable, Dict, Optional, Tuple, Type
+from typing import Callable, Dict, Optional, Tuple, Type, Union
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.datasets.emnist_dataset import (
+ _augment_emnist_mapping,
+ _load_emnist_essentials,
+)
from text_recognizer.models.base import Model
@@ -16,7 +19,7 @@ class CharacterModel(Model):
def __init__(
self,
network_fn: Type[nn.Module],
- network_args: Dict,
+ network_args: Optional[Dict] = None,
data_loader: Optional[Callable] = None,
data_loader_args: Optional[Dict] = None,
metrics: Optional[Dict] = None,
@@ -44,19 +47,23 @@ class CharacterModel(Model):
lr_scheduler_args,
device,
)
- self.load_mapping()
+ if self.mapping is None:
+ self.load_mapping()
self.tensor_transform = ToTensor()
self.softmax = nn.Softmax(dim=0)
def load_mapping(self) -> None:
"""Mapping between integers and classes."""
- self._mapping = load_emnist_mapping()
+ essentials = _load_emnist_essentials()
+ self._mapping = _augment_emnist_mapping(dict(essentials["mapping"]))
- def predict_on_image(self, image: np.ndarray) -> Tuple[str, float]:
+ def predict_on_image(
+ self, image: Union[np.ndarray, torch.Tensor]
+ ) -> Tuple[str, float]:
"""Character prediction on an image.
Args:
- image (np.ndarray): An image containing a character.
+ image (Union[np.ndarray, torch.Tensor]): An image containing a character.
Returns:
Tuple[str, float]: The predicted character and the confidence in the prediction.
@@ -64,12 +71,15 @@ class CharacterModel(Model):
"""
if image.dtype == np.uint8:
- image = (image / 255).astype(np.float32)
-
- # Conver to Pytorch Tensor.
- image = self.tensor_transform(image)
+ # Converts an image with range [0, 255] with to Pytorch Tensor with range [0, 1].
+ image = self.tensor_transform(image)
+ if image.dtype == torch.uint8:
+ # If the image is an unscaled tensor.
+ image = image.type("torch.FloatTensor") / 255
with torch.no_grad():
+ # Put the image tensor on the device the model weights are on.
+ image = image.to(self.device)
logits = self.network(image)
prediction = self.softmax(logits.data.squeeze())
diff --git a/src/text_recognizer/tests/test_character_predictor.py b/src/text_recognizer/tests/test_character_predictor.py
index c603a3a..01bda78 100644
--- a/src/text_recognizer/tests/test_character_predictor.py
+++ b/src/text_recognizer/tests/test_character_predictor.py
@@ -4,7 +4,6 @@ import os
from pathlib import Path
import unittest
-import click
from loguru import logger
from text_recognizer.character_predictor import CharacterPredictor
@@ -18,19 +17,10 @@ os.environ["CUDA_VISIBLE_DEVICES"] = ""
class TestCharacterPredictor(unittest.TestCase):
"""Tests for the CharacterPredictor class."""
- # @click.command()
- # @click.option(
- # "--network", type=str, help="Network to load, e.g. MLP or LeNet.", default="MLP"
- # )
def test_filename(self) -> None:
"""Test that CharacterPredictor correctly predicts on a single image, for serveral test images."""
- network_module = importlib.import_module("text_recognizer.networks")
- network_fn_ = getattr(network_module, "MLP")
- # network_args = {"input_size": [28, 28], "output_size": 62, "dropout_rate": 0}
- network_args = {"input_size": 784, "output_size": 62, "dropout_rate": 0.2}
- predictor = CharacterPredictor(
- network_fn=network_fn_, network_args=network_args
- )
+ network_fn_ = MLP
+ predictor = CharacterPredictor(network_fn=network_fn_)
for filename in SUPPORT_DIRNAME.glob("*.png"):
pred, conf = predictor.predict(str(filename))
diff --git a/src/text_recognizer/weights/CharacterModel_Emnist_LeNet_weights.pt b/src/text_recognizer/weights/CharacterModel_Emnist_LeNet_weights.pt
index 43a3891..46b1cb1 100644
--- a/src/text_recognizer/weights/CharacterModel_Emnist_LeNet_weights.pt
+++ b/src/text_recognizer/weights/CharacterModel_Emnist_LeNet_weights.pt
Binary files differ
diff --git a/src/text_recognizer/weights/CharacterModel_Emnist_MLP_weights.pt b/src/text_recognizer/weights/CharacterModel_Emnist_MLP_weights.pt
index 0dde787..4ec12c1 100644
--- a/src/text_recognizer/weights/CharacterModel_Emnist_MLP_weights.pt
+++ b/src/text_recognizer/weights/CharacterModel_Emnist_MLP_weights.pt
Binary files differ
diff --git a/src/training/callbacks/__init__.py b/src/training/callbacks/__init__.py
index 868d739..fbcc285 100644
--- a/src/training/callbacks/__init__.py
+++ b/src/training/callbacks/__init__.py
@@ -1 +1,19 @@
-"""TBC."""
+"""The callback modules used in the training script."""
+from .base import Callback, CallbackList, Checkpoint
+from .early_stopping import EarlyStopping
+from .lr_schedulers import CyclicLR, MultiStepLR, OneCycleLR, ReduceLROnPlateau, StepLR
+from .wandb_callbacks import WandbCallback, WandbImageLogger
+
+__all__ = [
+ "Callback",
+ "CallbackList",
+ "Checkpoint",
+ "EarlyStopping",
+ "WandbCallback",
+ "WandbImageLogger",
+ "CyclicLR",
+ "MultiStepLR",
+ "OneCycleLR",
+ "ReduceLROnPlateau",
+ "StepLR",
+]
diff --git a/src/training/callbacks/base.py b/src/training/callbacks/base.py
index d80a1e5..e0d91e6 100644
--- a/src/training/callbacks/base.py
+++ b/src/training/callbacks/base.py
@@ -1,12 +1,33 @@
"""Metaclass for callback functions."""
-from abc import ABC
-from typing import Callable, List, Type
+from enum import Enum
+from typing import Callable, Dict, List, Type, Union
+from loguru import logger
+import numpy as np
+import torch
-class Callback(ABC):
+from text_recognizer.models import Model
+
+
+class ModeKeys:
+ """Mode keys for CallbackList."""
+
+ TRAIN = "train"
+ VALIDATION = "validation"
+
+
+class Callback:
"""Metaclass for callbacks used in training."""
+ def __init__(self) -> None:
+ """Initializes the Callback instance."""
+ self.model = None
+
+ def set_model(self, model: Type[Model]) -> None:
+ """Set the model."""
+ self.model = model
+
def on_fit_begin(self) -> None:
"""Called when fit begins."""
pass
@@ -15,35 +36,27 @@ class Callback(ABC):
"""Called when fit ends."""
pass
- def on_train_epoch_begin(self) -> None:
- """Called at the beginning of an epoch."""
- pass
-
- def on_train_epoch_end(self) -> None:
- """Called at the end of an epoch."""
+ def on_epoch_begin(self, epoch: int, logs: Dict = {}) -> None:
+ """Called at the beginning of an epoch. Only used in training mode."""
pass
- def on_val_epoch_begin(self) -> None:
- """Called at the beginning of an epoch."""
+ def on_epoch_end(self, epoch: int, logs: Dict = {}) -> None:
+ """Called at the end of an epoch. Only used in training mode."""
pass
- def on_val_epoch_end(self) -> None:
- """Called at the end of an epoch."""
- pass
-
- def on_train_batch_begin(self) -> None:
+ def on_train_batch_begin(self, batch: int, logs: Dict = {}) -> None:
"""Called at the beginning of an epoch."""
pass
- def on_train_batch_end(self) -> None:
+ def on_train_batch_end(self, batch: int, logs: Dict = {}) -> None:
"""Called at the end of an epoch."""
pass
- def on_val_batch_begin(self) -> None:
+ def on_validation_batch_begin(self, batch: int, logs: Dict = {}) -> None:
"""Called at the beginning of an epoch."""
pass
- def on_val_batch_end(self) -> None:
+ def on_validation_batch_end(self, batch: int, logs: Dict = {}) -> None:
"""Called at the end of an epoch."""
pass
@@ -51,9 +64,29 @@ class Callback(ABC):
class CallbackList:
"""Container for abstracting away callback calls."""
- def __init__(self, callbacks: List[Callable] = None) -> None:
- """TBC."""
- self._callbacks = callbacks if callbacks is not None else []
+ mode_keys = ModeKeys()
+
+ def __init__(self, model: Type[Model], callbacks: List[Callback] = None) -> None:
+ """Container for `Callback` instances.
+
+ This object wraps a list of `Callback` instances and allows them all to be
+ called via a single end point.
+
+ Args:
+ model (Type[Model]): A `Model` instance.
+ callbacks (List[Callback]): List of `Callback` instances. Defaults to None.
+
+ """
+
+ self._callbacks = callbacks or []
+ if model:
+ self.set_model(model)
+
+ def set_model(self, model: Type[Model]) -> None:
+ """Set the model for all callbacks."""
+ self.model = model
+ for callback in self._callbacks:
+ callback.set_model(model=self.model)
def append(self, callback: Type[Callback]) -> None:
"""Append new callback to callback list."""
@@ -61,41 +94,147 @@ class CallbackList:
def on_fit_begin(self) -> None:
"""Called when fit begins."""
- for _ in self._callbacks:
- pass
+ for callback in self._callbacks:
+ callback.on_fit_begin()
def on_fit_end(self) -> None:
"""Called when fit ends."""
- pass
+ for callback in self._callbacks:
+ callback.on_fit_end()
- def on_train_epoch_begin(self) -> None:
+ def on_epoch_begin(self, epoch: int, logs: Dict = {}) -> None:
"""Called at the beginning of an epoch."""
- pass
+ for callback in self._callbacks:
+ callback.on_epoch_begin(epoch, logs)
- def on_train_epoch_end(self) -> None:
+ def on_epoch_end(self, epoch: int, logs: Dict = {}) -> None:
"""Called at the end of an epoch."""
- pass
-
- def on_val_epoch_begin(self) -> None:
+ for callback in self._callbacks:
+ callback.on_epoch_end(epoch, logs)
+
+ def _call_batch_hook(
+ self, mode: str, hook: str, batch: int, logs: Dict = {}
+ ) -> None:
+ """Helper function for all batch_{begin | end} methods."""
+ if hook == "begin":
+ self._call_batch_begin_hook(mode, batch, logs)
+ elif hook == "end":
+ self._call_batch_end_hook(mode, batch, logs)
+ else:
+ raise ValueError(f"Unrecognized hook {hook}.")
+
+ def _call_batch_begin_hook(self, mode: str, batch: int, logs: Dict = {}) -> None:
+ """Helper function for all `on_*_batch_begin` methods."""
+ hook_name = f"on_{mode}_batch_begin"
+ self._call_batch_hook_helper(hook_name, batch, logs)
+
+ def _call_batch_end_hook(self, mode: str, batch: int, logs: Dict = {}) -> None:
+ """Helper function for all `on_*_batch_end` methods."""
+ hook_name = f"on_{mode}_batch_end"
+ self._call_batch_hook_helper(hook_name, batch, logs)
+
+ def _call_batch_hook_helper(
+ self, hook_name: str, batch: int, logs: Dict = {}
+ ) -> None:
+ """Helper function for `on_*_batch_begin` methods."""
+ for callback in self._callbacks:
+ hook = getattr(callback, hook_name)
+ hook(batch, logs)
+
+ def on_train_batch_begin(self, batch: int, logs: Dict = {}) -> None:
"""Called at the beginning of an epoch."""
- pass
+ self._call_batch_hook(self.mode_keys.TRAIN, "begin", batch)
- def on_val_epoch_end(self) -> None:
+ def on_train_batch_end(self, batch: int, logs: Dict = {}) -> None:
"""Called at the end of an epoch."""
- pass
+ self._call_batch_hook(self.mode_keys.TRAIN, "end", batch)
- def on_train_batch_begin(self) -> None:
+ def on_validation_batch_begin(self, batch: int, logs: Dict = {}) -> None:
"""Called at the beginning of an epoch."""
- pass
-
- def on_train_batch_end(self) -> None:
- """Called at the end of an epoch."""
- pass
+ self._call_batch_hook(self.mode_keys.VALIDATION, "begin", batch)
- def on_val_batch_begin(self) -> None:
- """Called at the beginning of an epoch."""
- pass
-
- def on_val_batch_end(self) -> None:
+ def on_validation_batch_end(self, batch: int, logs: Dict = {}) -> None:
"""Called at the end of an epoch."""
- pass
+ self._call_batch_hook(self.mode_keys.VALIDATION, "end", batch)
+
+ def __iter__(self) -> iter:
+ """Iter function for callback list."""
+ return iter(self._callbacks)
+
+
+class Checkpoint(Callback):
+ """Saving model parameters at the end of each epoch."""
+
+ mode_dict = {
+ "min": torch.lt,
+ "max": torch.gt,
+ }
+
+ def __init__(
+ self, monitor: str = "accuracy", mode: str = "auto", min_delta: float = 0.0
+ ) -> None:
+ """Monitors a quantity that will allow us to determine the best model weights.
+
+ Args:
+ monitor (str): Name of the quantity to monitor. Defaults to "accuracy".
+ mode (str): Description of parameter `mode`. Defaults to "auto".
+ min_delta (float): Description of parameter `min_delta`. Defaults to 0.0.
+
+ """
+ super().__init__()
+ self.monitor = monitor
+ self.mode = mode
+ self.min_delta = torch.tensor(min_delta)
+
+ if mode not in ["auto", "min", "max"]:
+ logger.warning(f"Checkpoint mode {mode} is unkown, fallback to auto mode.")
+
+ self.mode = "auto"
+
+ if self.mode == "auto":
+ if "accuracy" in self.monitor:
+ self.mode = "max"
+ else:
+ self.mode = "min"
+ logger.debug(
+ f"Checkpoint mode set to {self.mode} for monitoring {self.monitor}."
+ )
+
+ torch_inf = torch.tensor(np.inf)
+ self.min_delta *= 1 if self.monitor_op == torch.gt else -1
+ self.best_score = torch_inf if self.monitor_op == torch.lt else -torch_inf
+
+ @property
+ def monitor_op(self) -> float:
+ """Returns the comparison method."""
+ return self.mode_dict[self.mode]
+
+ def on_epoch_end(self, epoch: int, logs: Dict) -> None:
+ """Saves a checkpoint for the network parameters.
+
+ Args:
+ epoch (int): The current epoch.
+ logs (Dict): The log containing the monitored metrics.
+
+ """
+ current = self.get_monitor_value(logs)
+ if current is None:
+ return
+ if self.monitor_op(current - self.min_delta, self.best_score):
+ self.best_score = current
+ is_best = True
+ else:
+ is_best = False
+
+ self.model.save_checkpoint(is_best, epoch, self.monitor)
+
+ def get_monitor_value(self, logs: Dict) -> Union[float, None]:
+ """Extracts the monitored value."""
+ monitor_value = logs.get(self.monitor)
+ if monitor_value is None:
+ logger.warning(
+ f"Checkpoint is conditioned on metric {self.monitor} which is not available. Available"
+ + f"metrics are: {','.join(list(logs.keys()))}"
+ )
+ return None
+ return monitor_value
diff --git a/src/training/callbacks/early_stopping.py b/src/training/callbacks/early_stopping.py
index 4da0e85..c9b7907 100644
--- a/src/training/callbacks/early_stopping.py
+++ b/src/training/callbacks/early_stopping.py
@@ -1 +1,107 @@
"""Implements Early stopping for PyTorch model."""
+from typing import Dict, Union
+
+from loguru import logger
+import numpy as np
+import torch
+from training.callbacks import Callback
+
+
+class EarlyStopping(Callback):
+ """Stops training when a monitored metric stops improving."""
+
+ mode_dict = {
+ "min": torch.lt,
+ "max": torch.gt,
+ }
+
+ def __init__(
+ self,
+ monitor: str = "val_loss",
+ min_delta: float = 0.0,
+ patience: int = 3,
+ mode: str = "auto",
+ ) -> None:
+ """Initializes the EarlyStopping callback.
+
+ Args:
+ monitor (str): Description of parameter `monitor`. Defaults to "val_loss".
+ min_delta (float): Description of parameter `min_delta`. Defaults to 0.0.
+ patience (int): Description of parameter `patience`. Defaults to 3.
+ mode (str): Description of parameter `mode`. Defaults to "auto".
+
+ """
+ super().__init__()
+ self.monitor = monitor
+ self.patience = patience
+ self.min_delta = torch.tensor(min_delta)
+ self.mode = mode
+ self.wait_count = 0
+ self.stopped_epoch = 0
+
+ if mode not in ["auto", "min", "max"]:
+ logger.warning(
+ f"EarlyStopping mode {mode} is unkown, fallback to auto mode."
+ )
+
+ self.mode = "auto"
+
+ if self.mode == "auto":
+ if "accuracy" in self.monitor:
+ self.mode = "max"
+ else:
+ self.mode = "min"
+ logger.debug(
+ f"EarlyStopping mode set to {self.mode} for monitoring {self.monitor}."
+ )
+
+ self.torch_inf = torch.tensor(np.inf)
+ self.min_delta *= 1 if self.monitor_op == torch.gt else -1
+ self.best_score = (
+ self.torch_inf if self.monitor_op == torch.lt else -self.torch_inf
+ )
+
+ @property
+ def monitor_op(self) -> float:
+ """Returns the comparison method."""
+ return self.mode_dict[self.mode]
+
+ def on_fit_begin(self) -> Union[torch.lt, torch.gt]:
+ """Reset the early stopping variables for reuse."""
+ self.wait_count = 0
+ self.stopped_epoch = 0
+ self.best_score = (
+ self.torch_inf if self.monitor_op == torch.lt else -self.torch_inf
+ )
+
+ def on_epoch_end(self, epoch: int, logs: Dict) -> None:
+ """Computes the early stop criterion."""
+ current = self.get_monitor_value(logs)
+ if current is None:
+ return
+ if self.monitor_op(current - self.min_delta, self.best_score):
+ self.best_score = current
+ self.wait_count = 0
+ else:
+ self.wait_count += 1
+ if self.wait_count >= self.patience:
+ self.stopped_epoch = epoch
+ self.model.stop_training = True
+
+ def on_fit_end(self) -> None:
+ """Logs if early stopping was used."""
+ if self.stopped_epoch > 0:
+ logger.info(
+ f"Stopped training at epoch {self.stopped_epoch + 1} with early stopping."
+ )
+
+ def get_monitor_value(self, logs: Dict) -> Union[torch.Tensor, None]:
+ """Extracts the monitor value."""
+ monitor_value = logs.get(self.monitor)
+ if monitor_value is None:
+ logger.warning(
+ f"Early stopping is conditioned on metric {self.monitor} which is not available. Available"
+ + f"metrics are: {','.join(list(logs.keys()))}"
+ )
+ return None
+ return torch.tensor(monitor_value)
diff --git a/src/training/callbacks/lr_schedulers.py b/src/training/callbacks/lr_schedulers.py
new file mode 100644
index 0000000..00c7e9b
--- /dev/null
+++ b/src/training/callbacks/lr_schedulers.py
@@ -0,0 +1,97 @@
+"""Callbacks for learning rate schedulers."""
+from typing import Callable, Dict, List, Optional, Type
+
+from training.callbacks import Callback
+
+from text_recognizer.models import Model
+
+
+class StepLR(Callback):
+ """Callback for StepLR."""
+
+ def __init__(self) -> None:
+ """Initializes the callback."""
+ super().__init__()
+ self.lr_scheduler = None
+
+ def set_model(self, model: Type[Model]) -> None:
+ """Sets the model and lr scheduler."""
+ self.model = model
+ self.lr_scheduler = self.model.lr_scheduler
+
+ def on_epoch_end(self, epoch: int, logs: Dict = {}) -> None:
+ """Takes a step at the end of every epoch."""
+ self.lr_scheduler.step()
+
+
+class MultiStepLR(Callback):
+ """Callback for MultiStepLR."""
+
+ def __init__(self) -> None:
+ """Initializes the callback."""
+ super().__init__()
+ self.lr_scheduler = None
+
+ def set_model(self, model: Type[Model]) -> None:
+ """Sets the model and lr scheduler."""
+ self.model = model
+ self.lr_scheduler = self.model.lr_scheduler
+
+ def on_epoch_end(self, epoch: int, logs: Dict = {}) -> None:
+ """Takes a step at the end of every epoch."""
+ self.lr_scheduler.step()
+
+
+class ReduceLROnPlateau(Callback):
+ """Callback for ReduceLROnPlateau."""
+
+ def __init__(self) -> None:
+ """Initializes the callback."""
+ super().__init__()
+ self.lr_scheduler = None
+
+ def set_model(self, model: Type[Model]) -> None:
+ """Sets the model and lr scheduler."""
+ self.model = model
+ self.lr_scheduler = self.model.lr_scheduler
+
+ def on_epoch_end(self, epoch: int, logs: Dict = {}) -> None:
+ """Takes a step at the end of every epoch."""
+ val_loss = logs["val_loss"]
+ self.lr_scheduler.step(val_loss)
+
+
+class CyclicLR(Callback):
+ """Callback for CyclicLR."""
+
+ def __init__(self) -> None:
+ """Initializes the callback."""
+ super().__init__()
+ self.lr_scheduler = None
+
+ def set_model(self, model: Type[Model]) -> None:
+ """Sets the model and lr scheduler."""
+ self.model = model
+ self.lr_scheduler = self.model.lr_scheduler
+
+ def on_train_batch_end(self, batch: int, logs: Dict = {}) -> None:
+ """Takes a step at the end of every training batch."""
+ self.lr_scheduler.step()
+
+
+class OneCycleLR(Callback):
+ """Callback for OneCycleLR."""
+
+ def __init__(self) -> None:
+ """Initializes the callback."""
+ super().__init__()
+ self.lr_scheduler = None
+
+ def set_model(self, model: Type[Model]) -> None:
+ """Sets the model and lr scheduler."""
+ self.model = model
+ self.lr_scheduler = self.model.lr_scheduler
+
+ def on_train_batch_end(self, batch: int, logs: Dict = {}) -> None:
+ """Takes a step at the end of every training batch."""
+ self.lr_scheduler.step()
diff --git a/src/training/callbacks/wandb_callbacks.py b/src/training/callbacks/wandb_callbacks.py
new file mode 100644
index 0000000..f64cbe1
--- /dev/null
+++ b/src/training/callbacks/wandb_callbacks.py
@@ -0,0 +1,93 @@
+"""Callbacks using wandb."""
+from typing import Callable, Dict, List, Optional, Type
+
+import numpy as np
+from torchvision.transforms import Compose, ToTensor
+from training.callbacks import Callback
+import wandb
+
+from text_recognizer.datasets import Transpose
+from text_recognizer.models.base import Model
+
+
+class WandbCallback(Callback):
+ """A custom W&B metric logger for the trainer."""
+
+ def __init__(self, log_batch_frequency: int = None) -> None:
+ """Short summary.
+
+ Args:
+ log_batch_frequency (int): If None, metrics will be logged every epoch.
+ If set to an integer, callback will log every metrics every log_batch_frequency.
+
+ """
+ super().__init__()
+ self.log_batch_frequency = log_batch_frequency
+
+ def _on_batch_end(self, batch: int, logs: Dict) -> None:
+ if self.log_batch_frequency and batch % self.log_batch_frequency == 0:
+ wandb.log(logs, commit=True)
+
+ def on_train_batch_end(self, batch: int, logs: Dict = {}) -> None:
+ """Logs training metrics."""
+ if logs is not None:
+ self._on_batch_end(batch, logs)
+
+ def on_validation_batch_end(self, batch: int, logs: Dict = {}) -> None:
+ """Logs validation metrics."""
+ if logs is not None:
+ self._on_batch_end(batch, logs)
+
+ def on_epoch_end(self, epoch: int, logs: Dict) -> None:
+ """Logs at epoch end."""
+ wandb.log(logs, commit=True)
+
+
+class WandbImageLogger(Callback):
+ """Custom W&B callback for image logging."""
+
+ def __init__(
+ self,
+ example_indices: Optional[List] = None,
+ num_examples: int = 4,
+ transfroms: Optional[Callable] = None,
+ ) -> None:
+ """Initializes the WandbImageLogger with the model to train.
+
+ Args:
+ example_indices (Optional[List]): Indices for validation images. Defaults to None.
+ num_examples (int): Number of random samples to take if example_indices are not specified. Defaults to 4.
+ transfroms (Optional[Callable]): Transforms to use on the validation images, e.g. transpose. Defaults to
+ None.
+
+ """
+
+ super().__init__()
+ self.example_indices = example_indices
+ self.num_examples = num_examples
+ self.transfroms = transfroms
+ if self.transfroms is None:
+ self.transforms = Compose([Transpose()])
+
+ def set_model(self, model: Type[Model]) -> None:
+ """Sets the model and extracts validation images from the dataset."""
+ self.model = model
+ data_loader = self.model.data_loaders("val")
+ if self.example_indices is None:
+ self.example_indices = np.random.randint(
+ 0, len(data_loader.dataset.data), self.num_examples
+ )
+ self.val_images = data_loader.dataset.data[self.example_indices]
+ self.val_targets = data_loader.dataset.targets[self.example_indices].numpy()
+
+ def on_epoch_end(self, epoch: int, logs: Dict) -> None:
+ """Get network predictions on validation images."""
+ images = []
+ for i, image in enumerate(self.val_images):
+ image = self.transforms(image)
+ pred, conf = self.model.predict_on_image(image)
+ ground_truth = self.model._mapping[self.val_targets[i]]
+ caption = f"Prediction: {pred} Confidence: {conf:.3f} Ground Truth: {ground_truth}"
+ images.append(wandb.Image(image, caption=caption))
+
+ wandb.log({"examples": images}, commit=False)
diff --git a/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/config.yml b/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/config.yml
deleted file mode 100644
index 2595325..0000000
--- a/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/config.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 8
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: LeNet
-network_args:
- input_size:
- - 28
- - 28
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/model/best.pt b/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/model/best.pt
deleted file mode 100644
index 6d78bad..0000000
--- a/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/model/last.pt b/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/model/last.pt
deleted file mode 100644
index 6d78bad..0000000
--- a/src/training/experiments/CharacterModel_Emnist_LeNet/0721_231455/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/config.yml b/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/config.yml
deleted file mode 100644
index 2595325..0000000
--- a/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/config.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 8
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: LeNet
-network_args:
- input_size:
- - 28
- - 28
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/model/best.pt b/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/model/best.pt
deleted file mode 100644
index 43a3891..0000000
--- a/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/model/last.pt b/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/model/last.pt
deleted file mode 100644
index 61c03f0..0000000
--- a/src/training/experiments/CharacterModel_Emnist_LeNet/0722_190746/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_124928/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_124928/config.yml
deleted file mode 100644
index 2aa52cd..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_124928/config.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: null
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.001
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141139/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141139/config.yml
deleted file mode 100644
index 829297d..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141139/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.0003
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.0006
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/config.yml
deleted file mode 100644
index 829297d..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.0003
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.0006
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/model/best.pt
deleted file mode 100644
index d0db78b..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/model/last.pt
deleted file mode 100644
index d0db78b..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141213/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/config.yml
deleted file mode 100644
index 3df32bb..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.01
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.1
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/model/best.pt
deleted file mode 100644
index 5914c8f..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/model/last.pt
deleted file mode 100644
index 5ba44bb..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141433/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/model/best.pt
deleted file mode 100644
index 96c21c1..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/model/last.pt
deleted file mode 100644
index f024c0d..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_141702/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_145028/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_145028/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_145028/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_150212/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_150212/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_150212/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_150301/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_150301/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_150301/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_150317/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_150317/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_150317/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/model/best.pt
deleted file mode 100644
index f833a89..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/model/last.pt
deleted file mode 100644
index f833a89..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_151135/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_151408/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_151408/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_151408/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153144/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_153144/config.yml
deleted file mode 100644
index 829297d..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153144/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.0003
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.0006
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153207/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_153207/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153207/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/model/best.pt
deleted file mode 100644
index cbbc5e1..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/model/last.pt
deleted file mode 100644
index cbbc5e1..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_153310/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/config.yml
deleted file mode 100644
index fb75736..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/model/best.pt
deleted file mode 100644
index c93e3c6..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/model/last.pt
deleted file mode 100644
index c93e3c6..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_175150/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/config.yml
deleted file mode 100644
index 1be5113..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: Adam
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 5.0e-05
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/model/best.pt
deleted file mode 100644
index 580bad2..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/model/last.pt
deleted file mode 100644
index 97e245c..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_180741/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/config.yml
deleted file mode 100644
index d2f98a2..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/config.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: Adamax
-optimizer_args:
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/model/best.pt
deleted file mode 100644
index 5a3df56..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/model/last.pt
deleted file mode 100644
index 7f28dc3..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_181933/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/config.yml
deleted file mode 100644
index d2f98a2..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/config.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: Adamax
-optimizer_args:
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/model/best.pt
deleted file mode 100644
index 6f09780..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/model/last.pt
deleted file mode 100644
index 3bb103e..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_183347/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/config.yml
deleted file mode 100644
index a7c66c5..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/config.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/model/best.pt
deleted file mode 100644
index c3e3618..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/model/last.pt
deleted file mode 100644
index c3e3618..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190044/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/config.yml
deleted file mode 100644
index a7c66c5..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/config.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/model/best.pt
deleted file mode 100644
index 44d9b9b..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/model/last.pt
deleted file mode 100644
index 44d9b9b..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190633/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/config.yml
deleted file mode 100644
index a7c66c5..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/config.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/model/best.pt
deleted file mode 100644
index 4a0333c..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/model/last.pt
deleted file mode 100644
index 4a0333c..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_190738/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191111/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191111/config.yml
deleted file mode 100644
index a7c66c5..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191111/config.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 0
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/config.yml
deleted file mode 100644
index 08c344c..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/config.yml
+++ /dev/null
@@ -1,46 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 1
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/model/best.pt
deleted file mode 100644
index 076aae1..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/model/last.pt
deleted file mode 100644
index 076aae1..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191310/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/config.yml
deleted file mode 100644
index 0b9b10e..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/config.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 1
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: null
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: RMSprop
-optimizer_args:
- alpha: 0.9
- centered: false
- eps: 1.0e-07
- lr: 0.001
- momentum: 0
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/model/best.pt
deleted file mode 100644
index 2fb0195..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/model/last.pt
deleted file mode 100644
index 2fb0195..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191412/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/config.yml
deleted file mode 100644
index 93c2854..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/config.yml
+++ /dev/null
@@ -1,42 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 4
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: null
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: RMSprop
-optimizer_args:
- alpha: 0.9
- centered: false
- eps: 1.0e-07
- lr: 0.001
- momentum: 0
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/model/best.pt
deleted file mode 100644
index 9acc5b1..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/model/last.pt
deleted file mode 100644
index b8cc01c..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191504/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/config.yml
deleted file mode 100644
index 7340941..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/config.yml
+++ /dev/null
@@ -1,47 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 8
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/model/best.pt
deleted file mode 100644
index 26bfb07..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/model/last.pt
deleted file mode 100644
index 26bfb07..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0721_191826/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/config.yml
deleted file mode 100644
index 90f0e13..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/config.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 8
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 33
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-resume_experiment: last
-train_args:
- batch_size: 256
- epochs: 33
- val_metric: accuracy
-verbosity: 1
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/model/best.pt
deleted file mode 100644
index f0f297b..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/model/last.pt
deleted file mode 100644
index c1adda5..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_191559/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213125/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0722_213125/config.yml
deleted file mode 100644
index 8d77de5..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213125/config.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 8
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-resume_experiment: null
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
-verbosity: 2
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/config.yml
deleted file mode 100644
index 8d77de5..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/config.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 8
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-resume_experiment: null
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
-verbosity: 2
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/model/best.pt
deleted file mode 100644
index e985997..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/model/last.pt
deleted file mode 100644
index e985997..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213413/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/config.yml b/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/config.yml
deleted file mode 100644
index 8d77de5..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/config.yml
+++ /dev/null
@@ -1,49 +0,0 @@
-criterion: CrossEntropyLoss
-criterion_args:
- ignore_index: -100
- reduction: mean
- weight: null
-data_loader_args:
- batch_size: 256
- cuda: true
- num_workers: 8
- sample_to_balance: true
- seed: 4711
- shuffle: true
- splits:
- - train
- - val
- subsample_fraction: null
- target_transform: null
- transform: null
-dataloader: EmnistDataLoader
-device: cuda:0
-experiment_group: Sample Experiments
-lr_scheduler: OneCycleLR
-lr_scheduler_args:
- epochs: 16
- max_lr: 0.001
- steps_per_epoch: 1314
-metrics:
-- accuracy
-model: CharacterModel
-network: MLP
-network_args:
- input_size: 784
- num_layers: 3
- output_size: 62
-optimizer: AdamW
-optimizer_args:
- amsgrad: false
- betas:
- - 0.9
- - 0.999
- eps: 1.0e-08
- lr: 0.01
- weight_decay: 0
-resume_experiment: null
-train_args:
- batch_size: 256
- epochs: 16
- val_metric: accuracy
-verbosity: 2
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/model/best.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/model/best.pt
deleted file mode 100644
index 0dde787..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/model/best.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/model/last.pt b/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/model/last.pt
deleted file mode 100644
index e02738b..0000000
--- a/src/training/experiments/CharacterModel_Emnist_MLP/0722_213549/model/last.pt
+++ /dev/null
Binary files differ
diff --git a/src/training/experiments/sample.yml b/src/training/experiments/sample.yml
deleted file mode 100644
index 0ed560d..0000000
--- a/src/training/experiments/sample.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-experiment_group: Sample Experiments
-experiments:
- - dataloader: EmnistDataLoader
- model: CharacterModel
- metrics: [accuracy]
- network: MLP
- network_args:
- input_shape: 784
- num_layers: 2
- train_args:
- batch_size: 256
- epochs: 16
- criterion: CrossEntropyLoss
- criterion_args:
- weight: null
- ignore_index: -100
- reduction: mean
- optimizer: AdamW
- optimizer_args:
- lr: 3.e-4
- betas: [0.9, 0.999]
- eps: 1.e-08
- weight_decay: 0
- amsgrad: false
- lr_scheduler: OneCycleLR
- lr_scheduler_args:
- max_lr: 3.e-5
- epochs: 16
- # - dataloader: EmnistDataLoader
- # model: CharacterModel
- # network: MLP
- # network_args:
- # input_shape: 784
- # num_layers: 4
- # train_args:
- # batch_size: 256
- # - dataloader: EmnistDataLoader
- # model: CharacterModel
- # network: LeNet
- # network_args:
- # input_shape: [28, 28]
- # train_args:
- # batch_size: 256
diff --git a/src/training/experiments/sample_experiment.yml b/src/training/experiments/sample_experiment.yml
index e8d5023..70edb63 100644
--- a/src/training/experiments/sample_experiment.yml
+++ b/src/training/experiments/sample_experiment.yml
@@ -1,6 +1,6 @@
experiment_group: Sample Experiments
experiments:
- - dataloader: EmnistDataLoader
+ - dataloader: EmnistDataLoaders
data_loader_args:
splits: [train, val]
sample_to_balance: true
@@ -14,19 +14,18 @@ experiments:
seed: 4711
model: CharacterModel
metrics: [accuracy]
- network: MLP
- network_args:
- input_size: 784
- output_size: 62
- num_layers: 3
- # network: LeNet
+ # network: MLP
# network_args:
- # input_size: [28, 28]
+ # input_size: 784
# output_size: 62
+ # num_layers: 3
+ network: LeNet
+ network_args:
+ input_size: [28, 28]
+ output_size: 62
train_args:
batch_size: 256
epochs: 16
- val_metric: accuracy
criterion: CrossEntropyLoss
criterion_args:
weight: null
@@ -52,5 +51,20 @@ experiments:
lr_scheduler_args:
max_lr: 1.e-3
epochs: 16
- verbosity: 2 # 0, 1, 2
+ callbacks: [Checkpoint, EarlyStopping, WandbCallback, WandbImageLogger, OneCycleLR]
+ callback_args:
+ Checkpoint:
+ monitor: val_accuracy
+ EarlyStopping:
+ monitor: val_loss
+ min_delta: 0.0
+ patience: 3
+ mode: min
+ WandbCallback:
+ log_batch_frequency: 10
+ WandbImageLogger:
+ num_examples: 4
+ OneCycleLR:
+ null
+ verbosity: 1 # 0, 1, 2
resume_experiment: null
diff --git a/src/training/prepare_experiments.py b/src/training/prepare_experiments.py
index eb872d7..5a665b3 100644
--- a/src/training/prepare_experiments.py
+++ b/src/training/prepare_experiments.py
@@ -1,12 +1,13 @@
"""Run a experiment from a config file."""
import json
-from subprocess import check_call
+from subprocess import run
import click
from loguru import logger
import yaml
+# flake8: noqa: S404,S607,S603
def run_experiments(experiments_filename: str) -> None:
"""Run experiment from file."""
with open(experiments_filename) as f:
@@ -15,10 +16,19 @@ def run_experiments(experiments_filename: str) -> None:
for index in range(num_experiments):
experiment_config = experiments_config["experiments"][index]
experiment_config["experiment_group"] = experiments_config["experiment_group"]
- # cmd = f"python training/run_experiment.py --gpu=-1 '{json.dumps(experiment_config)}'"
- cmd = f"poetry run run-experiment --gpu=-1 --save --experiment_config '{json.dumps(experiment_config)}'"
+ cmd = f"poetry run run-experiment --gpu=-1 --save --experiment_config={json.dumps(experiment_config)}"
print(cmd)
- check_call(cmd, shell=True)
+ run(
+ [
+ "poetry",
+ "run",
+ "run-experiment",
+ "--gpu=-1",
+ "--save",
+ f"--experiment_config={json.dumps(experiment_config)}",
+ ],
+ check=True,
+ )
@click.command()
diff --git a/src/training/run_experiment.py b/src/training/run_experiment.py
index 0b29ce9..c133ce5 100644
--- a/src/training/run_experiment.py
+++ b/src/training/run_experiment.py
@@ -12,8 +12,10 @@ import click
from loguru import logger
import torch
from tqdm import tqdm
+from training.callbacks import CallbackList
from training.gpu_manager import GPUManager
from training.train import Trainer
+import wandb
import yaml
@@ -48,9 +50,8 @@ def create_experiment_dir(model: Callable, experiment_config: Dict) -> Path:
logger.debug(f"Resuming the latest experiment {experiment}")
else:
experiment = experiment_config["resume_experiment"]
- assert (
- str(experiment_dir / experiment) in available_experiments
- ), "Experiment does not exist."
+ if not str(experiment_dir / experiment) in available_experiments:
+ raise FileNotFoundError("Experiment does not exist.")
logger.debug(f"Resuming the experiment {experiment}")
experiment_dir = experiment_dir / experiment
@@ -87,6 +88,13 @@ def load_modules_and_arguments(experiment_config: Dict) -> Tuple[Callable, Dict]
optimizer_ = getattr(torch.optim, experiment_config["optimizer"])
optimizer_args = experiment_config.get("optimizer_args", {})
+ # Callbacks
+ callback_modules = importlib.import_module("training.callbacks")
+ callbacks = []
+ for callback in experiment_config["callbacks"]:
+ args = experiment_config["callback_args"][callback] or {}
+ callbacks.append(getattr(callback_modules, callback)(**args))
+
# Learning rate scheduler
if experiment_config["lr_scheduler"] is not None:
lr_scheduler_ = getattr(
@@ -111,7 +119,7 @@ def load_modules_and_arguments(experiment_config: Dict) -> Tuple[Callable, Dict]
"lr_scheduler_args": lr_scheduler_args,
}
- return model_class_, model_args
+ return model_class_, model_args, callbacks
def run_experiment(
@@ -120,11 +128,14 @@ def run_experiment(
"""Runs an experiment."""
# Load the modules and model arguments.
- model_class_, model_args = load_modules_and_arguments(experiment_config)
+ model_class_, model_args, callbacks = load_modules_and_arguments(experiment_config)
# Initializes the model with experiment config.
model = model_class_(**model_args, device=device)
+ # Instantiate a CallbackList.
+ callbacks = CallbackList(model, callbacks)
+
# Create new experiment.
experiment_dir = create_experiment_dir(model, experiment_config)
@@ -132,6 +143,9 @@ def run_experiment(
log_dir = experiment_dir / "log"
model_dir = experiment_dir / "model"
+ # Set the model dir to be able to save checkpoints.
+ model.model_dir = model_dir
+
# Get checkpoint path.
checkpoint_path = model_dir / "last.pt"
if not checkpoint_path.exists():
@@ -162,6 +176,13 @@ def run_experiment(
logger.info(f"The class mapping is {model.mapping}")
+ # Initializes Weights & Biases
+ if use_wandb:
+ wandb.init(project="text-recognizer", config=experiment_config)
+
+ # Lets W&B save the model and track the gradients and optional parameters.
+ wandb.watch(model.network)
+
# PÅ•ints a summary of the network in terminal.
model.summary()
@@ -181,21 +202,26 @@ def run_experiment(
with open(str(config_path), "w") as f:
yaml.dump(experiment_config, f)
- # TODO: wandb
trainer = Trainer(
model=model,
model_dir=model_dir,
- epochs=experiment_config["train_args"]["epochs"],
- val_metric=experiment_config["train_args"]["val_metric"],
+ train_args=experiment_config["train_args"],
+ callbacks=callbacks,
checkpoint_path=checkpoint_path,
)
trainer.fit()
+ logger.info("Loading checkpoint with the best weights.")
+ model.load_checkpoint(model_dir / "best.pt")
+
score = trainer.validate()
logger.info(f"Validation set evaluation: {score}")
+ if use_wandb:
+ wandb.log({"validation_metric": score["val_accuracy"]})
+
if save_weights:
model.save_weights(model_dir)
@@ -220,12 +246,11 @@ def main(experiment_config: str, gpu: int, save: bool, nowandb: bool) -> None:
if gpu < 0:
gpu_manager = GPUManager(True)
gpu = gpu_manager.get_free_gpu()
-
device = "cuda:" + str(gpu)
experiment_config = json.loads(experiment_config)
os.environ["CUDA_VISIBLE_DEVICES"] = f"{gpu}"
- run_experiment(experiment_config, save, device, nowandb)
+ run_experiment(experiment_config, save, device, use_wandb=not nowandb)
if __name__ == "__main__":
diff --git a/src/training/train.py b/src/training/train.py
index 8cd5110..3334c2e 100644
--- a/src/training/train.py
+++ b/src/training/train.py
@@ -2,17 +2,19 @@
from pathlib import Path
import time
-from typing import Dict, Optional, Type
+from typing import Dict, List, Optional, Tuple, Type
from loguru import logger
import numpy as np
import torch
from tqdm import tqdm, trange
+from training.callbacks import Callback, CallbackList
from training.util import RunningAverage
import wandb
from text_recognizer.models import Model
+
torch.backends.cudnn.benchmark = True
np.random.seed(4711)
torch.manual_seed(4711)
@@ -22,51 +24,82 @@ torch.cuda.manual_seed(4711)
class Trainer:
"""Trainer for training PyTorch models."""
- # TODO implement wandb.
- # TODO implement Bayesian parameter search.
-
def __init__(
self,
model: Type[Model],
model_dir: Path,
- epochs: int,
- val_metric: str = "accuracy",
+ train_args: Dict,
+ callbacks: CallbackList,
checkpoint_path: Optional[Path] = None,
- use_wandb: Optional[bool] = False,
) -> None:
"""Initialization of the Trainer.
Args:
model (Type[Model]): A model object.
model_dir (Path): Path to the model directory.
- epochs (int): Number of epochs to train.
- val_metric (str): The validation metric to evaluate the model on. Defaults to "accuracy".
+ train_args (Dict): The training arguments.
+ callbacks (CallbackList): List of callbacks to be called.
checkpoint_path (Optional[Path]): The path to a previously trained model. Defaults to None.
- use_wandb (Optional[bool]): Sync training to wandb.
"""
self.model = model
self.model_dir = model_dir
- self.epochs = epochs
self.checkpoint_path = checkpoint_path
- self.start_epoch = 0
+ self.start_epoch = 1
+ self.epochs = train_args["epochs"] + self.start_epoch
+ self.callbacks = callbacks
if self.checkpoint_path is not None:
- self.start_epoch = self.model.load_checkpoint(self.checkpoint_path)
-
- if use_wandb:
- # TODO implement wandb logging.
- pass
-
- self.val_metric = val_metric
- self.best_val_metric = 0.0
+ self.start_epoch = self.model.load_checkpoint(self.checkpoint_path) + 1
# Parse the name of the experiment.
experiment_dir = str(self.model_dir.parents[1]).split("/")
self.experiment_name = experiment_dir[-2] + "/" + experiment_dir[-1]
+ def training_step(
+ self,
+ batch: int,
+ samples: Tuple[torch.Tensor, torch.Tensor],
+ loss_avg: Type[RunningAverage],
+ ) -> Dict:
+ """Performs the training step."""
+ # Pass the tensor to the device for computation.
+ data, targets = samples
+ data, targets = (
+ data.to(self.model.device),
+ targets.to(self.model.device),
+ )
+
+ # Forward pass.
+ # Get the network prediction.
+ output = self.model.network(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()
+
+ # Compute metrics.
+ loss_avg.update(loss.item())
+ output = output.data.cpu()
+ targets = targets.data.cpu()
+ metrics = {
+ metric: self.model.metrics[metric](output, targets)
+ for metric in self.model.metrics
+ }
+ metrics["loss"] = loss_avg()
+ return metrics
+
def train(self) -> None:
- """Training loop."""
+ """Runs the training loop for one epoch."""
# Set model to traning mode.
self.model.train()
@@ -79,57 +112,54 @@ class Trainer:
total=len(data_loader),
leave=False,
unit="step",
- bar_format="{n_fmt}/{total_fmt} |{bar:20}| {remaining} {rate_inv_fmt}{postfix}",
+ bar_format="{n_fmt}/{total_fmt} |{bar:30}| {remaining} {rate_inv_fmt}{postfix}",
) as t:
- for data, targets in data_loader:
+ for batch, samples in enumerate(data_loader):
+ self.callbacks.on_train_batch_begin(batch)
- data, targets = (
- data.to(self.model.device),
- targets.to(self.model.device),
- )
+ metrics = self.training_step(batch, samples, loss_avg)
- # Forward pass.
- # Get the network prediction.
- output = self.model.network(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()
-
- # Compute metrics.
- loss_avg.update(loss.item())
- output = output.data.cpu()
- targets = targets.data.cpu()
- metrics = {
- metric: self.model.metrics[metric](output, targets)
- for metric in self.model.metrics
- }
- metrics["loss"] = loss_avg()
+ self.callbacks.on_train_batch_end(batch, logs=metrics)
# Update Tqdm progress bar.
t.set_postfix(**metrics)
t.update()
- # If the model has a learning rate scheduler, compute a step.
- if self.model.lr_scheduler is not None:
- self.model.lr_scheduler.step()
-
- def validate(self) -> Dict:
- """Evaluation loop.
+ def validation_step(
+ self,
+ batch: int,
+ samples: Tuple[torch.Tensor, torch.Tensor],
+ loss_avg: Type[RunningAverage],
+ ) -> Dict:
+ """Performs the validation step."""
+ # Pass the tensor to the device for computation.
+ data, targets = samples
+ data, targets = (
+ data.to(self.model.device),
+ targets.to(self.model.device),
+ )
+
+ # Forward pass.
+ # Get the network prediction.
+ output = self.model.network(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: self.model.metrics[metric](output, targets)
+ for metric in self.model.metrics
+ }
+ metrics["loss"] = loss.item()
- Returns:
- Dict: A dictionary of evaluation metrics.
+ return metrics
- """
+ def validate(self, epoch: Optional[int] = None) -> Dict:
+ """Runs the validation loop for one epoch."""
# Set model to eval mode.
self.model.eval()
@@ -146,44 +176,37 @@ class Trainer:
total=len(data_loader),
leave=False,
unit="step",
- bar_format="{n_fmt}/{total_fmt} |{bar:20}| {remaining} {rate_inv_fmt}{postfix}",
+ bar_format="{n_fmt}/{total_fmt} |{bar:30}| {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),
- )
-
- with torch.no_grad():
- # Forward pass.
- # Get the network prediction.
- output = self.model.network(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: self.model.metrics[metric](output, targets)
- for metric in self.model.metrics
- }
- metrics["loss"] = loss.item()
-
- summary.append(metrics)
+ with torch.no_grad():
+ for batch, samples in enumerate(data_loader):
+ self.callbacks.on_validation_batch_begin(batch)
- # Update Tqdm progress bar.
- t.set_postfix(**metrics)
- t.update()
+ metrics = self.validation_step(batch, samples, loss_avg)
+
+ self.callbacks.on_validation_batch_end(batch, logs=metrics)
+
+ 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]
+ "val_" + 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)
+ if epoch:
+ logger.debug(
+ f"Validation metrics at epoch {epoch} - "
+ + " - ".join(f"{k}: {v:.4f}" for k, v in metrics_mean.items())
+ )
+ else:
+ logger.debug(
+ "Validation metrics - "
+ + " - ".join(f"{k}: {v:.4f}" for k, v in metrics_mean.items())
+ )
return metrics_mean
@@ -192,31 +215,35 @@ class Trainer:
logger.debug(f"Running an experiment called {self.experiment_name}.")
t_start = time.time()
+
+ self.callbacks.on_fit_begin()
+
+ # TODO: fix progress bar as callback.
# Run the training loop.
for epoch in trange(
+ self.start_epoch,
self.epochs,
- initial=self.start_epoch,
leave=False,
- bar_format="{desc}: {n_fmt}/{total_fmt} |{bar:10}| {remaining}{postfix}",
+ bar_format="{desc}: {n_fmt}/{total_fmt} |{bar:30}| {remaining}{postfix}",
desc="Epoch",
):
+ self.callbacks.on_epoch_begin(epoch)
+
# Perform one training pass over the training set.
self.train()
# Evaluate the model on the validation set.
- val_metrics = self.validate()
+ val_metrics = self.validate(epoch)
- # 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
- self.best_val_metric = val_metric if is_best else self.best_val_metric
- # Save checkpoint.
- self.model.save_checkpoint(self.model_dir, is_best, epoch, self.val_metric)
+ self.callbacks.on_epoch_end(epoch, logs=val_metrics)
- if self.start_epoch > 0 and epoch + self.start_epoch == self.epochs:
- logger.debug(f"Trained the model for {self.epochs} number of epochs.")
+ if self.model.stop_training:
break
+ # Calculate the total training time.
t_end = time.time()
t_training = t_end - t_start
+
+ self.callbacks.on_fit_end()
+
logger.info(f"Training took {t_training:.2f} s.")
diff --git a/src/wandb/settings b/src/wandb/settings
new file mode 100644
index 0000000..eafb083
--- /dev/null
+++ b/src/wandb/settings
@@ -0,0 +1,4 @@
+[default]
+entity = aktersnurra
+project = text-recognizer
+base_url = https://api.wandb.ai