Computer_Vision/Chapter14/Siamese_networks.ipynb

408 lines
256 KiB
Plaintext
Raw Normal View History

2024-02-13 03:34:51 +01:00
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Siamese_networks.ipynb",
"provenance": [],
"collapsed_sections": [],
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"accelerator": "GPU"
},
"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/Chapter14/Siamese_networks.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"metadata": {
"id": "ffad2gE9AmLs"
},
"source": [
"!pip install -q torch_snippets\n",
"from torch_snippets import *\n",
"!wget -q https://www.dropbox.com/s/ua1rr8btkmpqjxh/face-detection.zip\n",
"!unzip -q face-detection.zip\n",
"device = 'cuda' if torch.cuda.is_available() else 'cpu'"
],
"execution_count": 1,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "xZcDcdb2AocA"
},
"source": [
"class SiameseNetworkDataset(Dataset):\n",
" def __init__(self, folder, transform=None, should_invert=True):\n",
" self.folder = folder\n",
" self.items = Glob(f'{self.folder}/*/*') \n",
" self.transform = transform\n",
" def __getitem__(self, ix):\n",
" itemA = self.items[ix]\n",
" person = fname(parent(itemA))\n",
" same_person = randint(2)\n",
" if same_person:\n",
" itemB = choose(Glob(f'{self.folder}/{person}/*', silent=True))\n",
" else:\n",
" while True:\n",
" itemB = choose(self.items)\n",
" if person != fname(parent(itemB)):\n",
" break\n",
" imgA = read(itemA)\n",
" imgB = read(itemB)\n",
" if self.transform:\n",
" imgA = self.transform(imgA)\n",
" imgB = self.transform(imgB)\n",
" return imgA, imgB, np.array([1-same_person])\n",
" def __len__(self):\n",
" return len(self.items)\n"
],
"execution_count": 2,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "CinJWNg2AvO_",
"outputId": "de794434-58b7-4100-8414-ead41dda1ca4",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 52
}
},
"source": [
"from torchvision import transforms\n",
"\n",
"trn_tfms = transforms.Compose([\n",
" transforms.ToPILImage(),\n",
" transforms.RandomHorizontalFlip(),\n",
" transforms.RandomAffine(5, (0.01,0.2),\n",
" scale=(0.9,1.1)),\n",
" transforms.Resize((100,100)),\n",
" transforms.ToTensor(),\n",
" transforms.Normalize((0.5), (0.5))\n",
"])\n",
"\n",
"val_tfms = transforms.Compose([\n",
" transforms.ToPILImage(),\n",
" transforms.Resize((100,100)),\n",
" transforms.ToTensor(),\n",
" transforms.Normalize((0.5), (0.5))\n",
"])\n",
"\n",
"trn_ds = SiameseNetworkDataset(folder=\"./data/faces/training/\", transform=trn_tfms)\n",
"val_ds = SiameseNetworkDataset(folder=\"./data/faces/testing/\", transform=val_tfms)\n",
"\n",
"trn_dl = DataLoader(trn_ds, shuffle=True, batch_size=64)\n",
"val_dl = DataLoader(val_ds, shuffle=False, batch_size=64)"
],
"execution_count": 3,
"outputs": [
{
"output_type": "stream",
"text": [
"2020-10-05 17:18:49.095 | INFO | torch_snippets.loader:Glob:161 - 370 files found at ./data/faces/training//*/*\n",
"2020-10-05 17:18:49.097 | INFO | torch_snippets.loader:Glob:161 - 30 files found at ./data/faces/testing//*/*\n"
],
"name": "stderr"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "a_zb_HlTAxY6"
},
"source": [
"def convBlock(ni, no):\n",
" return nn.Sequential(\n",
" nn.Dropout(0.2),\n",
" nn.Conv2d(ni, no, kernel_size=3, padding=1, padding_mode='reflect'),\n",
" nn.ReLU(inplace=True),\n",
" nn.BatchNorm2d(no),\n",
" )"
],
"execution_count": 4,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "_k8qYdmnAzDv"
},
"source": [
"class SiameseNetwork(nn.Module):\n",
" def __init__(self):\n",
" super(SiameseNetwork, self).__init__()\n",
" self.features = nn.Sequential(\n",
" convBlock(1,4),\n",
" convBlock(4,8),\n",
" convBlock(8,8),\n",
" nn.Flatten(),\n",
" nn.Linear(8*100*100, 500), nn.ReLU(inplace=True),\n",
" nn.Linear(500, 500), nn.ReLU(inplace=True),\n",
" nn.Linear(500, 5)\n",
" )\n",
"\n",
" def forward(self, input1, input2):\n",
" output1 = self.features(input1)\n",
" output2 = self.features(input2)\n",
" return output1, output2"
],
"execution_count": 5,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "qOawdFCHA1Ao"
},
"source": [
"class ContrastiveLoss(torch.nn.Module):\n",
" \"\"\"\n",
" Contrastive loss function.\n",
" Based on: http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf\n",
" \"\"\"\n",
"\n",
" def __init__(self, margin=2.0):\n",
" super(ContrastiveLoss, self).__init__()\n",
" self.margin = margin\n",
" def forward(self, output1, output2, label):\n",
" euclidean_distance = F.pairwise_distance(output1, output2, keepdim = True)\n",
" loss_contrastive = torch.mean((1-label) * torch.pow(euclidean_distance, 2) +\n",
" (label) * torch.pow(torch.clamp(self.margin - euclidean_distance, min=0.0), 2))\n",
" acc = ((euclidean_distance > 0.6) == label).float().mean()\n",
" return loss_contrastive, acc"
],
"execution_count": 6,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "r0PZEC-0A4aD"
},
"source": [
"def train_batch(model, data, optimizer, criterion):\n",
" imgsA, imgsB, labels = [t.to(device) for t in data]\n",
" optimizer.zero_grad()\n",
" codesA, codesB = model(imgsA, imgsB)\n",
" loss, acc = criterion(codesA, codesB, labels)\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",
" imgsA, imgsB, labels = [t.to(device) for t in data]\n",
" codesA, codesB = model(imgsA, imgsB)\n",
" loss, acc = criterion(codesA, codesB, labels)\n",
" return loss.item(), acc.item()"
],
"execution_count": 7,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "O99n1-N6A6Vh"
},
"source": [
"model = SiameseNetwork().to(device)\n",
"criterion = ContrastiveLoss()\n",
"optimizer = optim.Adam(model.parameters(),lr = 0.001)"
],
"execution_count": 8,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "d8u-q8l7A70U",
"outputId": "4f932e2e-a537-4045-dd5d-90c2909d484e",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 190
}
},
"source": [
"n_epochs = 200\n",
"log = Report(n_epochs)\n",
"\n",
"for epoch in range(n_epochs):\n",
" N = len(trn_dl)\n",
" for i, data in enumerate(trn_dl):\n",
" loss, acc = train_batch(model, data, optimizer, criterion)\n",
" log.record(epoch+(1+i)/N, trn_loss=loss, trn_acc=acc, end='\\r')\n",
" N = len(val_dl)\n",
" for i, data in enumerate(val_dl):\n",
" loss, acc = validate_batch(model, data, criterion)\n",
" log.record(epoch+(1+i)/N, val_loss=loss, val_acc=acc, end='\\r')\n",
" if (epoch+1)%20==0: log.report_avgs(epoch+1)\n",
" if epoch==10: optimizer = optim.Adam(model.parameters(), lr=0.0005)"
],
"execution_count": 9,
"outputs": [
{
"output_type": "stream",
"text": [
"EPOCH: 20.000\ttrn_loss: 0.663\ttrn_acc: 0.660\tval_loss: 0.602\tval_acc: 0.600\t(16.50s - 148.47s remaining)\n",
"EPOCH: 40.000\ttrn_loss: 0.430\ttrn_acc: 0.762\tval_loss: 0.465\tval_acc: 0.667\t(32.57s - 130.28s remaining)\n",
"EPOCH: 60.000\ttrn_loss: 0.395\ttrn_acc: 0.746\tval_loss: 0.371\tval_acc: 0.700\t(48.54s - 113.26s remaining)\n",
"EPOCH: 80.000\ttrn_loss: 0.255\ttrn_acc: 0.851\tval_loss: 0.220\tval_acc: 0.867\t(64.58s - 96.87s remaining)\n",
"EPOCH: 100.000\ttrn_loss: 0.252\ttrn_acc: 0.852\tval_loss: 0.381\tval_acc: 0.767\t(80.24s - 80.24s remaining)\n",
"EPOCH: 120.000\ttrn_loss: 0.212\ttrn_acc: 0.900\tval_loss: 0.214\tval_acc: 0.800\t(95.98s - 63.99s remaining)\n",
"EPOCH: 140.000\ttrn_loss: 0.251\ttrn_acc: 0.879\tval_loss: 0.385\tval_acc: 0.833\t(111.54s - 47.80s remaining)\n",
"EPOCH: 160.000\ttrn_loss: 0.201\ttrn_acc: 0.891\tval_loss: 0.257\tval_acc: 0.833\t(127.11s - 31.78s remaining)\n",
"EPOCH: 180.000\ttrn_loss: 0.156\ttrn_acc: 0.920\tval_loss: 0.400\tval_acc: 0.733\t(142.95s - 15.88s remaining)\n",
"EPOCH: 200.000\ttrn_loss: 0.174\ttrn_acc: 0.909\tval_loss: 0.377\tval_acc: 0.767\t(158.47s - 0.00s remaining)\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "v7PNY-3SA-9o",
"outputId": "a93b8ff7-61e7-489d-e71c-de2c48e372d7",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 905
}
},
"source": [
"log.plot_epochs(['trn_loss', 'val_loss'], log=True, title='Variation in training and validation loss')\n",
"log.plot_epochs(['trn_acc', 'val_acc'], title='Variation in training and validation accuracy')"
],
"execution_count": 21,
"outputs": [
{
"output_type": "stream",
"text": [
" 0%| | 0/200 [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%|██████████| 200/200 [00:00<00:00, 5808.36it/s]\n"
],
"name": "stderr"
},
{
"output_type": "display_data",
"data": {
"image/png": "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
"text/plain": [
"<Figure size 576x432 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
},
{
"output_type": "stream",
"text": [
"100%|██████████| 200/200 [00:00<00:00, 5617.91it/s]\n"
],
"name": "stderr"
},
{
"output_type": "display_data",
"data": {
"image/png": "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
"text/plain": [
"<Figure size 576x432 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "3Zjl6wROB3sc",
"outputId": "249cca9f-689b-4a21-def4-15e9b5097221",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 390
}
},
"source": [
"model.eval()\n",
"val_dl = DataLoader(val_ds,num_workers=6,batch_size=1,shuffle=True)\n",
"dataiter = iter(val_dl)\n",
"x0, _, _ = next(dataiter)\n",
"\n",
"for i in range(2):\n",
" _, x1, label2 = next(dataiter)\n",
" concatenated = torch.cat((x0*0.5+0.5, x1*0.5+0.5),0)\n",
" output1,output2 = model(x0.cuda(),x1.cuda())\n",
" euclidean_distance = F.pairwise_distance(output1, output2)\n",
" output = 'Same Face' if euclidean_distance.item() < 0.6 else 'Different'\n",
" show(torchvision.utils.make_grid(concatenated),\n",
" title='Dissimilarity: {:.2f}\\n{}'.format(euclidean_distance.item(), output))\n",
" plt.show()"
],
"execution_count": 20,
"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"
}
},
{
"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": "nNwrC5MfDDgv"
},
"source": [
""
],
"execution_count": null,
"outputs": []
}
]
}