Computer_Vision/Chapter09/Semantic_Segmentation_with_U_Net.ipynb

762 lines
256 KiB
Plaintext
Raw Normal View History

2024-02-13 03:34:51 +01:00
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Semantic_Segmentation_with_U_Net.ipynb",
"provenance": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"accelerator": "GPU",
"widgets": {
"application/vnd.jupyter.widget-state+json": {
"5292c3b952b3466f9c2d05bf97dc3fcc": {
"model_module": "@jupyter-widgets/controls",
"model_name": "HBoxModel",
"state": {
"_view_name": "HBoxView",
"_dom_classes": [],
"_model_name": "HBoxModel",
"_view_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"_view_count": null,
"_view_module_version": "1.5.0",
"box_style": "",
"layout": "IPY_MODEL_bd6d2b25f8254a77925ed65471913b48",
"_model_module": "@jupyter-widgets/controls",
"children": [
"IPY_MODEL_300e54bb169442a19c843ee9b240ae51",
"IPY_MODEL_f06a86af1f854643bcc67d7921214717"
]
}
},
"bd6d2b25f8254a77925ed65471913b48": {
"model_module": "@jupyter-widgets/base",
"model_name": "LayoutModel",
"state": {
"_view_name": "LayoutView",
"grid_template_rows": null,
"right": null,
"justify_content": null,
"_view_module": "@jupyter-widgets/base",
"overflow": null,
"_model_module_version": "1.2.0",
"_view_count": null,
"flex_flow": null,
"width": null,
"min_width": null,
"border": null,
"align_items": null,
"bottom": null,
"_model_module": "@jupyter-widgets/base",
"top": null,
"grid_column": null,
"overflow_y": null,
"overflow_x": null,
"grid_auto_flow": null,
"grid_area": null,
"grid_template_columns": null,
"flex": null,
"_model_name": "LayoutModel",
"justify_items": null,
"grid_row": null,
"max_height": null,
"align_content": null,
"visibility": null,
"align_self": null,
"height": null,
"min_height": null,
"padding": null,
"grid_auto_rows": null,
"grid_gap": null,
"max_width": null,
"order": null,
"_view_module_version": "1.2.0",
"grid_template_areas": null,
"object_position": null,
"object_fit": null,
"grid_auto_columns": null,
"margin": null,
"display": null,
"left": null
}
},
"300e54bb169442a19c843ee9b240ae51": {
"model_module": "@jupyter-widgets/controls",
"model_name": "FloatProgressModel",
"state": {
"_view_name": "ProgressView",
"style": "IPY_MODEL_a25e41d7ae29488788c6c3b1cee7d00e",
"_dom_classes": [],
"description": "100%",
"_model_name": "FloatProgressModel",
"bar_style": "success",
"max": 553507836,
"_view_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"value": 553507836,
"_view_count": null,
"_view_module_version": "1.5.0",
"orientation": "horizontal",
"min": 0,
"description_tooltip": null,
"_model_module": "@jupyter-widgets/controls",
"layout": "IPY_MODEL_0431d166f9d946a1a9cb6da37e08e900"
}
},
"f06a86af1f854643bcc67d7921214717": {
"model_module": "@jupyter-widgets/controls",
"model_name": "HTMLModel",
"state": {
"_view_name": "HTMLView",
"style": "IPY_MODEL_433a0a7d7d4b49f9bfcf610c9d0f66ad",
"_dom_classes": [],
"description": "",
"_model_name": "HTMLModel",
"placeholder": "",
"_view_module": "@jupyter-widgets/controls",
"_model_module_version": "1.5.0",
"value": " 528M/528M [03:52<00:00, 2.38MB/s]",
"_view_count": null,
"_view_module_version": "1.5.0",
"description_tooltip": null,
"_model_module": "@jupyter-widgets/controls",
"layout": "IPY_MODEL_b0d5e6d13dd14b02a3e60517301dfeb6"
}
},
"a25e41d7ae29488788c6c3b1cee7d00e": {
"model_module": "@jupyter-widgets/controls",
"model_name": "ProgressStyleModel",
"state": {
"_view_name": "StyleView",
"_model_name": "ProgressStyleModel",
"description_width": "initial",
"_view_module": "@jupyter-widgets/base",
"_model_module_version": "1.5.0",
"_view_count": null,
"_view_module_version": "1.2.0",
"bar_color": null,
"_model_module": "@jupyter-widgets/controls"
}
},
"0431d166f9d946a1a9cb6da37e08e900": {
"model_module": "@jupyter-widgets/base",
"model_name": "LayoutModel",
"state": {
"_view_name": "LayoutView",
"grid_template_rows": null,
"right": null,
"justify_content": null,
"_view_module": "@jupyter-widgets/base",
"overflow": null,
"_model_module_version": "1.2.0",
"_view_count": null,
"flex_flow": null,
"width": null,
"min_width": null,
"border": null,
"align_items": null,
"bottom": null,
"_model_module": "@jupyter-widgets/base",
"top": null,
"grid_column": null,
"overflow_y": null,
"overflow_x": null,
"grid_auto_flow": null,
"grid_area": null,
"grid_template_columns": null,
"flex": null,
"_model_name": "LayoutModel",
"justify_items": null,
"grid_row": null,
"max_height": null,
"align_content": null,
"visibility": null,
"align_self": null,
"height": null,
"min_height": null,
"padding": null,
"grid_auto_rows": null,
"grid_gap": null,
"max_width": null,
"order": null,
"_view_module_version": "1.2.0",
"grid_template_areas": null,
"object_position": null,
"object_fit": null,
"grid_auto_columns": null,
"margin": null,
"display": null,
"left": null
}
},
"433a0a7d7d4b49f9bfcf610c9d0f66ad": {
"model_module": "@jupyter-widgets/controls",
"model_name": "DescriptionStyleModel",
"state": {
"_view_name": "StyleView",
"_model_name": "DescriptionStyleModel",
"description_width": "",
"_view_module": "@jupyter-widgets/base",
"_model_module_version": "1.5.0",
"_view_count": null,
"_view_module_version": "1.2.0",
"_model_module": "@jupyter-widgets/controls"
}
},
"b0d5e6d13dd14b02a3e60517301dfeb6": {
"model_module": "@jupyter-widgets/base",
"model_name": "LayoutModel",
"state": {
"_view_name": "LayoutView",
"grid_template_rows": null,
"right": null,
"justify_content": null,
"_view_module": "@jupyter-widgets/base",
"overflow": null,
"_model_module_version": "1.2.0",
"_view_count": null,
"flex_flow": null,
"width": null,
"min_width": null,
"border": null,
"align_items": null,
"bottom": null,
"_model_module": "@jupyter-widgets/base",
"top": null,
"grid_column": null,
"overflow_y": null,
"overflow_x": null,
"grid_auto_flow": null,
"grid_area": null,
"grid_template_columns": null,
"flex": null,
"_model_name": "LayoutModel",
"justify_items": null,
"grid_row": null,
"max_height": null,
"align_content": null,
"visibility": null,
"align_self": null,
"height": null,
"min_height": null,
"padding": null,
"grid_auto_rows": null,
"grid_gap": null,
"max_width": null,
"order": null,
"_view_module_version": "1.2.0",
"grid_template_areas": null,
"object_position": null,
"object_fit": null,
"grid_auto_columns": null,
"margin": null,
"display": null,
"left": null
}
}
}
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/PacktPublishing/Hands-On-Computer-Vision-with-PyTorch/blob/master/Chapter09/Semantic_Segmentation_with_U_Net.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"metadata": {
"id": "5r38dynQvu7D",
"outputId": "d2c9f2bb-f5b4-4bd3-b5c3-fb0a69af0fb1",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"import os\n",
"if not os.path.exists('dataset1'):\n",
" !wget -q https://www.dropbox.com/s/0pigmmmynbf9xwq/dataset1.zip\n",
" !unzip -q dataset1.zip\n",
" !rm dataset1.zip\n",
" !pip install -q torch_snippets pytorch_model_summary\n",
"\n",
"from torch_snippets import *\n",
"from torchvision import transforms\n",
"from sklearn.model_selection import train_test_split\n",
"device = 'cuda' if torch.cuda.is_available() else 'cpu'"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"\u001b[K |████████████████████████████████| 61kB 4.7MB/s \n",
"\u001b[K |████████████████████████████████| 36.7MB 82kB/s \n",
"\u001b[K |████████████████████████████████| 102kB 13.2MB/s \n",
"\u001b[?25h Building wheel for contextvars (setup.py) ... \u001b[?25l\u001b[?25hdone\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "NiA-XrIxvxK7"
},
"source": [
"tfms = transforms.Compose([\n",
" transforms.ToTensor(),\n",
" transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) # imagenet\n",
"])"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "0VntXyjtvzY9"
},
"source": [
"class SegData(Dataset):\n",
" def __init__(self, split):\n",
" self.items = stems(f'dataset1/images_prepped_{split}')\n",
" self.split = split\n",
" def __len__(self):\n",
" return len(self.items)\n",
" def __getitem__(self, ix):\n",
" image = read(f'dataset1/images_prepped_{self.split}/{self.items[ix]}.png', 1)\n",
" image = cv2.resize(image, (224,224))\n",
" mask = read(f'dataset1/annotations_prepped_{self.split}/{self.items[ix]}.png')\n",
" mask = cv2.resize(mask, (224,224))\n",
" return image, mask\n",
" def choose(self): return self[randint(len(self))]\n",
" def collate_fn(self, batch):\n",
" ims, masks = list(zip(*batch))\n",
" ims = torch.cat([tfms(im.copy()/255.)[None] for im in ims]).float().to(device)\n",
" ce_masks = torch.cat([torch.Tensor(mask[None]) for mask in masks]).long().to(device)\n",
" return ims, ce_masks"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "GnQ1x5SOwW_n",
"outputId": "4e4e3dd8-011e-4330-b923-e27aaa068167",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"trn_ds = SegData('train')\n",
"val_ds = SegData('test')\n",
"trn_dl = DataLoader(trn_ds, batch_size=4, shuffle=True, collate_fn=trn_ds.collate_fn)\n",
"val_dl = DataLoader(val_ds, batch_size=1, shuffle=True, collate_fn=val_ds.collate_fn)"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"2020-11-07 12:49:50.267 | INFO | torch_snippets.loader:Glob:181 - 367 files found at dataset1/images_prepped_train\n",
"2020-11-07 12:49:50.270 | INFO | torch_snippets.loader:Glob:181 - 101 files found at dataset1/images_prepped_test\n"
],
"name": "stderr"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "DZAeohNDwXdM",
"outputId": "67642cbc-c2c3-4220-a938-ec6179c9cbc2",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 303
}
},
"source": [
"show(trn_ds[10][0])"
],
"execution_count": null,
"outputs": [
{
"output_type": "display_data",
"data": {
"image/png": "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
"text/plain": [
"<Figure size 360x360 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "ROi8_8AewZXB"
},
"source": [
"def conv(in_channels, out_channels):\n",
" return nn.Sequential(\n",
" nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=1, padding=1),\n",
" nn.BatchNorm2d(out_channels),\n",
" nn.ReLU(inplace=True)\n",
" )"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "noHOfSF4wg6m"
},
"source": [
"def up_conv(in_channels, out_channels):\n",
" return nn.Sequential(\n",
" nn.ConvTranspose2d(in_channels, out_channels, kernel_size=2, stride=2),\n",
" nn.ReLU(inplace=True)\n",
" )"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "vIJ-JtHiwiUu"
},
"source": [
"from torchvision.models import vgg16_bn\n",
"class UNet(nn.Module):\n",
" def __init__(self, pretrained=True, out_channels=12):\n",
" super().__init__()\n",
"\n",
" self.encoder = vgg16_bn(pretrained=pretrained).features\n",
" self.block1 = nn.Sequential(*self.encoder[:6])\n",
" self.block2 = nn.Sequential(*self.encoder[6:13])\n",
" self.block3 = nn.Sequential(*self.encoder[13:20])\n",
" self.block4 = nn.Sequential(*self.encoder[20:27])\n",
" self.block5 = nn.Sequential(*self.encoder[27:34])\n",
"\n",
" self.bottleneck = nn.Sequential(*self.encoder[34:])\n",
" self.conv_bottleneck = conv(512, 1024)\n",
"\n",
" self.up_conv6 = up_conv(1024, 512)\n",
" self.conv6 = conv(512 + 512, 512)\n",
" self.up_conv7 = up_conv(512, 256)\n",
" self.conv7 = conv(256 + 512, 256)\n",
" self.up_conv8 = up_conv(256, 128)\n",
" self.conv8 = conv(128 + 256, 128)\n",
" self.up_conv9 = up_conv(128, 64)\n",
" self.conv9 = conv(64 + 128, 64)\n",
" self.up_conv10 = up_conv(64, 32)\n",
" self.conv10 = conv(32 + 64, 32)\n",
" self.conv11 = nn.Conv2d(32, out_channels, kernel_size=1)\n",
" def forward(self, x):\n",
" block1 = self.block1(x)\n",
" block2 = self.block2(block1)\n",
" block3 = self.block3(block2)\n",
" block4 = self.block4(block3)\n",
" block5 = self.block5(block4)\n",
"\n",
" bottleneck = self.bottleneck(block5)\n",
" x = self.conv_bottleneck(bottleneck)\n",
"\n",
" x = self.up_conv6(x)\n",
" x = torch.cat([x, block5], dim=1)\n",
" x = self.conv6(x)\n",
"\n",
" x = self.up_conv7(x)\n",
" x = torch.cat([x, block4], dim=1)\n",
" x = self.conv7(x)\n",
"\n",
" x = self.up_conv8(x)\n",
" x = torch.cat([x, block3], dim=1)\n",
" x = self.conv8(x)\n",
"\n",
" x = self.up_conv9(x)\n",
" x = torch.cat([x, block2], dim=1)\n",
" x = self.conv9(x)\n",
"\n",
" x = self.up_conv10(x)\n",
" x = torch.cat([x, block1], dim=1)\n",
" x = self.conv10(x)\n",
"\n",
" x = self.conv11(x)\n",
"\n",
" return x"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "8c-Ztheqwqoi"
},
"source": [
"ce = nn.CrossEntropyLoss()\n",
"def UnetLoss(preds, targets):\n",
" ce_loss = ce(preds, targets)\n",
" acc = (torch.max(preds, 1)[1] == targets).float().mean()\n",
" return ce_loss, acc"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "CzzQfvyrwx6M"
},
"source": [
"def train_batch(model, data, optimizer, criterion):\n",
" model.train()\n",
" ims, ce_masks = data\n",
" _masks = model(ims)\n",
" optimizer.zero_grad()\n",
" loss, acc = criterion(_masks, ce_masks)\n",
" loss.backward()\n",
" optimizer.step()\n",
" return loss.item(), acc.item()\n",
"\n",
"@torch.no_grad()\n",
"def validate_batch(model, data, criterion):\n",
" model.eval()\n",
" ims, masks = data\n",
" _masks = model(ims)\n",
" loss, acc = criterion(_masks, masks)\n",
" return loss.item(), acc.item()"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "wob9T8n7w0Q-",
"outputId": "658203d6-fdb0-43f3-8148-076003acbac5",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 83,
"referenced_widgets": [
"5292c3b952b3466f9c2d05bf97dc3fcc",
"bd6d2b25f8254a77925ed65471913b48",
"300e54bb169442a19c843ee9b240ae51",
"f06a86af1f854643bcc67d7921214717",
"a25e41d7ae29488788c6c3b1cee7d00e",
"0431d166f9d946a1a9cb6da37e08e900",
"433a0a7d7d4b49f9bfcf610c9d0f66ad",
"b0d5e6d13dd14b02a3e60517301dfeb6"
]
}
},
"source": [
"model = UNet().to(device)\n",
"criterion = UnetLoss\n",
"optimizer = optim.Adam(model.parameters(), lr=1e-3)\n",
"n_epochs = 20"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"Downloading: \"https://download.pytorch.org/models/vgg16_bn-6c64b313.pth\" to /root/.cache/torch/hub/checkpoints/vgg16_bn-6c64b313.pth\n"
],
"name": "stderr"
},
{
"output_type": "display_data",
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5292c3b952b3466f9c2d05bf97dc3fcc",
"version_minor": 0,
"version_major": 2
},
"text/plain": [
"HBox(children=(FloatProgress(value=0.0, max=553507836.0), HTML(value='')))"
]
},
"metadata": {
"tags": []
}
},
{
"output_type": "stream",
"text": [
"\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "6OfgZty5w1ie",
"outputId": "5a5c52da-1287-4f0e-f1a1-4740da8c608a",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"log = Report(n_epochs)\n",
"for ex in range(n_epochs):\n",
" N = len(trn_dl)\n",
" for bx, data in enumerate(trn_dl):\n",
" loss, acc = train_batch(model, data, optimizer, criterion)\n",
" log.record(ex+(bx+1)/N, trn_loss=loss, trn_acc=acc, end='\\r')\n",
"\n",
" N = len(val_dl)\n",
" for bx, data in enumerate(val_dl):\n",
" loss, acc = validate_batch(model, data, criterion)\n",
" log.record(ex+(bx+1)/N, val_loss=loss, val_acc=acc, end='\\r')\n",
" \n",
" log.report_avgs(ex+1)"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"EPOCH: 1.000\ttrn_loss: 1.169\ttrn_acc: 0.737\tval_loss: 0.976\tval_acc: 0.742\t(18.50s - 351.43s remaining)\n",
"EPOCH: 2.000\ttrn_loss: 0.692\ttrn_acc: 0.827\tval_loss: 0.590\tval_acc: 0.858\t(36.80s - 331.24s remaining)\n",
"EPOCH: 3.000\ttrn_loss: 0.567\ttrn_acc: 0.851\tval_loss: 0.606\tval_acc: 0.840\t(54.90s - 311.11s remaining)\n",
"EPOCH: 4.000\ttrn_loss: 0.496\ttrn_acc: 0.866\tval_loss: 0.544\tval_acc: 0.856\t(73.06s - 292.25s remaining)\n",
"EPOCH: 5.000\ttrn_loss: 0.468\ttrn_acc: 0.872\tval_loss: 0.487\tval_acc: 0.864\t(91.31s - 273.92s remaining)\n",
"EPOCH: 6.000\ttrn_loss: 0.420\ttrn_acc: 0.883\tval_loss: 0.603\tval_acc: 0.809\t(109.59s - 255.72s remaining)\n",
"EPOCH: 7.000\ttrn_loss: 0.402\ttrn_acc: 0.887\tval_loss: 0.423\tval_acc: 0.870\t(127.91s - 237.55s remaining)\n",
"EPOCH: 8.000\ttrn_loss: 0.373\ttrn_acc: 0.894\tval_loss: 0.424\tval_acc: 0.863\t(146.29s - 219.43s remaining)\n",
"EPOCH: 9.000\ttrn_loss: 0.341\ttrn_acc: 0.902\tval_loss: 0.428\tval_acc: 0.869\t(164.71s - 201.31s remaining)\n",
"EPOCH: 10.000\ttrn_loss: 0.327\ttrn_acc: 0.907\tval_loss: 0.404\tval_acc: 0.879\t(183.10s - 183.10s remaining)\n",
"EPOCH: 11.000\ttrn_loss: 0.310\ttrn_acc: 0.913\tval_loss: 0.615\tval_acc: 0.819\t(201.44s - 164.81s remaining)\n",
"EPOCH: 12.000\ttrn_loss: 0.316\ttrn_acc: 0.910\tval_loss: 0.381\tval_acc: 0.894\t(219.77s - 146.51s remaining)\n",
"EPOCH: 13.000\ttrn_loss: 0.288\ttrn_acc: 0.919\tval_loss: 0.473\tval_acc: 0.870\t(238.21s - 128.27s remaining)\n",
"EPOCH: 14.000\ttrn_loss: 0.266\ttrn_acc: 0.925\tval_loss: 0.402\tval_acc: 0.885\t(256.77s - 110.04s remaining)\n",
"EPOCH: 15.000\ttrn_loss: 0.254\ttrn_acc: 0.928\tval_loss: 0.358\tval_acc: 0.897\t(275.37s - 91.79s remaining)\n",
"EPOCH: 16.000\ttrn_loss: 0.247\ttrn_acc: 0.930\tval_loss: 0.386\tval_acc: 0.893\t(294.03s - 73.51s remaining)\n",
"EPOCH: 17.000\ttrn_loss: 0.236\ttrn_acc: 0.933\tval_loss: 0.408\tval_acc: 0.888\t(312.70s - 55.18s remaining)\n",
"EPOCH: 18.000\ttrn_loss: 0.227\ttrn_acc: 0.936\tval_loss: 0.400\tval_acc: 0.895\t(331.29s - 36.81s remaining)\n",
"EPOCH: 19.000\ttrn_loss: 0.217\ttrn_acc: 0.938\tval_loss: 0.422\tval_acc: 0.896\t(349.77s - 18.41s remaining)\n",
"EPOCH: 20.000\ttrn_loss: 0.207\ttrn_acc: 0.941\tval_loss: 0.405\tval_acc: 0.896\t(368.25s - 0.00s remaining)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "qO45oGH7w9vr",
"outputId": "995f5e7c-b75f-4013-f070-6b9207c16949",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 473
}
},
"source": [
"log.plot_epochs(['trn_loss','val_loss'])"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
" 0%| | 0/20 [00:00<?, ?it/s]/usr/local/lib/python3.6/dist-packages/numpy/core/fromnumeric.py:3335: RuntimeWarning: Mean of empty slice.\n",
" out=out, **kwargs)\n",
"/usr/local/lib/python3.6/dist-packages/numpy/core/_methods.py:161: RuntimeWarning: invalid value encountered in double_scalars\n",
" ret = ret.dtype.type(ret / rcount)\n",
"100%|██████████| 20/20 [00:00<00:00, 1512.44it/s]\n"
],
"name": "stderr"
},
{
"output_type": "display_data",
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAfEAAAFzCAYAAAAuSjCuAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOzdd3wVVf7/8de5qaRBGoGQQBIIvUpVQUEREVRsgIru6lq+uz/Lqqsr6lrXupbddXUtu/YCunYBRVEQUTrSqxAg9BIISSCknd8fk1BCOrkteT8fj/sgd2buzGcC+rnnzDnnY6y1iIiIiP9xeTsAERERqRslcRERET+lJC4iIuKnlMRFRET8lJK4iIiIn1ISFxER8VOB3g6gtuLi4mxKSoq3w6h3eXl5hIeHezsMt2ro96j7838N/R51f/5r4cKFe6y18eW3uy2JG2NeB84Hdllru1awfxxwN2CAHOAP1tol1Z03JSWFBQsW1He4XjdjxgwGDx7s7TDcqqHfo+7P/zX0e9T9+S9jzKaKtruzO/1NYHgV+zOAM6213YC/Aq+6MRYREZEGx20tcWvtTGNMShX7fz7m7RwgyV2xiIiINES+MrDtOuArbwchIiLiT4w7104vbYlPquiZ+DHHDAH+DQy01u6t5JgbgRsBEhISek+cOLH+g/Wy3NxcIiIivB2GWzX0e9T9+b+Gfo/euj9jDOHh4QQEBLj1OtZajDFuvYa7FRcXk5eXR/ncPGTIkIXW2j7lj/fq6HRjTHfgv8B5lSVwAGvtq5Q+M+/Tp49tiAMXGvKAjDIN/R51f/6vod+jt+4vIyODyMhIYmNj3Zpkc3JyiIyMdNv53c1ay969e8nJySE1NbVGn/Fad7oxpjXwCXC1tXatt+IQERH3ys/Pd3sCbwiMMcTGxpKfn1/jz7hzitkEYDAQZ4zZAjwIBAFYa18GHgBigX+X/sUWVdRVICIi/k8JvGZq+3ty5+j0K6rZfz1wvbuuLyIi0tD5yuh0ERERt9m/fz///ve/6+VcgwcP9plFx5TERUSkwassiRcVFXkhmvrjd2uni4iI/3r4yxWs3HagXs/ZOTGKBy/oUuUx48ePZ/369fTs2ZOgoCBCQ0OJjo5m9erVvPrqqzz00EPExcWxfPlyevfuzbvvvluj59MTJkzg8ccfx1rLyJEjeeqppyguLua6665jwYIFGGP43e9+x+23387zzz/Pyy+/TGBgIJ07d6Y+pks36iS+/2ABCzfto29qDFGhQd4OR0RE3OTJJ59k+fLlLF68mBkzZjBy5EiWL19OamoqM2bM4JdffmHFihUkJiZy+umn89NPPzFw4MAqz7lt2zbuvvtuFi5cSHR0NMOGDeOzzz4jOTmZrVu3snz5csDpBSiLISMjg5CQkCPbTlajTuLLtx7gurcW8P4N/TmtbZy3wxERafCqazF7Sr9+/Y6bi92vXz+SkpzVv3v27MnGjRurTeLz589n8ODBxMc7xcXGjRvHzJkzuf/++9mwYQO33HILI0eOZNiwYQB0796dcePGcdFFF3HRRRfVy3006mfiafFOyboNu/O8HImIiHhS+ZKlISEhR34OCAg4qWfl0dHRLFmyhMGDB/Pyyy9z/fXORKzJkydz0003sWjRIvr27Vsvz+MbdRJvERVKk6AAJXERkQYuMjKSnJycej1nv379+OGHH9izZw/FxcVMmDCBM888kz179lBSUsKll17Ko48+yqJFiygpKSEzM5MhQ4bw1FNPkZ2dTW5u7knH0Ki7010uQ2pcOBv2nPwvUkREfFdsbCynn346Xbt2pUmTJiQkJJz0OVu2bMmTTz7JkCFDjgxsGzVqFEuWLOHaa6+lpKQEgCeeeILi4mKuuuoqsrOzsdZy66230qxZs5OOoVEncYDU+HCWbcn2dhgiIuJm77//foXbBw8efNya8i+88EKV55kxY8aRn6+44gquuOL4tc169OjBokWLTvjcrFmzah5sDTXq7nSAtnHhbNl3kMNFxd4ORUREpFYafUs8LT6CEgub9h6kfYL/Vr8REZH6dfHFF5ORkXHctqeeeopzzz3XSxGdSEn8yAj1XCVxERE54tNPP/V2CNVq9N3pqXGlSXyPRqiLiIh/afRJPDI0iOaRIZpmJiIifqfRJ3FwutQ37NY0MxER8S9K4jiD29SdLiIi/kZJHEiLC2f/wUKy8gq8HYqIiPiAiIiISvdt3LiRrl27ejCayimJc/wIdREREX/R6KeYAaTFOd+4NuzOo09KjJejERFp4N4YeeK2LhdBvxug4CC8N/rE/T2vhF7jIG8vfPib4/ddO7naS44fP57k5GRuuukmAB566CECAwOZPn06+/bto7CwkEcffZRRo0bV6lby8/P5wx/+wIIFCwgMDOS5555jyJAhrFixgmuvvZaCggJKSkr4+OOPSUxMZMyYMWzZsoXi4mLuv/9+xo4dW6vrlackDiRFNyEowLBea6iLiDRIY8eO5bbbbjuSxD/88EOmTp3KrbfeSlRUFHv27GHAgAFceOGFGGNqfN4XX3wRYwzLli1j9erVDBs2jLVr1/Lyyy/zxz/+kXHjxlFQUEBxcTFTpkwhMTGRyZOdLx3Z2Se/5LeSOBAY4KJNbLimmYmIeEJVLefgsKr3h8fWqOVdXq9evdi1axfbtm1j9+7dREdH06JFC26//XZmzpyJy+Vi69at7Ny5kxYtWtT4vLNmzeKWW24BoGPHjrRp04a1a9dy6qmn8thjj7FlyxYuueQS0tPT6datG3/605+4++67Of/88xk0aFCt76M8PRMvlRYXToZGqIuINFijR4/mo48+4oMPPmDs2LG899577N69m4ULF7J48WISEhLIz8+vl2tdeeWVfPHFFzRp0oQRI0bw/fff0759exYtWkS3bt34y1/+wiOPPHLS11ESL5UWH8GmvXkUFZd4OxQREXGDsWPHMnHiRD766CNGjx5NdnY2zZs3JygoiOnTp7Np06Zan3PQoEG89957AKxdu5bNmzfToUMHNmzYQFpaGrfeeiujRo1i6dKlbNu2jbCwMK666iruuuuuCiud1Za600ulxYdTWGzZsu8QKaVLsYqISMPRpUsXcnJyaNWqFS1btmTcuHFccMEFdOvWjT59+tCxY8dan/P//b//xx/+8Ae6detGYGAgb775JiEhIXz44Ye88847BAUF0aJFC+69917mz5/PXXfdhcvlIigoiJdeeumk70lJvFTakTXUc5XERUQaqGXLlh35OS4ujtmzZ1d4XG5u5QOdU1JSWL58OQChoaG88cYbJxwzfvx4xo8ff9y2c889t94roKk7vVRa/NFpZiIiIv5ALfFSMeHBNAsLYr2SuIiI4LTar7766uO2hYSEMHfuXC9FdCIl8WOkxakQioiIO1hrazX/2hd069aNxYsXe/Sa1tpaHa/u9GOoEIqISP0LDQ1l7969tU5QjY21lr179xIaGlrjz6glfoy0+HA+WriFnPxCIkODvB2OiEiDkJSUxJYtW9i9e7dbr5Ofn1+rBOiLQkNDSUpKqvHxSuLHKFtDPWNPHt2Tmnk5GhGRhiEoKIjU1FS3X2fGjBn06tXL7dfxJepOP0bbI9XM1KUuIiK+T0n8GK1jw3AZlSQVERH/oCR+jJDAAJKiw1ivwW0iIuIHlMTLSYtXNTMREfEPSuLlpMVFkLEnl5ISTYUQERHfpiReTlp8OPmFJWw/UD/l6ERERNxFSbyctNIR6hnqUhcRER+nJF5O27JCKHs0Ql1ERHybkng5zSNDCA8O0OA2ERHxeUri5RhjSI0PZ73miouIiI9TEq9AWlyEWuIiIuLzlMQrkBYfzrbsQ+QXFns7FBERkUopiVcgLT4Ca51CKCIiIr5KSbwCaXEqhCIiIr5PSbwCaUeqmWlwm4iI+C4l8QqEBQfSsmmoutNFRMSnKYlXIi0+XNXMRETEpymJVyI1LpwNu3OxVoVQRETENymJVyItLoKc/CL25BZ4OxQREZEKKYlXQoPbRETE1ymJV+JoIRQ9FxcREd+kJF6JxGZNCA50qSUuI
"text/plain": [
"<Figure size 576x432 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "2JcqPTizyv5l",
"outputId": "795a7bf4-4d76-4206-cad0-caffe2f9fe60",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 162
}
},
"source": [
"im, mask = next(iter(val_dl))\n",
"_mask = model(im)\n",
"_, _mask = torch.max(_mask, dim=1)\n",
"subplots([im[0].permute(1,2,0).detach().cpu()[:,:,0], mask.permute(1,2,0).detach().cpu()[:,:,0]\n",
",_mask.permute(1,2,0).detach().cpu()[:,:,0]],\n",
"nc=3, titles=['Original image','Original mask','Predicted mask'])"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"2020-11-07 13:00:34.595 | INFO | torch_snippets.loader:subplots:375 - plotting 3 images in a grid of 1x3 @ (5, 5)\n"
],
"name": "stderr"
},
{
"output_type": "display_data",
"data": {
"image/png": "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
"text/plain": [
"<Figure size 360x360 with 3 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "z5PjwPdcy0we"
},
"source": [
""
],
"execution_count": null,
"outputs": []
}
]
}