diff --git a/labs/lab25/ML3.ipynb b/labs/lab25/ML3.ipynb new file mode 100644 index 0000000..dab9ef3 --- /dev/null +++ b/labs/lab25/ML3.ipynb @@ -0,0 +1,3070 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Intro to CV, DL, and PyTorch (Intro 3: \"Intro x3\")" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from IPython.display import Image as JupyterImage\n", + "from typing import Dict, Iterable, List, Optional, Tuple\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "import torch.optim as optim\n", + "import tqdm\n", + "from PIL import Image, ImageOps, ImageChops # pip install Pillow\n", + "from skimage import io, transform # pip install scikit-image\n", + "from torch.nn import CrossEntropyLoss, Module\n", + "from torch.optim import SGD\n", + "from torch.optim.lr_scheduler import CosineAnnealingLR\n", + "from torch.utils.data import Dataset, DataLoader\n", + "\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# https://stackoverflow.com/questions/40536560/ipython-and-jupyter-autocomplete-not-working\n", + "\n", + "%config Completer.use_jedi = False" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Classification\n", + "\n", + "* https://en.wikipedia.org/wiki/Precision_and_recall" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## \"Data\"\n", + "\n", + "* https://en.wikipedia.org/wiki/Portable_Network_Graphics\n", + "* https://stackoverflow.com/questions/1962795/how-to-get-alpha-value-of-a-png-image-with-pil\n", + "* https://matplotlib.org/stable/tutorials/introductory/images.html" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data_original images ML3.ipynb\r\n" + ] + } + ], + "source": [ + "! ls" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "DATA_FOLDER_ORIGINAL = 'data_original'" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "circle.png square.png\ttriangle.png\r\n" + ] + } + ], + "source": [ + "! ls $DATA_FOLDER_ORIGINAL" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "TRIANGLE = 'triangle'\n", + "SQUARE = 'square'\n", + "CIRCLE = 'circle'" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "JupyterImage(filename=f'{DATA_FOLDER_ORIGINAL}/{CIRCLE}.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "JupyterImage(filename=f'{DATA_FOLDER_ORIGINAL}/{TRIANGLE}.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlgAAAGQCAYAAAByNR6YAAAACXBIWXMAAAfPAAAHzwGGUVlPAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAABOJJREFUeJzt1jFNBVEUANG78HtMoIAWNfQYwgJ2SEgIDqipdzExyQu75yiYcmYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC21QEAZ/cw30/H3D+v7riQY5/9/Xcef1aHcF231QEAZ7fP7XWbeVndcSH7zP3HzBgslrlbHQAAsWN1ABgsAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQIAiBksAICYwQLgZI5tdQHcVgcAnN0283bM9rm64zqOOWa+VlcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8L/8AXb9FJR9+3UsAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "JupyterImage(filename=f'{DATA_FOLDER_ORIGINAL}/{SQUARE}.png')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Geometric Approach (\"Handcrafted ML\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## On the Way to ML: Data Preprocessing\n", + "\n", + "* https://en.wikipedia.org/wiki/Data_augmentation\n", + "* https://stackoverflow.com/questions/18777873/convert-rgb-to-black-or-white" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Data Augmentation" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "# https://www.geeksforgeeks.org/how-to-rotate-an-image-using-python/\n", + "\n", + "original_image = Image.open(f\"{DATA_FOLDER_ORIGINAL}/{TRIANGLE}.png\")" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "original_image" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(600, 400)" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "original_image.size" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "original_image.rotate(60)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "original_image.rotate(60).save('rotated_60.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "data_original images ML3.ipynb rotated_60.png\r\n" + ] + } + ], + "source": [ + "! ls" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "JupyterImage('rotated_60.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "# http://www.legendu.net/misc/blog/python-pillow-image-shift/" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "DATA_FOLDER_GENERATED = 'data_generated'" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "! mkdir $DATA_FOLDER_GENERATED" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "original_image" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ImageChops.offset(original_image, -50, -50)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['triangle.png', 'square.png', 'circle.png']" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "os.listdir(DATA_FOLDER_ORIGINAL)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('square', '.png')" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "os.path.splitext('square.png')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 3/3 [00:08<00:00, 2.84s/it]\n" + ] + } + ], + "source": [ + "x_shift_range = range(-50, 51, 25)\n", + "y_shift_range = range(-50, 51, 25)\n", + "\n", + "_original_image_names = os.listdir(DATA_FOLDER_ORIGINAL)\n", + "\n", + "for image_name in tqdm.tqdm(_original_image_names, total=len(_original_image_names)):\n", + " image_path = os.path.join(DATA_FOLDER_ORIGINAL, image_name)\n", + " original_image = Image.open(image_path)\n", + " \n", + " for x_shift in x_shift_range:\n", + " for y_shift in y_shift_range:\n", + " if CIRCLE in image_name:\n", + " angle_range = [0]\n", + " else:\n", + " angle_range = range(0, 91, 30)\n", + " \n", + " for angle in angle_range:\n", + " image = original_image.rotate(angle)\n", + " image = ImageChops.offset(\n", + " image, xoffset=x_shift, yoffset=y_shift\n", + " )\n", + " \n", + " basename, extension = os.path.splitext(image_name)\n", + " new_image_name = (\n", + " f'{basename}'\n", + " f'__xo_{x_shift}'\n", + " f'__yo_{y_shift}'\n", + " f'__ang_{angle}{extension}'\n", + " )\n", + " new_image_path = os.path.join(\n", + " DATA_FOLDER_GENERATED, new_image_name\n", + " )\n", + " image.save(new_image_path)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "225\r\n" + ] + } + ], + "source": [ + "! ls data_generated | wc -l" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "circle__xo_0__yo_0__ang_0.png\r\n", + "circle__xo_0__yo_-25__ang_0.png\r\n", + "circle__xo_0__yo_25__ang_0.png\r\n", + "circle__xo_0__yo_-50__ang_0.png\r\n", + "circle__xo_0__yo_50__ang_0.png\r\n", + "circle__xo_-25__yo_0__ang_0.png\r\n", + "circle__xo_25__yo_0__ang_0.png\r\n", + "circle__xo_-25__yo_-25__ang_0.png\r\n", + "circle__xo_-25__yo_25__ang_0.png\r\n", + "circle__xo_25__yo_-25__ang_0.png\r\n" + ] + } + ], + "source": [ + "! ls data_generated | head" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "class GeometricShapesDataset(Dataset):\n", + " _LABEL_NAME_TO_ID = {\n", + " 'triangle': 0,\n", + " 'square': 1,\n", + " 'circle': 2,\n", + " }\n", + " _LABEL_ID_TO_NAME = {v: k for k, v in _LABEL_NAME_TO_ID.items()}\n", + " \n", + " def __init__(\n", + " self,\n", + " folder_path: str,\n", + " file_names = None,\n", + " transform=None\n", + " ):\n", + " self._root_folder = folder_path\n", + " self._transform = transform\n", + " \n", + " _file_names = sorted(os.listdir(self._root_folder))\n", + " \n", + " if file_names is not None:\n", + " assert set(file_names) < set(_file_names)\n", + " \n", + " self._file_names = file_names\n", + " else:\n", + " self._file_names = _file_names\n", + "\n", + " def __len__(self) -> int:\n", + " return len(self._file_names)\n", + "\n", + " def __getitem__(self, index: int) -> Tuple[np.array, int]:\n", + " file_name = self._file_names[index]\n", + " file_path = os.path.join(self._root_folder, file_name)\n", + " image = io.imread(file_path)\n", + " label_name = file_name.split('__')[0]\n", + " label = self._LABEL_NAME_TO_ID[label_name]\n", + "\n", + " if self._transform is None:\n", + " sample = image\n", + " else:\n", + " sample = self._transform(image)\n", + "\n", + " return (sample, label)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "dataset = GeometricShapesDataset(folder_path=DATA_FOLDER_GENERATED)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(400, 600, 4)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dataset[1][0].shape" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Label ID: 2. Label name: circle.\n", + "Image shape: (400, 600, 4)\n" + ] + }, + { + "data": { + "text/plain": [ + "((array([[[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " ...,\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]]], dtype=uint8),\n", + " 2),\n", + " array([[[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " ...,\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]],\n", + " \n", + " [[0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " ...,\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0],\n", + " [0, 0, 0, 0]]], dtype=uint8),\n", + " 2)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "_data_item = dataset[1]\n", + "_image, _label = _data_item\n", + "\n", + "print(\n", + " f'Label ID: {_label}.'\n", + " f' Label name: {GeometricShapesDataset._LABEL_ID_TO_NAME[_label]}.'\n", + ")\n", + "\n", + "print(f'Image shape: {_image.shape}')\n", + "\n", + "plt.imshow(_image)\n", + "\n", + "_data_item, _image, _label" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[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]], dtype=uint8)" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "_image[:, :, -1]" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "def to_black_and_white(image: np.array) -> np.array:\n", + " image_one_channel = (\n", + " np.max(\n", + " image[:, :, :3], axis=2, keepdims=True\n", + " ) # * image[:, :, -1:]\n", + " ).astype(int)\n", + " \n", + " image_one_channel[image_one_channel > 0] = 255\n", + " \n", + " return image_one_channel" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[0],\n", + " [0],\n", + " [0],\n", + " ...,\n", + " [0],\n", + " [0],\n", + " [0]],\n", + "\n", + " [[0],\n", + " [0],\n", + " [0],\n", + " ...,\n", + " [0],\n", + " [0],\n", + " [0]],\n", + "\n", + " [[0],\n", + " [0],\n", + " [0],\n", + " ...,\n", + " [0],\n", + " [0],\n", + " [0]],\n", + "\n", + " ...,\n", + "\n", + " [[0],\n", + " [0],\n", + " [0],\n", + " ...,\n", + " [0],\n", + " [0],\n", + " [0]],\n", + "\n", + " [[0],\n", + " [0],\n", + " [0],\n", + " ...,\n", + " [0],\n", + " [0],\n", + " [0]],\n", + "\n", + " [[0],\n", + " [0],\n", + " [0],\n", + " ...,\n", + " [0],\n", + " [0],\n", + " [0]]])" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "to_black_and_white(_image)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlYAAADMCAYAAACxx+0TAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAAeDklEQVR4nO3de5RV9Znm8e9TVRQgIAVSInKJN7wrKBU1F9cy9jKKK93ISGjUtJhxhpjEFc1lEuhMNDFtJ854a5KJI1GDGWMMdrywvLRBxKRNOmohRBGDFooBGiiQcBOEurzzR22wxIK67XP2PsXzcZ1V+/zO3mc/RR3feut39t5HEYGZmZmZdV9Z1gHMzMzMego3VmZmZmYpcWNlZmZmlhI3VmZmZmYpcWNlZmZmlhI3VmZmZmYpKVhjJekCScsk1UmaXqj9mJmlzfXLzLpKhbiOlaRy4HXgPGAV8CJwSUQsTX1nZmYpcv0ys+4o1IzVGUBdRLwZEbuAB4AJBdqXmVmaXL/MrMsK1VgNB1a2ur8qGTMzyzvXLzPrsoqsdixpGjANoF+/fuOOP/74rKKYWQYWLly4ISKqs87RVa1rGDAuyyxmVnwRobbGC9VYrQZGtro/IhlrHWgWMAugpqYmamtrCxTFzPJI0ttZZ9iHdusXfLCGSfKHrpoZULi3Al8ERks6UlIlMAWYW6B9mZmlyfXLzLqsIDNWEdEo6WrgKaAcuCciXi3EvszM0uT6ZWbdUbBjrCLiCeCJQj2/mVmhuH6ZWVf5yutmZmZmKXFjZWZmZpYSN1ZmZmZmKXFjZWZmZpYSN1ZmZmZmKXFjZWZmZpYSN1ZmZmZmKXFjZWZmZpYSN1ZmZmZmKXFjZWZmZpYSN1ZmZmZmKXFjZWZmZpaSbn0Is6QVwFagCWiMiBpJg4FfAUcAK4DJEfHX7sU0M0ufa5iZpS2NGatPRcTYiKhJ7k8H5kfEaGB+ct/MLK9cw8wsNYV4K3ACcG+yfC9wUQH2YWZWKK5hZtZl3W2sAviNpIWSpiVjQyNiTbK8FhjazX2YmRWKa5iZpapbx1gBn4yI1ZIOBeZJ+nPrByMiJEVbGyZFbBrAqFGjuhnDzKxLUqlhZma7dWvGKiJWJ1/rgYeBM4B1koYBJF/r97HtrIioiYia6urq7sQwM+uStGpYsfKaWf51ubGS1E/SgN3LwKeBJcBcYGqy2lTg0e6GNDNLm2uYmRVCd94KHAo8LGn389wfEf8m6UVgjqQrgbeByd2PaWaWOtcwM0tdlxuriHgTGNPG+DvA33QnlJlZobmGmVkh+MrrZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWknYbK0n3SKqXtKTV2GBJ8yS9kXwdlIxL0kxJdZJelnR6IcObmbXHNczMiqkjM1azgQv2GpsOzI+I0cD85D7AeGB0cpsG3JFOTDOzLpuNa5iZFUm7jVVE/A7YuNfwBODeZPle4KJW4z+PFn8EqiQNSymrmVmnuYaZWTF19RiroRGxJlleCwxNlocDK1uttyoZMzPLE9cwMyuIbh+8HhEBRGe3kzRNUq2k2vXr13c3hplZl6RRwwoQy8xKVFcbq3W7p8eTr/XJ+GpgZKv1RiRjHxIRsyKiJiJqqquruxjDzKxLUq1hBU1qZiWlq43VXGBqsjwVeLTV+OXJmTVnAZtbTbebmeWFa5iZFURFeytI+iVwDjBE0irgeuCHwBxJVwJvA5OT1Z8ALgTqgO3A5wuQ2cysw1zDzKyY1HJ4QbZqamqittaHKZgdSCQt7Clvo0nKvpCaWVFFhNoa95XXzczMzFLixsrMzMwsJW6szMzMzFLixsrMzMwsJW6szMzMzFLixsrMzMwsJW6szMzMzFLixsrMzMwsJW6szMzMzFLixsrMzMwsJW6szMzMzFLixsrMzMwsJW6szMzMzFLSbmMl6R5J9ZKWtBr7rqTVkhYntwtbPTZDUp2kZZLOL1RwM7OOcA0zs2LqyIzVbOCCNsZvi4ixye0JAEknAlOAk5JtfiKpPK2wZmZdMBvXMDMrknYbq4j4HbCxg883AXggInZGxFtAHXBGN/KZmXWLa5iZFVN3jrG6WtLLyTT7oGRsOLCy1TqrkrEPkTRNUq2k2vXr13cjhplZl6RWwwod1MxKR1cbqzuAo4GxwBrgls4+QUTMioiaiKiprq7uYgwzsy5JtYalnM3MSliXGquIWBcRTRHRDPyU96fKVwMjW606IhkzM8sN1zAzK5QuNVaShrW6OxHYfbbNXGCKpN6SjgRGAy90L6KZWbpcw8ysUCraW0HSL4FzgCGSVgHXA+dIGgsEsAL4AkBEvCppDrAUaAS+HBFNBUluZtYBrmFmVkyKiKwzUFNTE7W1Pv7T7EAiaWFPOT5JUvaF1MyKKiLU1rivvG5mZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilpt7GSNFLSAklLJb0q6ZpkfLCkeZLeSL4OSsYlaaakOkkvSzq90N+EmVlbXL/MrNg6MmPVCHw9Ik4EzgK+LOlEYDowPyJGA/OT+wDjgdHJbRpwR+qpzcw6xvXLzIqqor0VImINsCZZ3irpNWA4MAE4J1ntXuBZ4FvJ+M8jIoA/SqqSNCx5HsvIzp072bVrF83RDIAQZWVl9OnTh4qKdl8GZiXJ9atn6NevH3379t3n4xs3bqS5ubmIicz2rVO/USUdAZwGPA8MbVVs1gJDk+XhwMpWm61Kxj5QmCRNo+UvQkaNGtXZ3NaOzVs2s2rLKv649jlWVa5gWb+lrNm1ml2xi2aaqVAFfcv6MrrX8YxcexQnDT6FUwaO5fBDDqeysjLr+GapS7N+Jc+3p4ZZuiQxevRoxo8fzzHHHMOYMWM44YQT2ly3qamJJ598kq1bt/Lwww/zyiuvsGHDhiInNntfhxsrSf2BXwPXRsQWSXsei4iQFJ3ZcUTMAmYB1NTUdGpba1tDQwOvrVrK41sfYX6/x6krf53th2yjSclfcn0/+M8sxEs8TxwOvaIXg94bzKmv1fC3ZRfzqcPO4/Ahh9P652xWqtKuX8l2e2pYV7a3DxswYAATJ07k8ssv54wzzqB///4dqkFXXHEFAF/60pdYvnw5v//975kzZw7PPfcc27ZtK3Bqsw/qUGMlqRctRekXEfFQMrxu9xS5pGFAfTK+GhjZavMRyZgVSGNjIy/WvcB9793N01WPsXHABpp3N1P7qUnB+78LGrSLetby9MDH+C1P8ZH3jua/LLuMSw65nFHVnlG00uX6lX8DBgzgoosu4tprr2Xs2LGUlXXthPXy8nKOPfZYjj32WKZOncqiRYu45ZZbmDNnDk1NTSmnNmtbR84KFHA38FpE3NrqobnA1GR5KvBoq/HLk7NrzgI2+/iEwlm1fhXfXTaDyysn8KuBP2MD9e83VV3UQAN1Tcu4ufd3+ft3L+S+Jfeyffv2lBKbFY/rV75JYtKkSTzzzDPcc889nH766V1uqvZWVlbGuHHjmD17Nj/96U8ZPnx4Ks9r1h61HKO5nxWkTwL/DrwC7P6N/Y+0HKcwBxgFvA1MjoiNSSH7MXABsB34fETU7m8fNTU1UVu731VsL83NzSxY+Qz/1PAtllQsJpL/Uheij/pw4bsT+U71Dxh1qGevLB2SFkZETYH3UfD6lezHbwV20sCBA7n11luZPHky/fv3L/j+li1bxnXXXceDDz5Ie7/3zDoiItp8T6jdxqoY3Fh1zs6dO7nvjZ9xU//r2MiGwjRUexFlnNb4Uf6p6XbOPO6sgu/Per5iNFbF4saqc6qqqpg1axaTJk0q6nGcmzdv5otf/CKPPvqoZ+Gt2/bVWPnK6yVm586dzHzlFr7ffzobozhNFUDQzKKKF7i6cioLVj5TlH2aWc9z8MEHZ9JUQcss2ezZs7nrrruKMktmByY3ViWkoaGBO5f+mJlDbmQbW4gi/5EcBG/xBl/Xf+f51/9Y1H2bWekbOHAgd911F5/97GczO+O4srKSKVOmZJrBejY3ViUiInj4zQf5l0E3soMdRZup+lAOBX9peIvpXM3yNcszyWBmpWfgwIHceeedTJo0KesoSOLWW2/NZNbMej43ViVi8V8W8c8HfZvNbMqsqdotFLxSuYjvb57B1m1bM81iZqVh6tSpTJ48OTeNTFVVFTfffDOHH3541lGsh3FjVQK2bNvCD5q/zarGtzNvqt4XPNVnLve/da/PsDGz/RozZgzf//73c9NU7TZq1ChmzpxJeXl51lGsB3FjlXMRwa+X/4p/14KiH1O1P0Gwi53M6nc7y9fWZR3HzHKqvLyca665hoMPPjjrKG268MIL91y53SwNbqxybu2GtdzVdyYNsSvrKG16u+wt7tl0h69qbGZtOuWUU7j44ouzjrFPffr04dprr2XQoEFZR7Eewo1VjkUEj678Ncsrl+VqtuoDIpjbdw5vrHk96yRmljPl5eV85Stfye1s1W4nnHACF110UdYxrIdwY5Vj27Zv46EB99NAY9ZR9ikUrIu1PLbuER9rZWYfcPLJJzNx4sSsY7SrvLyc8ePH+1grS4UbqxxbvHIRf+71CuTmgPW2hZp5ctAjbNvuT5E3s/edffbZVFVVZR2jQ8aPH8+4ceOyjmE9gBurHPvNjsfYHu9mHaNdQVBX/hqvrVyadRQzy4ny8vJcXLOqo/r378/IkSOzjmE9gBurnNrx3g7+VLUwv8dW7WV787vU7vLV2M2sxejRo/noRz+adYxOueyyy7KOYD1Au42VpJGSFkhaKulVSdck49+VtFrS4uR2YattZkiqk7RM0vmF/AZ6qvp36nkjSmcGqFnNLG7wB2lbvrh+Zad3795UVlZmHaNTRo4c6c8QtG6r6MA6jcDXI+IlSQOAhZLmJY/dFhE3t15Z0onAFOAk4HDgaUnHRoTPx++EjfEO28pK66rmf6l+k3e3v0u/g/plHcVsN9evjEyaNImKio78ismPU089lVGjRrF0aen8UWv50+6MVUSsiYiXkuWtwGvA8P1sMgF4ICJ2RsRbQB1wRhphDyRL31nCTt7LOkanrG5cyaYtm7KOYbaH61d2SuWgdbO0deoYK0lHAKcBzydDV0t6WdI9knZfXW04sLLVZqvYfyGzNryzfQPNJXb5gl2xk8am/F4awg5srl9mVgwdbqwk9Qd+DVwbEVuAO4CjgbHAGuCWzuxY0jRJtZJq169f35lNDwgNTQ3k61O12tcUTb4Cu+VS2vUrec49NSzNrGZW2jrUWEnqRUtR+kVEPAQQEesioikimoGf8v50+Wqg9TmrI5KxD4iIWRFRExE11dXV3fkezMz2qRD1K3mOPTWscOnNrNR05KxAAXcDr0XEra3Gh7VabSKwJFmeC0yR1FvSkcBo4IX0Ih8YKssrc35Z0A8rV7mvXGy54vplZsXWkVM2PgH8A/CKpMXJ2D8Cl0gaS8tlwVcAXwCIiFclzQGW0nJGzpd9Rk3nDelXTbnKaKQ56ygd1lt9qCgvrbOArMdz/TKzomr3t2BEPAdtHu7zxH62uRG4sRu5DngnDDqJ3o19aFTpfEzMiF6jqDq4KusYZnu4fmVn3bp1RAQtk4alo7m5dP6YtXzylddzalDZYPrHgKxjdMrItUf5GlZmBsAjjzxSciezvPDCC6xYsSLrGFbi3Fjl1NAhQzleJ2Udo8PKKGNsfx/Da2Ytdu3axY4dO7KO0Snbtm3jvfdK6/qBlj9urHKqT+8+nLJpHCqRiy4cpH7U9D4z6xhmlhNvvPEGzz//fPsr5sgTT+zzHWKzDnNjlWOf7vsZ+in/n1ulEMfvOpkThp6YdRQzy4mI4P777886Rodt2rSJ3/3ud1nHsB7AjVWOjRk5lhPeOzX3s1ZSGedrgo+vMrMP+MMf/sCGDRuyjtEhy5Yt82cEWircWOVY/379mVTxOSqiV9ZR9kMMi+F85qCJJXf2j5kV1ptvvsmSJUvaXzFjjY2N/PjHP6ahoSHrKNYDuLHKub8dPJHRZSdA5LNpEeKi7VM4eujRWUcxs5xpaGjg9ttvZ9euXVlH2a9FixYxd+7crGNYD+HGKucOrTqUaTuvpVKVWUf5EIU4svxorjjkC77iupm16emnn+bxxx/POsY+RQQ/+tGP2LJlS9ZRrIdwY5Vzkpg4fBKfajw/d8daVZb15ovbvsFRhx2VdRQzy6l3332X6dOnU19fn3WUNs2dO5dHHnkk6xjWg7ixKgH9+/XnWxU3MEpH0fZFpIuvPMr5TNMk/v6Iy7KOYmY59/rrrzN9+vTcXTB07dq13HDDDWzdujXrKNaDuLEqEad+5FT+57s/oCoGoYyPtxLilB2nM6PPDfTr6zMBzax9DzzwAHfeeWduPjJm3bp1fO5zn+Oll17KOor1MG6sSoQk/u7YiXx9w/X01UGZvS0oxJFlo/nfB/9fjjz8yEwymFnp2bFjB9/4xjeYNWtW1lFobm7mjjvuYP78+VlHsR6o3cZKUh9JL0j6k6RXJX0vGT9S0vOS6iT9Smo5ulpS7+R+XfL4EQX+Hg4YFRUV/LcxV/G1TddzcFQVvbkSYnT5CczkHk4fcXpR923WVa5h+bFjxw5++MMf8uCDD2Y2c9XU1MRPfvITbrrppkz2bz1fR2asdgLnRsQYYCxwgaSzgJuA2yLiGOCvwJXJ+lcCf03Gb0vWs5RUVlZy9UnXcv3mmzlUhxXlMgxCiDJq3vs4P2m6j4+N+kTB92mWItewHHn77be54oormDVrFhFR1H3X19dz1VVX8c1vftOfCWgF025jFS22JXd7JbcAzgX+NRm/F7goWZ6Q3Cd5/G/kK0emqlevXlw+5vPc3fwg43aeSTkVBZu9UoiD6Mcl+q/8bMiDnHbEaQXZj1mhuIblz/bt2/na177GjTfeWJQrs0cEa9as4dJLL+Wuu+4quQ+HttLSoWOsJJVLWgzUA/OA5cCmiGhMVlkFDE+WhwMrAZLHNwOHpJjZaDnm6mNHfoJ7hzzEVzbPoLpsaOoHtZdTwUmM5bamu/lfQ2cybMiwVJ/frFhcw/Jnx44dfOc732Hy5MkFPdZpx44dPPTQQ3z84x/3MVVWFB1qrCKiKSLGAiOAM4Dju7tjSdMk1UqqXb9+fXef7oA1bMgwZpx8PffzOP/QeBXVGoqirKXJ6uQsu5L/KqIXx3My39l+Ew8MeJyLj55M3z59C/MNmBVBoWtYd5/rQLZgwQKmTJnCjBkzWLFiRWpvDzY0NPDUU08xYcIELr30UlasWJHK85q1R519EUu6DtgBfAs4LCIaJX0M+G5EnC/pqWT5PyRVAGuB6tjPjmpqaqK21rWpu5qamqhbXcdTWx7j3/o+Sp3+zBZtolFNBEFbnVbL0VNlVFLJIRzKuMYzOX/XBM4ddh7Vg6qL/03YAUPSwoioyWC/qdcwScU9WKiHOuywwzjttNP46le/yplnnknfvn3p1avjn5Xa0NDAhg0bmDdvHvfddx/PPvusP//PCiai7beJKtrbUFI10BARmyT1Bc6j5WDOBcAk4AFgKvBossnc5P5/JI8/s7+CZOkpLy/nuFHHcRzH8flt0/jPTf/JS2teZGXVm7y8azEbG96hoXkXTTTRS72oLOvNqD5HcOJ7p3Jk2TGcNnwch/Q/hMrK/H18jllXuYaVjrVr1/Lkk0/y7LPPMnjwYM4++2yOO+44Lr74Yg466KB9brd48WIWLlzI8uXL+e1vf0t9fX3RD4w3263dGStJp9JyIGc5LW8dzomIGyQdRUtBGgwsAj4XETsl9QH+H3AasBGYEhFv7m8fnrEqrIigqamJ5ubmPcVm97G45eXl/pw/y0SxZqyKUcM8Y1VYvXv33lOz2tLY2EhjY+M+HzcrhH3NWHX6rcBCcGNlduDJ6q3AQnBjZXbg2Vdj5Suvm5mZmaXEjZWZmZlZStxYmZmZmaXEjZWZmZlZStxYmZmZmaXEjZWZmZlZStxYmZmZmaXEjZWZmZlZStxYmZmZmaXEjZWZmZlZStxYmZmZmaXEjZWZmZlZStptrCT1kfSCpD9JelXS95Lx2ZLekrQ4uY1NxiVppqQ6SS9LOr3A34OZWZtcv8ys2Co6sM5O4NyI2CapF/CcpCeTx/5HRPzrXuuPB0YntzOBO5KvZmbF5vplZkXV7oxVtNiW3O2V3GI/m0wAfp5s90egStKw7kc1M+sc1y8zK7YOHWMlqVzSYqAemBcRzycP3ZhMl98mqXcyNhxY2WrzVcmYmVnRuX6ZWTF1qLGKiKaIGAuMAM6QdDIwAzge+CgwGPhWZ3YsaZqkWkm169ev71xqM7MOKkT9gg/WsDTzmllp69RZgRGxCVgAXBARa5Lp8p3Az4AzktVWAyNbbTYiGdv7uWZFRE1E1FRXV3cpvJlZR6VZv5Ln21PDChjbzEpMR84KrJZUlSz3Bc4D/rz7uANJAi4CliSbzAUuT86uOQvYHBFrCpDdzGy/XL/MrNg6clbgMOBeSeW0NGJzIuIxSc9IqgYELAauStZ/ArgQqAO2A59PPbWZWce4fplZUSlifyfIFEdNTU3U1vowBbMDiaSFPeVtNEnZF1IzK6qIUFvjvvK6mZmZWUrcWJmZmZmlxI2VmZmZWUrcWJmZmZmlxI2VmZmZWUrcWJmZmZmlxI2VmZmZWUrcWJmZmZmlxI2VmZmZWUrcWJmZmZmlxI2VmZmZWUrcWJmZmZmlxI2VmZmZWUrcWJmZmZmlxI2VmZmZWUrcWJmZmZmlRBGRdQYkbQWWZZ2jg4YAG7IO0QHOmb5SyVoqOT8SEdVZh0hDCdWwUnltlEpOKJ2szpmufdavimIn2YdlEVGTdYiOkFRbClmdM32lkrVUcvYwJVHDSuW1USo5oXSyOmfx+K1AMzMzs5S4sTIzMzNLSV4aq1lZB+iEUsnqnOkrlaylkrMnKZV/c+dMX6lkdc4iycXB62ZmZmY9QV5mrMzMzMxKXuaNlaQLJC2TVCdpesZZ7pFUL2lJq7HBkuZJeiP5OigZl6SZSe6XJZ1exJwjJS2QtFTSq5KuyXHWPpJekPSnJOv3kvEjJT2fZPqVpMpkvHdyvy55/IhiZU32Xy5pkaTH8ppT0gpJr0haLKk2Gcvdz/5AkKf6leRxDUs3p+tXYXL26BqWaWMlqRz4P8B44ETgEkknZhhpNnDBXmPTgfkRMRqYn9yHlsyjk9s04I4iZQRoBL4eEScCZwFfTv7d8ph1J3BuRIwBxgIXSDoLuAm4LSKOAf4KXJmsfyXw12T8tmS9YroGeK3V/bzm/FREjG11WnIef/Y9Wg7rF7iGpc31q3B6bg2LiMxuwMeAp1rdnwHMyDjTEcCSVveXAcOS5WG0XK8G4E7gkrbWyyDzo8B5ec8KHAS8BJxJywXgKvZ+HQBPAR9LliuS9VSkfCNo+R/6XOAxQDnNuQIYstdYrn/2PfGWx/qV5HANK0xG16/0svboGpb1W4HDgZWt7q9KxvJkaESsSZbXAkOT5VxkT6ZwTwOeJ6dZk+npxUA9MA9YDmyKiMY28uzJmjy+GTikSFFvB74JNCf3D8lpzgB+I2mhpGnJWC5/9j1cqfzb5vq1kfca5vpVED26huXlyuslISJCUm5Oo5TUH/g1cG1EbJG057E8ZY2IJmCspCrgYeD4bBN9mKTPAPURsVDSORnHac8nI2K1pEOBeZL+3PrBPP3sLV/y9toohRrm+lUQPbqGZT1jtRoY2er+iGQsT9ZJGgaQfK1PxjPNLqkXLQXpFxHxUJ6z7hYRm4AFtExJV0na3di3zrMna/L4QOCdIsT7BPB3klYAD9Aynf4vOcxJRKxOvtbTUujPIOc/+x6qVP5tc/naKLUa5vqVnp5ew7JurF4ERidnLlQCU4C5GWfa21xgarI8lZZjAXaPX56csXAWsLnVNGZBqeXPuruB1yLi1pxnrU7+0kNSX1qOo3iNlgI1aR9Zd38Pk4BnInljvZAiYkZEjIiII2h5HT4TEZflLaekfpIG7F4GPg0sIYc/+wNAKdQvyOFro1RqmOtX+g6IGpb1QV7AhcDrtLxv/e2Ms/wSWAM00PI+7pW0vO88H3gDeBoYnKwrWs4IWg68AtQUMecnaXmP+mVgcXK7MKdZTwUWJVmXANcl40cBLwB1wINA72S8T3K/Lnn8qAxeB+cAj+UxZ5LnT8nt1d3/z+TxZ38g3PJUv5I8rmHp5nT9Sj9fj69hvvK6mZmZWUqyfivQzMzMrMdwY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWEjdWZmZmZilxY2VmZmaWkv8PXdQ18M0f9SkAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 2, figsize=(10, 5))\n", + "\n", + "_image, _ = dataset[1]\n", + "\n", + "axes[0].imshow(_image)\n", + "axes[1].imshow(to_black_and_white(_image), cmap='gray')\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dummy ML: Image -> \"Features\" -> Answer" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Intro to Torch" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "# https://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html\n", + "\n", + "a = torch.tensor([2., 3.], requires_grad=True)\n", + "b = torch.tensor([6., 4.], requires_grad=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([2., 3.], requires_grad=True)" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([6., 4.], requires_grad=True)" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$ Q = 3 a^3 - b^2 $$" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "Q = 3 * a ** 3 - b ** 2" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([-12., 65.], grad_fn=)" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Q" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "Q.sum().backward()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$ \\frac{\\partial Q}{\\partial a} = 9 a^2, \\quad \\frac{\\partial Q}{\\partial b} = -2b^2 $$" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [], + "source": [ + "assert torch.allclose(a.grad, 9 * a ** 2)\n", + "assert torch.allclose(b.grad, -2 * b)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Handmade Linear Model" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "class LinearModel1(Module):\n", + " def __init__(self, in_features: int, out_features: int):\n", + " super().__init__()\n", + " \n", + " self.weight = nn.Parameter(\n", + " torch.ones(\n", + " size=(out_features, in_features), requires_grad=True\n", + " )\n", + " )\n", + " self.bias = nn.Parameter(\n", + " torch.ones(size=(out_features, 1), requires_grad=True)\n", + " )\n", + " \n", + " def forward(self, input):\n", + " # input: Batch X Width X Height X InChannels\n", + " \n", + " input = input.flatten(1) # Batch X InFeatures\n", + " input = input.unsqueeze(-1) # Batch X InFeatures X 1\n", + " \n", + " output = torch.matmul(self.weight, input) + self.bias # Batch X OutFeatures X 1\n", + " output = output.squeeze(-1) # Batch X OutFeatures\n", + " \n", + " return output" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "tensor([[2369206., 2369206., 2369206.]], grad_fn=)" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "_image, _ = dataset[0]\n", + "_bw_image = to_black_and_white(_image)\n", + "\n", + "model = LinearModel1(in_features=_bw_image.size, out_features=3)\n", + "\n", + "_bw_image = _bw_image.squeeze(-1)\n", + "_bw_image = _bw_image[np.newaxis, np.newaxis, :, :]\n", + "\n", + "model(torch.FloatTensor(_bw_image) * 1.0)" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "del model" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "_image, _ = dataset[0]\n", + "_bw_image = to_black_and_white(_image)\n", + "\n", + "IMAGE_NIM_PIXELS = _bw_image.size" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "240000" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "IMAGE_NIM_PIXELS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Train-Test Split. Data Loaders" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "all_file_names = os.listdir(DATA_FOLDER_GENERATED)" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(42)\n", + "\n", + "val_size = 0.2\n", + "train_file_names = np.random.choice(\n", + " all_file_names, size=int(len(all_file_names) * (1.0 - val_size)),\n", + " replace=False,\n", + ")\n", + "val_file_names = [\n", + " f for f in all_file_names if f not in train_file_names\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "batch_size = 4\n", + "\n", + "\n", + "train_data = GeometricShapesDataset(\n", + " folder_path=DATA_FOLDER_GENERATED,\n", + " file_names=train_file_names,\n", + " transform=to_black_and_white\n", + ")\n", + "val_data = GeometricShapesDataset(\n", + " folder_path=DATA_FOLDER_GENERATED,\n", + " file_names=val_file_names,\n", + " transform=to_black_and_white\n", + ")\n", + "\n", + "train_dataloader = DataLoader(\n", + " train_data, batch_size=batch_size,\n", + " shuffle=True,\n", + ")\n", + "val_dataloader = DataLoader(\n", + " val_data, batch_size=batch_size,\n", + " shuffle=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "torch.Size([4, 400, 600, 1])\n", + "tensor([1, 1, 0, 0])\n" + ] + } + ], + "source": [ + "batch, batch_labels = next(iter(train_dataloader))\n", + "\n", + "print(batch.shape)\n", + "print(batch_labels)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [], + "source": [ + "CLASS_SIZES = {\n", + " label: 0\n", + " for label in GeometricShapesDataset._LABEL_ID_TO_NAME\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [], + "source": [ + "for _, batch_labels in train_dataloader:\n", + " for label in CLASS_SIZES:\n", + " CLASS_SIZES[label] += (batch_labels == label).sum().item()" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{0: 76, 1: 84, 2: 20}" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "CLASS_SIZES" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "180" + ] + }, + "execution_count": 54, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum(v for v in CLASS_SIZES.values())" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "NUM_TRAIN_IMAGES = len(train_file_names)" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [], + "source": [ + "assert sum(v for v in CLASS_SIZES.values()) == NUM_TRAIN_IMAGES" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [], + "source": [ + "CLASS_WEIGHTS = {\n", + " label: (NUM_TRAIN_IMAGES - CLASS_SIZES[label]) / NUM_TRAIN_IMAGES\n", + " for label in CLASS_SIZES\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{0: 0.5777777777777777, 1: 0.5333333333333333, 2: 0.8888888888888888}" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "CLASS_WEIGHTS" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "WEIGHTS = list(CLASS_WEIGHTS.values())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Train Loop" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [], + "source": [ + "model = LinearModel1(IMAGE_NIM_PIXELS, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Parameter containing:\n", + "tensor([[1., 1., 1., ..., 1., 1., 1.],\n", + " [1., 1., 1., ..., 1., 1., 1.],\n", + " [1., 1., 1., ..., 1., 1., 1.]], requires_grad=True)\n", + "Parameter containing:\n", + "tensor([[1.],\n", + " [1.],\n", + " [1.]], requires_grad=True)\n" + ] + } + ], + "source": [ + "for p in model.parameters():\n", + " print(p)" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 157179.047. LR: 0.010: 12%|█▎ | 1/8 [00:03<00:24, 3.46s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "8826236.079808235\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.008: 25%|██▌ | 2/8 [00:06<00:18, 3.16s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "8178351.90625\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.007: 38%|███▊ | 3/8 [00:09<00:15, 3.06s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5564203.78515625\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.005: 50%|█████ | 4/8 [00:12<00:11, 2.87s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2318186.6997070312\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.003: 62%|██████▎ | 5/8 [00:14<00:08, 2.73s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1051145.9814453125\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.001: 75%|███████▌ | 6/8 [00:17<00:05, 2.78s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "203954.09350585938\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.000: 88%|████████▊ | 7/8 [00:19<00:02, 2.60s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "113087.8125\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 60236.031. LR: 0.000: 100%|██████████| 8/8 [00:22<00:00, 2.83s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "72376.26611328125\n", + "Finished Training\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "num_epochs = 8\n", + "\n", + "# https://pytorch.org/docs/stable/generated/torch.nn.CrossEntropyLoss.html\n", + "criterion = CrossEntropyLoss(\n", + " weight=torch.FloatTensor(WEIGHTS)\n", + ")\n", + "\n", + "optimizer = SGD(model.parameters(), lr=0.01)\n", + "\n", + "# https://www.kaggle.com/code/isbhargav/guide-to-pytorch-learning-rate-scheduling/notebook\n", + "scheduler = CosineAnnealingLR(\n", + " optimizer, T_max=len(train_dataloader) * num_epochs\n", + ")\n", + "\n", + "with tqdm.tqdm(total=num_epochs) as pbar:\n", + " for epoch in range(num_epochs):\n", + " total_loss = 0\n", + " \n", + " for i, data in enumerate(train_dataloader):\n", + " # get the inputs; data is a list of [inputs, labels]\n", + " inputs, labels = data\n", + " inputs = 1.0 * inputs # TODO\n", + "\n", + " # zero the parameter gradients\n", + " optimizer.zero_grad()\n", + "\n", + " # forward + backward + optimize\n", + " outputs = model(inputs)\n", + " loss = criterion(outputs, labels)\n", + " loss.backward()\n", + " optimizer.step()\n", + " \n", + " total_loss += loss.item()\n", + " last_lr = scheduler.get_last_lr()[0]\n", + " \n", + " scheduler.step()\n", + "\n", + " pbar.set_description(f'Loss: {loss.item():.3f}. LR: {last_lr:.3f}')\n", + " \n", + " print(total_loss)\n", + " \n", + " pbar.update(1)\n", + "\n", + "print('Finished Training')" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "class Trainer:\n", + " def __init__(\n", + " self,\n", + " model,\n", + " loss,\n", + " optimizer,\n", + " scheduler,\n", + " train_dataloader,\n", + " max_num_epochs: int = 8\n", + " ):\n", + " self.model = model\n", + " self.criterion = loss\n", + " self.optimizer = optimizer\n", + " self.scheduler = scheduler\n", + " self.train_dataloader = train_dataloader\n", + " self.max_num_epochs = max_num_epochs\n", + "\n", + " def train(self):\n", + " with tqdm.tqdm(total=self.max_num_epochs) as pbar:\n", + " for epoch in range(self.max_num_epochs):\n", + " total_loss = 0\n", + "\n", + " for i, data in enumerate(self.train_dataloader):\n", + " # get the inputs; data is a list of [inputs, labels]\n", + " inputs, labels = data\n", + " inputs = 1.0 * inputs # TODO\n", + "\n", + " # zero the parameter gradients\n", + " self.optimizer.zero_grad()\n", + "\n", + " # forward + backward + optimize\n", + " outputs = self.model(inputs)\n", + " loss = self.criterion(outputs, labels)\n", + " loss.backward()\n", + " self.optimizer.step()\n", + "\n", + " total_loss += loss.item()\n", + " last_lr = self.scheduler.get_last_lr()[0]\n", + "\n", + " self.scheduler.step()\n", + "\n", + " pbar.set_description(f'Loss: {loss.item():.3f}. LR: {last_lr:.3f}')\n", + "\n", + " print(f'Epoch total loss: {total_loss:.3f}')\n", + "\n", + " pbar.update(1)\n", + "\n", + " print('Finished Training')" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [], + "source": [ + "model = LinearModel1(\n", + " IMAGE_NIM_PIXELS,\n", + " len(GeometricShapesDataset._LABEL_NAME_TO_ID)\n", + ")\n", + "criterion = CrossEntropyLoss(\n", + " weight=torch.FloatTensor(WEIGHTS)\n", + ")\n", + "optimizer = SGD(model.parameters(), lr=0.01)\n", + "scheduler = CosineAnnealingLR(\n", + " optimizer, T_max=len(train_dataloader) * num_epochs\n", + ")\n", + "num_epochs = 8\n", + "\n", + "trainer = Trainer(\n", + " model=model,\n", + " loss=criterion,\n", + " optimizer=optimizer,\n", + " scheduler=scheduler,\n", + " train_dataloader=train_dataloader,\n", + " max_num_epochs=num_epochs,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.010: 12%|█▎ | 1/8 [00:02<00:13, 1.99s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 8738589.726\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.008: 25%|██▌ | 2/8 [00:05<00:16, 2.78s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 7527236.627\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.007: 38%|███▊ | 3/8 [00:07<00:11, 2.37s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 4473548.826\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.005: 50%|█████ | 4/8 [00:10<00:10, 2.65s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 1842945.598\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.003: 62%|██████▎ | 5/8 [00:12<00:07, 2.48s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 941734.783\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.001: 75%|███████▌ | 6/8 [00:15<00:05, 2.58s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 543031.773\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.000: 88%|████████▊ | 7/8 [00:17<00:02, 2.56s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 85302.315\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.000: 100%|██████████| 8/8 [00:21<00:00, 2.64s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 79024.109\n", + "Finished Training\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "trainer.train()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Torch Linear Model" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [], + "source": [ + "class LinearModel(Module):\n", + " def __init__(\n", + " self,\n", + " in_features: int,\n", + " out_features: int,\n", + " bias: bool = True\n", + " ):\n", + " super().__init__()\n", + " \n", + " self.linear = nn.Linear(in_features, out_features, bias)\n", + " \n", + " def forward(self, input):\n", + " # input: Batch X Width X Height X InChannels\n", + "\n", + " input = input.flatten(1) # Batch X InFeatures\n", + " output = self.linear(input) # Batch X OutFeatures\n", + "\n", + " return output" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [], + "source": [ + "model = LinearModel(\n", + " IMAGE_NIM_PIXELS,\n", + " len(GeometricShapesDataset._LABEL_NAME_TO_ID)\n", + ")\n", + "criterion = nn.CrossEntropyLoss(\n", + " weight=torch.FloatTensor(WEIGHTS)\n", + ")\n", + "optimizer = SGD(model.parameters(), lr=0.01)\n", + "scheduler = CosineAnnealingLR(\n", + " optimizer, T_max=len(train_dataloader) * num_epochs\n", + ")\n", + "num_epochs = 8\n", + "\n", + "trainer = Trainer(\n", + " model=model,\n", + " loss=criterion,\n", + " optimizer=optimizer,\n", + " scheduler=scheduler,\n", + " train_dataloader=train_dataloader,\n", + " max_num_epochs=num_epochs,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 289657.000. LR: 0.010: 12%|█▎ | 1/8 [00:02<00:14, 2.04s/it]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 10216771.611\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 24233.479. LR: 0.009: 25%|██▌ | 2/8 [00:05<00:16, 2.78s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 6904853.602\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 51918.918. LR: 0.007: 38%|███▊ | 3/8 [00:07<00:13, 2.64s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 5476394.035\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.005: 50%|█████ | 4/8 [00:11<00:11, 2.94s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 2085807.211\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.003: 62%|██████▎ | 5/8 [00:14<00:09, 3.08s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 761269.438\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.001: 75%|███████▌ | 6/8 [00:17<00:05, 2.87s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 231287.395\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.000: 88%|████████▊ | 7/8 [00:20<00:02, 2.91s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 246003.281\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loss: 0.000. LR: 0.000: 100%|██████████| 8/8 [00:23<00:00, 2.88s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch total loss: 45245.589\n", + "Finished Training\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "trainer.train()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Model Quality Assessment: Classification Quality Metrics" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [], + "source": [ + "class ClassificationMetrics:\n", + " def __init__(self):\n", + " self.true_positive: int = 0\n", + " self.true_negative: int = 0\n", + " self.false_positive: int = 0\n", + " self.false_negative: int = 0\n", + " \n", + " @property\n", + " def precision(self) -> float:\n", + " return self.true_positive / (\n", + " self.true_positive + self.false_positive\n", + " )\n", + "\n", + " @property\n", + " def recall(self) -> float:\n", + " return self.true_positive / (\n", + " self.true_positive + self.false_negative\n", + " )\n", + " \n", + " @property\n", + " def accuracy(self) -> float:\n", + " p = self.true_positive + self.false_negative\n", + " n = self.true_negative + self.false_positive\n", + " \n", + " return (self.true_positive + self.true_negative) / (p + n)\n", + "\n", + " def update(self, other: 'ClassificationMetrics') -> None:\n", + " self.true_positive = self.true_positive + other.true_positive\n", + " self.false_positive = self.false_positive + other.false_positive\n", + " self.true_negative = self.true_negative + other.true_negative\n", + " self.false_negative = self.false_negative + other.false_negative\n", + " \n", + " def __str__(self):\n", + " return (\n", + " f'('\n", + " f'Precision={self.precision:.2f},'\n", + " f' Recall={self.recall:.2f},'\n", + " f' Accuracy={self.accuracy:.2f}'\n", + " f')'\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [], + "source": [ + "def validate(model, val_dataloader) -> Dict[int, ClassificationMetrics]:\n", + " model.eval()\n", + "\n", + " label2metrics = dict()\n", + "\n", + " for label in GeometricShapesDataset._LABEL_ID_TO_NAME:\n", + " label2metrics[label] = ClassificationMetrics()\n", + "\n", + " for i, data in enumerate(val_dataloader):\n", + " inputs, labels = data\n", + " inputs = 1.0 * inputs\n", + "\n", + " outputs = model(inputs)\n", + " predicted_labels = torch.argmax(outputs, axis=1)\n", + "\n", + " for label in GeometricShapesDataset._LABEL_ID_TO_NAME:\n", + " label_indices = torch.where(labels == label)[0]\n", + " nonlabel_indices = torch.where(labels != label)[0]\n", + "\n", + " metrics = ClassificationMetrics()\n", + "\n", + " metrics.true_positive = (\n", + " predicted_labels[label_indices] == label\n", + " ).sum().item()\n", + " metrics.true_negative = (\n", + " predicted_labels[nonlabel_indices] != label\n", + " ).sum().item()\n", + " metrics.false_positive = (\n", + " predicted_labels[nonlabel_indices] == label\n", + " ).sum().item()\n", + " metrics.false_negative = (\n", + " predicted_labels[label_indices] != label\n", + " ).sum().item()\n", + "\n", + " label2metrics[label].update(metrics)\n", + "\n", + " return label2metrics" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [], + "source": [ + "label2metrics = validate(model, train_dataloader)" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(Precision=1.00, Recall=0.97, Accuracy=0.99)\n", + "(Precision=1.00, Recall=1.00, Accuracy=1.00)\n", + "(Precision=0.91, Recall=1.00, Accuracy=0.99)\n" + ] + } + ], + "source": [ + "for l in label2metrics:\n", + " print(label2metrics[l])" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [], + "source": [ + "label2metrics = validate(model, val_dataloader)" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10 3\n", + "16 4\n", + "2 10\n" + ] + } + ], + "source": [ + "for l in label2metrics:\n", + " print(\n", + " label2metrics[l].true_positive, label2metrics[l].false_positive\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(Precision=0.77, Recall=0.42, Accuracy=0.62)\n", + "(Precision=0.80, Recall=1.00, Accuracy=0.91)\n", + "(Precision=0.17, Recall=0.40, Accuracy=0.71)\n" + ] + } + ], + "source": [ + "for l in label2metrics:\n", + " print(label2metrics[l])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "https://datascience.stackexchange.com/questions/15989/micro-average-vs-macro-average-performance-in-a-multiclass-classification-settin" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [], + "source": [ + "def accuracy_average(metrics: Iterable[ClassificationMetrics]):\n", + " return sum(\n", + " [m.accuracy for m in metrics]\n", + " ) / len(metrics)\n", + "\n", + "def precision_macro_average(metrics: Iterable[ClassificationMetrics]):\n", + " return sum(\n", + " [m.precision for m in metrics]\n", + " ) / len(metrics)\n", + "\n", + "def precision_micro_average(metrics: Iterable[ClassificationMetrics]):\n", + " return sum(\n", + " [m.true_positive for m in metrics]\n", + " ) / sum(\n", + " [m.true_positive + m.false_positive for m in metrics]\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.7481481481481481" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "accuracy_average(label2metrics.values())" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.5786324786324787" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "precision_macro_average(label2metrics.values())" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.6222222222222222" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "precision_micro_average(label2metrics.values())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## \"Blackbox-Like\" ML: Image -> Answer" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "* https://stackoverflow.com/questions/42883547/intuitive-understanding-of-1d-2d-and-3d-convolutions-in-convolutional-neural-n\n", + "* https://github.com/vdumoulin/conv_arithmetic\n", + "* https://ezyang.github.io/convolution-visualizer/index.html\n", + "* https://stats.stackexchange.com/questions/295397/what-is-the-difference-between-conv1d-and-conv2d\n", + "\n", + "\n", + "* https://datascience.stackexchange.com/questions/51470/what-are-the-differences-between-convolutional1d-convolutional2d-and-convoluti\n", + "* https://towardsdatascience.com/types-of-convolutions-in-deep-learning-717013397f4d" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Convolution (2D)\n", + "\n", + "Blue maps are inputs, and cyan maps are outputs.\n", + "\n", + "![](./docs/images/no_padding_no_strides.gif)\n", + "\n", + "Source: https://github.com/vdumoulin/conv_arithmetic" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [], + "source": [ + "# https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html\n", + "\n", + "class ConvModel(nn.Module):\n", + " def __init__(self):\n", + " super().__init__()\n", + " \n", + " self.conv1 = nn.Conv2d(\n", + " in_channels=1, out_channels=2, kernel_size=2, stride=2\n", + " )\n", + " self.conv2 = nn.Conv2d(\n", + " in_channels=2, out_channels=4, kernel_size=2, stride=2\n", + " )\n", + " self.pool = nn.MaxPool2d(kernel_size=2, stride=4)\n", + " self.fc1 = nn.Linear(216, 64)\n", + " self.fc2 = nn.Linear(64, 3)\n", + "\n", + " def forward(self, x):\n", + " # x: Batch X Width X Height X InChannels=1\n", + "\n", + " # Remove the only channel\n", + " x = x.squeeze(-1) # Batch X Width X Height\n", + " \n", + " # Make the dimension \"torch-compatible\": the second is \"num channels\"\n", + " x = x.unsqueeze(1) # Batch X InChannels=1 X Width X Height\n", + " \n", + " x = self.pool(F.relu(self.conv1(x)))\n", + " x = self.pool(F.relu(self.conv2(x)))\n", + " \n", + " x = torch.flatten(x, 1)\n", + " \n", + " x = F.relu(self.fc1(x))\n", + " x = self.fc2(x) # Batch X OutFeatures\n", + " \n", + " return x" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [], + "source": [ + "model = ConvModel()\n", + "\n", + "criterion = nn.CrossEntropyLoss(\n", + " weight=torch.FloatTensor(WEIGHTS)\n", + ")\n", + "optimizer = SGD(model.parameters(), lr=0.01)\n", + "scheduler = CosineAnnealingLR(\n", + " optimizer, T_max=len(train_dataloader) * num_epochs\n", + ")\n", + "num_epochs = 5\n", + "\n", + "trainer = Trainer(\n", + " model=model,\n", + " loss=criterion,\n", + " optimizer=optimizer,\n", + " scheduler=scheduler,\n", + " train_dataloader=train_dataloader,\n", + " max_num_epochs=num_epochs,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 0%| | 0/5 [00:00" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "infer(model, train_data[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Image is square.\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "infer(model, train_data[100])" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Image is circle.\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "infer(model, train_data[170])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Under the Hood" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example 1" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": {}, + "outputs": [], + "source": [ + "image, _ = train_data[150]" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(image)" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "image = torch.FloatTensor(image)\n", + "input = image.unsqueeze(0)\n", + "input = input.squeeze(-1)\n", + "input = input.unsqueeze(1)\n", + "\n", + "output_batch = F.relu(model.conv1(input))\n", + "output_batch = model.pool(output_batch)\n", + "output = output_batch[0]\n", + "\n", + "plt.imshow(\n", + " output.detach().numpy()[1]\n", + ")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWEAAAD4CAYAAAA94VfoAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/MnkTPAAAACXBIWXMAAAsTAAALEwEAmpwYAAALkklEQVR4nO3dX4ilhX2H8efrzLjrbkxtiQ12V6oXQZBAs2HYtDWEVmO6NmJyqZBclML0oinaFkLSm5L7EnJTCovaWGIU6x8IYqOWGKzQbJxdTeO6plhr425t1xJS3dCuu/rrxZwNU7vZOducd34n8z4fGHbO2cOZL8vsM++858ycVBWSpB4XdA+QpDEzwpLUyAhLUiMjLEmNjLAkNVoc4k4vzLbazs4h7lqSfib9Nz/izTqZd14/SIS3s5MPXfDRIe5akn4mHXj7b896vacjJKmREZakRkZYkhoZYUlqZIQlqZERlqRGRliSGhlhSWpkhCWpkRGWpEZGWJIaGWFJamSEJanRVBFOsi/J95K8mORzQ4+SpLHYMMJJFoA/B24ArgZuSXL10MMkaQymORLeC7xYVS9V1ZvAvcAnhp0lSeMwTYR3Aa+su3x0ct3/kmQlyWqS1VOcnNU+SdrSZvbAXFXtr6rlqlpeYtus7laStrRpInwMuHzd5d2T6yRJP6VpIvw08L4kVya5ELgZ+NqwsyRpHDZ8oc+qOp3kM8CjwAJwZ1UdHnyZJI3AVK+2XFWPAI8MvEWSRsefmJOkRkZYkhoZYUlqZIQlqZERlqRGRliSGhlhSWpkhCWpkRGWpEZGWJIaGWFJamSEJamREZakRkZYkhoZYUlqZIQlqZERlqRGRliSGhlhSWpkhCWpkRGWpEZGWJIaGWFJamSEJamREZakRkZYkhoZYUlqZIQlqdGGEU5yZ5LjSZ7bjEGSNCbTHAl/Gdg38A5JGqUNI1xVTwI/2IQtkjQ6i7O6oyQrwArAdnbM6m4laUub2QNzVbW/qparanmJbbO6W0na0nx2hCQ1MsKS1Giap6jdA/w9cFWSo0l+d/hZkjQOGz4wV1W3bMYQSRojT0dIUiMjLEmNjLAkNTLCktTICEtSIyMsSY2MsCQ1MsKS1MgIS1IjIyxJjYywJDUywpLUyAhLUiMjLEmNjLAkNTLCktTICEtSIyMsSY2MsCQ1MsKS1MgIS1IjIyxJjYywJDUywpLUyAhLUiMjLEmNjLAkNdowwkkuT/JEkueTHE5y62YMk6QxWJziNqeBP66qQ0kuBg4mebyqnh94myRteRseCVfVq1V1aPL+G8ARYNfQwyRpDKY5Ev6xJFcAe4ADZ/m7FWAFYDs7ZrFNkra8qR+YS/Iu4AHgtqp6/Z1/X1X7q2q5qpaX2DbLjZK0ZU0V4SRLrAX47qp6cNhJkjQe0zw7IsAdwJGq+uLwkyRpPKY5Er4G+DRwbZJnJ2+/PfAuSRqFDR+Yq6qngGzCFkkaHX9iTpIaGWFJamSEJamREZakRkZYkhoZYUlqZIQlqZERlqRGRliSGhlhSWpkhCWpkRGWpEZGWJIaGWFJamSEJamREZakRkZYkhoZYUlqZIQlqZERlqRGRliSGhlhSWpkhCWpkRGWpEZGWJIaGWFJamSEJanRhhFOsj3Jt5N8J8nhJF/YjGGSNAaLU9zmJHBtVZ1IsgQ8leRvqupbA2+TpC1vwwhXVQEnJheXJm815ChJGoupzgknWUjyLHAceLyqDpzlNitJVpOsnuLkjGdK0tY0VYSr6q2q+gCwG9ib5P1nuc3+qlququUlts14piRtTef17Iiq+iHwBLBvkDWSNDLTPDvi0iSXTN6/CLgeeGHgXZI0CtM8O+Iy4K4kC6xF+76qenjYWZI0DtM8O+IfgD2bsEWSRsefmJOkRkZYkhoZYUlqZIQlqZERlqRGRliSGhlhSWpkhCWpkRGWpEZGWJIaGWFJamSEJanRNL9FTRJAzdmreiXdCzQDHglLUiMjLEmNjLAkNTLCktTICEtSIyMsSY2MsCQ1MsKS1MgIS1IjIyxJjYywJDUywpLUyAhLUiMjLEmNpo5wkoUkzyR5eMhBkjQm53MkfCtwZKghkjRGU0U4yW7g48Dtw86RpHGZ9kj4S8Bngbd/0g2SrCRZTbJ6ipOz2CZJW96GEU5yI3C8qg6e63ZVtb+qlqtqeYltMxsoSVvZNEfC1wA3JXkZuBe4NslXBl0lSSOxYYSr6vNVtbuqrgBuBr5RVZ8afJkkjYDPE5akRuf1kvdV9U3gm4MskaQR8khYkhoZYUlqZIQlqZERlqRGRliSGhlhSWpkhCWpkRGWpEZGWJIaGWFJamSEJamREZakRkZYkhqd129RkzbLo8ee6Z7wf/zWrj3dE7QFeSQsSY2MsCQ1MsKS1MgIS1IjIyxJjYywJDUywpLUyAhLUiMjLEmNjLAkNTLCktTICEtSIyMsSY2MsCQ1mupXWSZ5GXgDeAs4XVXLQ46SpLE4n98n/JtV9R+DLZGkEfJ0hCQ1mjbCBTyW5GCSlbPdIMlKktUkq6c4ObuFkrSFTXs64sNVdSzJLwKPJ3mhqp5cf4Oq2g/sB3h3fqFmvFOStqSpjoSr6tjkz+PAQ8DeIUdJ0lhsGOEkO5NcfOZ94GPAc0MPk6QxmOZ0xHuBh5Kcuf1Xq+rrg66SpJHYMMJV9RLwK5uwRZJGx6eoSVIjIyxJjYywJDUywpLUyAhLUiMjLEmNjLAkNTLCktTICEtSIyMsSY2MsCQ1MsKS1ChVs//960leA/5lBnf1HmCeXtfOPec2b3tg/ja559zmbQ/MbtMvV9Wl77xykAjPSpLVeXplZ/ec27ztgfnb5J5zm7c9MPwmT0dIUiMjLEmN5j3C+7sHvIN7zm3e9sD8bXLPuc3bHhh401yfE5akrW7ej4QlaUszwpLUaC4jnGRfku8leTHJ5+Zgz51Jjid5rnsLQJLLkzyR5Pkkh5Pc2rxne5JvJ/nOZM8XOveckWQhyTNJHu7eApDk5STfTfJsktU52HNJkvuTvJDkSJJfa9xy1eTf5czb60lu69oz2fSHk8/n55Lck2T7IB9n3s4JJ1kA/hG4HjgKPA3cUlXPN276CHAC+Kuqen/XjnV7LgMuq6pDSS4GDgKf7Po3ShJgZ1WdSLIEPAXcWlXf6tizbtcfAcvAu6vqxs4tkz0vA8tVNRc/jJDkLuDvqur2JBcCO6rqh82zzjTgGPChqprFD339fzbsYu3z+Oqq+q8k9wGPVNWXZ/2x5vFIeC/wYlW9VFVvAvcCn+gcVFVPAj/o3LBeVb1aVYcm778BHAF2Ne6pqjoxubg0eWv96p5kN/Bx4PbOHfMqyc8BHwHuAKiqN+chwBPXAf/UFeB1FoGLkiwCO4B/HeKDzGOEdwGvrLt8lMbAzLskVwB7gAPNOxaSPAscBx6vqtY9wJeAzwJvN+9Yr4DHkhxMstK85UrgNeAvJ6dsbk+ys3nTGTcD93QOqKpjwJ8B3wdeBf6zqh4b4mPNY4Q1pSTvAh4Abquq1zu3VNVbVfUBYDewN0nbaZskNwLHq+pg14af4MNV9UHgBuD3J6e5uiwCHwT+oqr2AD8C5uHxlwuBm4C/bt7x86x9B34l8EvAziSfGuJjzWOEjwGXr7u8e3Kd1pmce30AuLuqHuzec8bkW9ongH2NM64Bbpqcg70XuDbJVxr3AD8+uqKqjgMPsXbqrctR4Oi671juZy3K3W4ADlXVvzfv+Cjwz1X1WlWdAh4Efn2IDzSPEX4aeF+SKydfFW8Gvta8aa5MHgi7AzhSVV+cgz2XJrlk8v5FrD2o+kLXnqr6fFXtrqorWPv8+UZVDXIUM60kOycPojL5tv9jQNuzbarq34BXklw1ueo6oO3B73VuoflUxMT3gV9NsmPy/+061h57mbnFIe70p1FVp5N8BngUWADurKrDnZuS3AP8BvCeJEeBP62qOxonXQN8Gvju5DwswJ9U1SNNey4D7po8qn0BcF9VzcXTwubIe4GH1v4/swh8taq+3juJPwDunhzsvAT8TueYyRen64Hf69wBUFUHktwPHAJOA88w0I8vz91T1CRpTObxdIQkjYYRlqRGRliSGhlhSWpkhCWpkRGWpEZGWJIa/Q/LysCTbhgfvAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "image = torch.FloatTensor(image)\n", + "input = image.unsqueeze(0)\n", + "input = input.squeeze(-1)\n", + "input = input.unsqueeze(1)\n", + "\n", + "output_batch = F.relu(model.conv1(input))\n", + "output_batch = model.pool(output_batch)\n", + "\n", + "output_batch = F.relu(model.conv2(output_batch))\n", + "output_batch = model.pool(output_batch)\n", + "\n", + "output = output_batch[0]\n", + "\n", + "plt.imshow(\n", + " output.detach().numpy()[1]\n", + ")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example 2" + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "metadata": {}, + "outputs": [], + "source": [ + "image, _ = train_data[20]" + ] + }, + { + "cell_type": "code", + "execution_count": 134, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 134, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(image)" + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "image = torch.FloatTensor(image)\n", + "input = image.unsqueeze(0)\n", + "input = input.squeeze(-1)\n", + "input = input.unsqueeze(1)\n", + "\n", + "output_batch = F.relu(model.conv1(input))\n", + "output_batch = model.pool(output_batch)\n", + "output = output_batch[0]\n", + "\n", + "plt.imshow(\n", + " output.detach().numpy()[1]\n", + ")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 136, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "image = torch.FloatTensor(image)\n", + "input = image.unsqueeze(0)\n", + "input = input.squeeze(-1)\n", + "input = input.unsqueeze(1)\n", + "\n", + "output_batch = F.relu(model.conv1(input))\n", + "output_batch = model.pool(output_batch)\n", + "\n", + "output_batch = F.relu(model.conv2(output_batch))\n", + "output_batch = model.pool(output_batch)\n", + "\n", + "output = output_batch[0]\n", + "\n", + "plt.imshow(\n", + " output.detach().numpy()[1]\n", + ")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Example 3" + ] + }, + { + "cell_type": "code", + "execution_count": 137, + "metadata": {}, + "outputs": [], + "source": [ + "image, _ = train_data[170]" + ] + }, + { + "cell_type": "code", + "execution_count": 138, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 138, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(image)" + ] + }, + { + "cell_type": "code", + "execution_count": 139, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "image = torch.FloatTensor(image)\n", + "input = image.unsqueeze(0)\n", + "input = input.squeeze(-1)\n", + "input = input.unsqueeze(1)\n", + "\n", + "output_batch = F.relu(model.conv1(input))\n", + "output_batch = model.pool(output_batch)\n", + "output = output_batch[0]\n", + "\n", + "plt.imshow(\n", + " output.detach().numpy()[1]\n", + ")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 140, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "image = torch.FloatTensor(image)\n", + "input = image.unsqueeze(0)\n", + "input = input.squeeze(-1)\n", + "input = input.unsqueeze(1)\n", + "\n", + "output_batch = F.relu(model.conv1(input))\n", + "output_batch = model.pool(output_batch)\n", + "\n", + "output_batch = F.relu(model.conv2(output_batch))\n", + "output_batch = model.pool(output_batch)\n", + "\n", + "output = output_batch[0]\n", + "\n", + "plt.imshow(\n", + " output.detach().numpy()[1]\n", + ")\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "fig, axes = plt.subplots(1, 2, figsize=(20, 10))\n", + "\n", + "axes[0].imshow(model.conv1.weight[0].squeeze(0).detach().numpy(),\n", + " cmap='hot', interpolation='nearest')\n", + "\n", + "axes[1].imshow(model.conv1.weight[1].squeeze(0).detach().numpy(),\n", + " cmap='hot', interpolation='nearest')\n", + "plt.show()" + ] + } + ], + "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.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/labs/lab25/data_original/circle.png b/labs/lab25/data_original/circle.png new file mode 100644 index 0000000..5986143 Binary files /dev/null and b/labs/lab25/data_original/circle.png differ diff --git a/labs/lab25/data_original/square.png b/labs/lab25/data_original/square.png new file mode 100644 index 0000000..6133242 Binary files /dev/null and b/labs/lab25/data_original/square.png differ diff --git a/labs/lab25/data_original/triangle.png b/labs/lab25/data_original/triangle.png new file mode 100644 index 0000000..86c8e6b Binary files /dev/null and b/labs/lab25/data_original/triangle.png differ diff --git a/labs/lab25/docs/images/no_padding_no_strides.gif b/labs/lab25/docs/images/no_padding_no_strides.gif new file mode 100644 index 0000000..ee10e35 Binary files /dev/null and b/labs/lab25/docs/images/no_padding_no_strides.gif differ