Yash Nagraj commited on
Commit
52c73e3
·
1 Parent(s): 31228c5

Add train code with dataset.sh

Browse files
Files changed (4) hide show
  1. Pix2Pix.ipynb +375 -0
  2. UNet.py +141 -0
  3. train.py +95 -0
  4. utils.py +34 -0
Pix2Pix.ipynb ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 10,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "import torch\n",
10
+ "from torch import nn\n",
11
+ "from tqdm.auto import tqdm\n",
12
+ "import torchvision\n",
13
+ "from torchvision import transforms\n",
14
+ "from torchvision.utils import make_grid\n",
15
+ "from torch.utils.data import DataLoader\n",
16
+ "import matplotlib.pyplot as plt\n",
17
+ "torch.manual_seed(0)\n",
18
+ "\n",
19
+ "def show_tensor_images(image_tensor, num_images=25, size=(1, 28, 28)):\n",
20
+ " '''\n",
21
+ " Function for visualizing images: Given a tensor of images, number of images, and\n",
22
+ " size per image, plots and prints the images in an uniform grid.\n",
23
+ " '''\n",
24
+ " image_shifted = image_tensor\n",
25
+ " image_unflat = image_shifted.detach().cpu().view(-1, *size)\n",
26
+ " image_grid = make_grid(image_unflat[:num_images], nrow=5)\n",
27
+ " plt.imshow(image_grid.permute(1, 2, 0).squeeze())\n",
28
+ " plt.show()"
29
+ ]
30
+ },
31
+ {
32
+ "cell_type": "code",
33
+ "execution_count": 3,
34
+ "metadata": {},
35
+ "outputs": [],
36
+ "source": [
37
+ "def crop(image, new_shape):\n",
38
+ " middle_height = image.shape[2] // 2\n",
39
+ " middle_width = image.shape[3] // 2\n",
40
+ " starting_height = middle_height - new_shape[2] // 2\n",
41
+ " final_height = starting_height + new_shape[2]\n",
42
+ " starting_width = middle_width - new_shape[3] // 2\n",
43
+ " final_width = starting_width + new_shape[3]\n",
44
+ " cropped_image = image[:, :, starting_height:final_height, starting_width:final_width] \n",
45
+ " return cropped_image"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": 4,
51
+ "metadata": {},
52
+ "outputs": [],
53
+ "source": [
54
+ "class Encoder(nn.Module):\n",
55
+ " def __init__(self,input_channels, use_bn=True, use_dropout = False):\n",
56
+ " super(Encoder, self).__init__()\n",
57
+ " self.conv1 = nn.Conv2d(input_channels, 2 * input_channels, kernel_size=3)\n",
58
+ " self.conv2 = nn.Conv2d(input_channels * 2, 2 * input_channels, kernel_size = 3)\n",
59
+ " self.activation = nn.ReLU()\n",
60
+ " self.pooling = nn.MaxPool2d(kernel_size=2, stride=2)\n",
61
+ " if use_bn:\n",
62
+ " self.bn = nn.BatchNorm2d(input_channels * 2)\n",
63
+ " self.use_bn = use_bn\n",
64
+ " if use_dropout:\n",
65
+ " self.dropout = nn.Dropout()\n",
66
+ " self.use_dp = use_dropout\n",
67
+ "\n",
68
+ " def forward(self, x):\n",
69
+ " x = self.conv1(x)\n",
70
+ " if self.use_bn:\n",
71
+ " x = self.bn(x)\n",
72
+ " if self.use_dp:\n",
73
+ " x = self.dropout(x)\n",
74
+ " x = self.activation(x)\n",
75
+ " x = self.conv2(x)\n",
76
+ " if self.use_bn:\n",
77
+ " x = self.bn(x)\n",
78
+ " if self.use_dp:\n",
79
+ " x = self.dropout(x)\n",
80
+ " x = self.activation(x)\n",
81
+ " x = self.pooling(x)\n",
82
+ " return x"
83
+ ]
84
+ },
85
+ {
86
+ "cell_type": "code",
87
+ "execution_count": 5,
88
+ "metadata": {},
89
+ "outputs": [],
90
+ "source": [
91
+ "class Decoder(nn.Module):\n",
92
+ " def __init__(self, input_channels, use_bn=True, use_dropout = False):\n",
93
+ " super(Decoder, self).__init__()\n",
94
+ " self.upsample = nn.Upsample(scale_factor = 2, mode='bilinear', align_corners=True)\n",
95
+ " self.conv1 = nn.Conv2d(input_channels, input_channels // 2, kernel_size = 2)\n",
96
+ " self.conv2 = nn.Conv2d(input_channels , input_channels //2 , kernel_size = 3,padding=1)\n",
97
+ " self.conv3 = nn.Conv2d(input_channels //2, input_channels // 2, kernel_size = 2,padding=1)\n",
98
+ " self.activation = nn.ReLU()\n",
99
+ " if use_bn:\n",
100
+ " self.bn = nn.BatchNorm2d(input_channels // 2)\n",
101
+ " self.use_bn = use_bn\n",
102
+ " if use_dropout:\n",
103
+ " self.dropout = nn.Dropout()\n",
104
+ " self.use_dp = use_dropout\n",
105
+ " \n",
106
+ "\n",
107
+ " def forward(self, x, skip_con_x):\n",
108
+ " x = self.upsample(x)\n",
109
+ " x = self.conv1(x)\n",
110
+ " skip_con_x = crop(skip_con_x, x.shape)\n",
111
+ " x = torch.cat([x, skip_con_x], axis = 1)\n",
112
+ " x = self.conv2(x)\n",
113
+ " if self.use_bn:\n",
114
+ " x = self.bn(x)\n",
115
+ " if self.use_dp:\n",
116
+ " x = self.dropout(x)\n",
117
+ " x = self.activation(x)\n",
118
+ " x = self.conv3(x)\n",
119
+ " if self.use_bn:\n",
120
+ " x = self.bn(x)\n",
121
+ " if self.use_dp:\n",
122
+ " x = self.dropout(x)\n",
123
+ " x = self.activation(x)\n",
124
+ " return x\n",
125
+ " "
126
+ ]
127
+ },
128
+ {
129
+ "cell_type": "code",
130
+ "execution_count": 6,
131
+ "metadata": {},
132
+ "outputs": [],
133
+ "source": [
134
+ "class FeatureMapBlock(nn.Module):\n",
135
+ " def __init__(self, input_channels, output_channels):\n",
136
+ " super(FeatureMapBlock, self).__init__()\n",
137
+ " self.conv = nn.Conv2d(input_channels, output_channels, kernel_size=1)\n",
138
+ " def forward(self, x):\n",
139
+ " x = self.conv(x)\n",
140
+ " return x"
141
+ ]
142
+ },
143
+ {
144
+ "cell_type": "code",
145
+ "execution_count": 7,
146
+ "metadata": {},
147
+ "outputs": [],
148
+ "source": [
149
+ "class UNet(nn.Module):\n",
150
+ " def __init__(self, input_channels, output_channels, hidden_channels = 64):\n",
151
+ " super(UNet, self).__init__()\n",
152
+ " self.upfeature = FeatureMapBlock(input_channels, hidden_channels)\n",
153
+ " self.encoder1 = Encoder(hidden_channels, use_dropout=True)\n",
154
+ " self.encoder2 = Encoder(hidden_channels * 2,use_dropout=True)\n",
155
+ " self.encoder3 = Encoder(hidden_channels * 4, use_dropout=True)\n",
156
+ " self.encoder4 = Encoder(hidden_channels * 8)\n",
157
+ " self.encoder5 = Encoder(hidden_channels * 16)\n",
158
+ " self.encoder6 = Encoder(hidden_channels * 32)\n",
159
+ " self.decoder1 = Decoder(hidden_channels * 64)\n",
160
+ " self.decoder2 = Decoder(hidden_channels * 32)\n",
161
+ " self.decoder3 = Decoder(hidden_channels * 16)\n",
162
+ " self.decoder4 = Decoder(hidden_channels * 8)\n",
163
+ " self.decoder5 = Decoder(hidden_channels * 4 )\n",
164
+ " self.decoder6 = Decoder(hidden_channels * 2)\n",
165
+ " self.downfeature = FeatureMapBlock(hidden_channels , output_channels)\n",
166
+ " self.sigmoid = nn.Sigmoid()\n",
167
+ "\n",
168
+ "\n",
169
+ " def forward(self, x):\n",
170
+ " x0 = self.upfeature(x)\n",
171
+ " x1 = self.encoder1(x0)\n",
172
+ " x2 = self.encoder2(x1)\n",
173
+ " x3 = self.encoder3(x2)\n",
174
+ " x4 = self.encoder4(x3)\n",
175
+ " x5 = self.encoder5(x4)\n",
176
+ " x6 = self.encoder6(x5)\n",
177
+ " x7 = self.decoder1(x6, x5)\n",
178
+ " x8 = self.decoder2(x7, x4)\n",
179
+ " x9 = self.decoder3(x8, x3)\n",
180
+ " x10 = self.decoder4(x9, x2)\n",
181
+ " x11 = self.decoder5(x10, x1)\n",
182
+ " x12 = self.decoder6(x11, x0)\n",
183
+ " xn = self.downfeature(x12)\n",
184
+ "\n",
185
+ " return self.sigmoid(xn)"
186
+ ]
187
+ },
188
+ {
189
+ "cell_type": "code",
190
+ "execution_count": 8,
191
+ "metadata": {},
192
+ "outputs": [],
193
+ "source": [
194
+ "class Discriminator(nn.Module):\n",
195
+ " def __init__(self, input_channels, hidden_channels=8) -> None:\n",
196
+ " super(Discriminator, self).__init__()\n",
197
+ " self.upfeature = FeatureMapBlock(input_channels,hidden_channels)\n",
198
+ " self.encoder1 = Encoder(hidden_channels, use_bn=False)\n",
199
+ " self.encoder2 = Encoder(hidden_channels*2)\n",
200
+ " self.encoder3 = Encoder(hidden_channels*4)\n",
201
+ " self.encoder4 = Encoder(hidden_channels*8)\n",
202
+ " self.final = nn.Conv2d(hidden_channels * 16,1,kernel_size=1)\n",
203
+ "\n",
204
+ " def forward(self, x,y):\n",
205
+ " x = torch.cat([x,y],axis=1)\n",
206
+ " x0 = self.upfeature(x)\n",
207
+ " x1 = self.encoder1(x0)\n",
208
+ " x2 = self.encoder2(x1)\n",
209
+ " x3 = self.encoder3(x2)\n",
210
+ " x4 = self.encoder4(x3)\n",
211
+ " xn = self.final(x4)\n",
212
+ "\n",
213
+ " return xn\n",
214
+ "\n"
215
+ ]
216
+ },
217
+ {
218
+ "cell_type": "code",
219
+ "execution_count": 9,
220
+ "metadata": {},
221
+ "outputs": [],
222
+ "source": [
223
+ "import torch.nn.functional as F\n",
224
+ "# New parameters\n",
225
+ "adv_criterion = nn.BCEWithLogitsLoss() \n",
226
+ "recon_criterion = nn.L1Loss() \n",
227
+ "lambda_recon = 200\n",
228
+ "\n",
229
+ "n_epochs = 20\n",
230
+ "input_dim = 3\n",
231
+ "real_dim = 3\n",
232
+ "display_step = 200\n",
233
+ "batch_size = 4\n",
234
+ "lr = 0.0002\n",
235
+ "target_shape = 256\n",
236
+ "device = 'cuda'"
237
+ ]
238
+ },
239
+ {
240
+ "cell_type": "code",
241
+ "execution_count": null,
242
+ "metadata": {},
243
+ "outputs": [],
244
+ "source": [
245
+ "transform = transforms.Compose([\n",
246
+ " transforms.ToTensor(),\n",
247
+ "])\n",
248
+ "\n",
249
+ "dataset = torchvision.datasets.ImageFolder(\"/datsets/maps\", transform=transform)"
250
+ ]
251
+ },
252
+ {
253
+ "cell_type": "code",
254
+ "execution_count": 12,
255
+ "metadata": {},
256
+ "outputs": [],
257
+ "source": [
258
+ "gen = UNet(input_dim, real_dim).to(device)\n",
259
+ "gen_opt = torch.optim.Adam(gen.parameters(),lr=lr)\n",
260
+ "disc = Discriminator(input_dim+real_dim).to(device)\n",
261
+ "disc_opt = torch.optim.Adam(disc.parameters(),lr=lr)\n",
262
+ "\n",
263
+ "def weights_init(m):\n",
264
+ " if isinstance(m,nn.Conv2d) or isinstance(m,nn.ConvTranspose2d):\n",
265
+ " torch.nn.init.normal_(m.weight,0.0,0.02)\n",
266
+ " if isinstance(m,nn.BatchNorm2d):\n",
267
+ " torch.nn.init.normal_(m.weight,0.0,0.02)\n",
268
+ " torch.nn.init.constant_(m.bias,0.0)\n",
269
+ "\n",
270
+ "gen =gen.apply(weights_init)\n",
271
+ "disc = disc.apply(weights_init)"
272
+ ]
273
+ },
274
+ {
275
+ "cell_type": "code",
276
+ "execution_count": 13,
277
+ "metadata": {},
278
+ "outputs": [],
279
+ "source": [
280
+ "def get_gen_loss(gen, disc, real, condition, dev_criterion, recon_criterion, lambda_recon):\n",
281
+ " gen_pred = gen(condition)\n",
282
+ " disc_pred = disc(gen_pred, real)\n",
283
+ " gen_adv_loss = dev_criterion(disc_pred, torch.ones_like(disc_pred))\n",
284
+ " gen_recon_loss = recon_criterion(real,gen_pred)\n",
285
+ " gen_loss = gen_adv_loss + lambda_recon * gen_recon_loss\n",
286
+ "\n",
287
+ " return gen_loss"
288
+ ]
289
+ },
290
+ {
291
+ "cell_type": "code",
292
+ "execution_count": null,
293
+ "metadata": {},
294
+ "outputs": [],
295
+ "source": [
296
+ "def train():\n",
297
+ " mean_gen_loss = 0\n",
298
+ " mean_disc_loss = 0\n",
299
+ " dataloader = DataLoader(dataset,batch_size=batch_size,shuffle=True)\n",
300
+ "\n",
301
+ " cur_step = 0\n",
302
+ " for epoch in range(n_epochs):\n",
303
+ " for image,_ in tqdm(dataloader):\n",
304
+ " image_width = image.shape[3]\n",
305
+ " condition = image[:, :, :, :image_width // 2]\n",
306
+ " condition = nn.functional.interpolate(condition, size=target_shape)\n",
307
+ " real = image[:, :, :, image_width // 2:]\n",
308
+ " real = nn.functional.interpolate(real, size=target_shape)\n",
309
+ " cur_batch_size = len(real)\n",
310
+ " condition = condition.to(device)\n",
311
+ " real = real.to(device)\n",
312
+ "\n",
313
+ " disc_opt.zero_grad()\n",
314
+ " with torch.no_grad():\n",
315
+ " fake = gen(condition)\n",
316
+ " disc_fake_pred = disc(fake.detach(),condition)\n",
317
+ " disc_fake_loss = adv_criterion(disc_fake_pred,torch.zeros_like(disc_fake_pred))\n",
318
+ " disc_real_pred = disc(real,condition)\n",
319
+ " disc_real_loss = adv_criterion(disc_real_pred,torch.ones_like(disc_real_pred))\n",
320
+ " disc_loss = (disc_fake_loss + disc_real_loss) / 2\n",
321
+ " disc_loss.backward(retain_graph= True)\n",
322
+ " disc_opt.step()\n",
323
+ "\n",
324
+ " gen.zero_grad()\n",
325
+ " gen_loss = get_gen_loss(gen,disc,real,condition,adv_criterion,recon_criterion,lambda_recon)\n",
326
+ " gen_loss.backward()\n",
327
+ " gen_opt.step()\n",
328
+ "\n",
329
+ " mean_gen_loss += gen_loss.item() / display_step\n",
330
+ " mean_disc_loss += disc_loss.item() / display_step\n",
331
+ "\n",
332
+ " if cur_step % display_step == 0:\n",
333
+ " print(f\"Epoch: {epoch} | Step: {cur_step} | Gen-Loss: {mean_gen_loss} | Disc-loss: {mean_disc_loss}\")\n",
334
+ " show_tensor_images(condition, size=(input_dim, target_shape, target_shape))\n",
335
+ " show_tensor_images(real, size=(real_dim, target_shape, target_shape))\n",
336
+ " show_tensor_images(fake, size=(real_dim, target_shape, target_shape))\n",
337
+ " mean_gen_loss = 0\n",
338
+ " mean_disc_loss = 0\n",
339
+ "\n",
340
+ " torch.save({\n",
341
+ " \"gen\":gen,\n",
342
+ " \"disc\":disc,\n",
343
+ " \"gen_opt\": gen_opt,\n",
344
+ " \"disc_opt\": disc_opt\n",
345
+ " },f\"checkpoints/Pix2Pix_Epoch{epoch}.pth\")\n",
346
+ " cur_step += 1\n",
347
+ "\n",
348
+ "train()\n",
349
+ "\n",
350
+ " "
351
+ ]
352
+ }
353
+ ],
354
+ "metadata": {
355
+ "kernelspec": {
356
+ "display_name": "Python 3",
357
+ "language": "python",
358
+ "name": "python3"
359
+ },
360
+ "language_info": {
361
+ "codemirror_mode": {
362
+ "name": "ipython",
363
+ "version": 3
364
+ },
365
+ "file_extension": ".py",
366
+ "mimetype": "text/x-python",
367
+ "name": "python",
368
+ "nbconvert_exporter": "python",
369
+ "pygments_lexer": "ipython3",
370
+ "version": "3.12.3"
371
+ }
372
+ },
373
+ "nbformat": 4,
374
+ "nbformat_minor": 2
375
+ }
UNet.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch.nn as nn
2
+ from utils import *
3
+
4
+
5
+
6
+ class Encoder(nn.Module):
7
+ def __init__(self,input_channels, use_bn=True, use_dropout = False):
8
+ super(Encoder, self).__init__()
9
+ self.conv1 = nn.Conv2d(input_channels, 2 * input_channels, kernel_size=3)
10
+ self.conv2 = nn.Conv2d(input_channels * 2, 2 * input_channels, kernel_size = 3)
11
+ self.activation = nn.ReLU()
12
+ self.pooling = nn.MaxPool2d(kernel_size=2, stride=2)
13
+ if use_bn:
14
+ self.bn = nn.BatchNorm2d(input_channels * 2)
15
+ self.use_bn = use_bn
16
+ if use_dropout:
17
+ self.dropout = nn.Dropout()
18
+ self.use_dp = use_dropout
19
+
20
+ def forward(self, x):
21
+ x = self.conv1(x)
22
+ if self.use_bn:
23
+ x = self.bn(x)
24
+ if self.use_dp:
25
+ x = self.dropout(x)
26
+ x = self.activation(x)
27
+ x = self.conv2(x)
28
+ if self.use_bn:
29
+ x = self.bn(x)
30
+ if self.use_dp:
31
+ x = self.dropout(x)
32
+ x = self.activation(x)
33
+ x = self.pooling(x)
34
+ return x
35
+
36
+
37
+ class Decoder(nn.Module):
38
+ def __init__(self, input_channels, use_bn=True, use_dropout = False):
39
+ super(Decoder, self).__init__()
40
+ self.upsample = nn.Upsample(scale_factor = 2, mode='bilinear', align_corners=True)
41
+ self.conv1 = nn.Conv2d(input_channels, input_channels // 2, kernel_size = 2)
42
+ self.conv2 = nn.Conv2d(input_channels , input_channels //2 , kernel_size = 3,padding=1)
43
+ self.conv3 = nn.Conv2d(input_channels //2, input_channels // 2, kernel_size = 2,padding=1)
44
+ self.activation = nn.ReLU()
45
+ if use_bn:
46
+ self.bn = nn.BatchNorm2d(input_channels // 2)
47
+ self.use_bn = use_bn
48
+ if use_dropout:
49
+ self.dropout = nn.Dropout()
50
+ self.use_dp = use_dropout
51
+
52
+
53
+ def forward(self, x, skip_con_x):
54
+ x = self.upsample(x)
55
+ x = self.conv1(x)
56
+ skip_con_x = crop(skip_con_x, x.shape)
57
+ x = torch.cat([x, skip_con_x], axis = 1)
58
+ x = self.conv2(x)
59
+ if self.use_bn:
60
+ x = self.bn(x)
61
+ if self.use_dp:
62
+ x = self.dropout(x)
63
+ x = self.activation(x)
64
+ x = self.conv3(x)
65
+ if self.use_bn:
66
+ x = self.bn(x)
67
+ if self.use_dp:
68
+ x = self.dropout(x)
69
+ x = self.activation(x)
70
+ return x
71
+
72
+
73
+ class FeatureMapBlock(nn.Module):
74
+ def __init__(self, input_channels, output_channels):
75
+ super(FeatureMapBlock, self).__init__()
76
+ self.conv = nn.Conv2d(input_channels, output_channels, kernel_size=1)
77
+ def forward(self, x):
78
+ x = self.conv(x)
79
+ return x
80
+
81
+
82
+ class UNet(nn.Module):
83
+ def __init__(self, input_channels, output_channels, hidden_channels = 64):
84
+ super(UNet, self).__init__()
85
+ self.upfeature = FeatureMapBlock(input_channels, hidden_channels)
86
+ self.encoder1 = Encoder(hidden_channels, use_dropout=True)
87
+ self.encoder2 = Encoder(hidden_channels * 2,use_dropout=True)
88
+ self.encoder3 = Encoder(hidden_channels * 4, use_dropout=True)
89
+ self.encoder4 = Encoder(hidden_channels * 8)
90
+ self.encoder5 = Encoder(hidden_channels * 16)
91
+ self.encoder6 = Encoder(hidden_channels * 32)
92
+ self.decoder1 = Decoder(hidden_channels * 64)
93
+ self.decoder2 = Decoder(hidden_channels * 32)
94
+ self.decoder3 = Decoder(hidden_channels * 16)
95
+ self.decoder4 = Decoder(hidden_channels * 8)
96
+ self.decoder5 = Decoder(hidden_channels * 4 )
97
+ self.decoder6 = Decoder(hidden_channels * 2)
98
+ self.downfeature = FeatureMapBlock(hidden_channels , output_channels)
99
+ self.sigmoid = nn.Sigmoid()
100
+
101
+
102
+ def forward(self, x):
103
+ x0 = self.upfeature(x)
104
+ x1 = self.encoder1(x0)
105
+ x2 = self.encoder2(x1)
106
+ x3 = self.encoder3(x2)
107
+ x4 = self.encoder4(x3)
108
+ x5 = self.encoder5(x4)
109
+ x6 = self.encoder6(x5)
110
+ x7 = self.decoder1(x6, x5)
111
+ x8 = self.decoder2(x7, x4)
112
+ x9 = self.decoder3(x8, x3)
113
+ x10 = self.decoder4(x9, x2)
114
+ x11 = self.decoder5(x10, x1)
115
+ x12 = self.decoder6(x11, x0)
116
+ xn = self.downfeature(x12)
117
+
118
+ return self.sigmoid(xn)
119
+
120
+
121
+ class Discriminator(nn.Module):
122
+ def __init__(self, input_channels, hidden_channels=8) -> None:
123
+ super(Discriminator, self).__init__()
124
+ self.upfeature = FeatureMapBlock(input_channels,hidden_channels)
125
+ self.encoder1 = Encoder(hidden_channels, use_bn=False)
126
+ self.encoder2 = Encoder(hidden_channels*2)
127
+ self.encoder3 = Encoder(hidden_channels*4)
128
+ self.encoder4 = Encoder(hidden_channels*8)
129
+ self.final = nn.Conv2d(hidden_channels * 16,1,kernel_size=1)
130
+
131
+ def forward(self, x,y):
132
+ x = torch.cat([x,y],axis=1)
133
+ x0 = self.upfeature(x)
134
+ x1 = self.encoder1(x0)
135
+ x2 = self.encoder2(x1)
136
+ x3 = self.encoder3(x2)
137
+ x4 = self.encoder4(x3)
138
+ xn = self.final(x4)
139
+
140
+ return xn
141
+
train.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch.nn.functional as F
2
+ import torch.nn as nn
3
+ from torchvision import transforms
4
+ import torchvision
5
+ from torch.utils.data import DataLoader
6
+ from UNet import *
7
+ from tqdm.auto import tqdm
8
+
9
+ adv_criterion = nn.BCEWithLogitsLoss()
10
+ recon_criterion = nn.L1Loss()
11
+ lambda_recon = 200
12
+
13
+ n_epochs = 50
14
+ input_dim = 3
15
+ real_dim = 3
16
+ display_step = 200
17
+ batch_size = 4
18
+ lr = 0.0002
19
+ target_shape = 256
20
+ device = 'cuda'
21
+
22
+
23
+ transform = transforms.Compose([
24
+ transforms.ToTensor(),
25
+ ])
26
+
27
+ dataset = torchvision.datasets.ImageFolder("/datasets/maps", transform=transform)
28
+
29
+
30
+ gen = UNet(input_dim, real_dim).to(device)
31
+ gen_opt = torch.optim.Adam(gen.parameters(),lr=lr)
32
+ disc = Discriminator(input_dim+real_dim).to(device)
33
+ disc_opt = torch.optim.Adam(disc.parameters(),lr=lr)
34
+
35
+ def weights_init(m):
36
+ if isinstance(m,nn.Conv2d) or isinstance(m,nn.ConvTranspose2d):
37
+ torch.nn.init.normal_(m.weight,0.0,0.02)
38
+ if isinstance(m,nn.BatchNorm2d):
39
+ torch.nn.init.normal_(m.weight,0.0,0.02)
40
+ torch.nn.init.constant_(m.bias,0.0)
41
+
42
+ gen =gen.apply(weights_init)
43
+ disc = disc.apply(weights_init)
44
+
45
+
46
+ mean_gen_loss = 0
47
+ mean_disc_loss = 0
48
+ dataloader = DataLoader(dataset,batch_size=batch_size,shuffle=True)
49
+
50
+ cur_step = 0
51
+ for epoch in range(n_epochs):
52
+ for image,_ in tqdm(dataloader):
53
+ image_width = image.shape[3]
54
+ condition = image[:, :, :, :image_width // 2]
55
+ condition = nn.functional.interpolate(condition, size=target_shape)
56
+ real = image[:, :, :, image_width // 2:]
57
+ real = nn.functional.interpolate(real, size=target_shape)
58
+ cur_batch_size = len(real)
59
+ condition = condition.to(device)
60
+ real = real.to(device)
61
+
62
+ disc_opt.zero_grad()
63
+ with torch.no_grad():
64
+ fake = gen(condition)
65
+ disc_fake_pred = disc(fake.detach(),condition)
66
+ disc_fake_loss = adv_criterion(disc_fake_pred,torch.zeros_like(disc_fake_pred))
67
+ disc_real_pred = disc(real,condition)
68
+ disc_real_loss = adv_criterion(disc_real_pred,torch.ones_like(disc_real_pred))
69
+ disc_loss = (disc_fake_loss + disc_real_loss) / 2
70
+ disc_loss.backward(retain_graph= True)
71
+ disc_opt.step()
72
+
73
+ gen.zero_grad()
74
+ gen_loss = get_gen_loss(gen,disc,real,condition,adv_criterion,recon_criterion,lambda_recon)
75
+ gen_loss.backward()
76
+ gen_opt.step()
77
+
78
+ mean_gen_loss += gen_loss.item() / display_step
79
+ mean_disc_loss += disc_loss.item() / display_step
80
+
81
+ if cur_step % display_step == 0:
82
+ print(f"Epoch: {epoch} | Step: {cur_step} | Gen-Loss: {mean_gen_loss} | Disc-loss: {mean_disc_loss}")
83
+ show_tensor_images(condition,epoch,cur_step,"condition", size=(input_dim, target_shape, target_shape))
84
+ show_tensor_images(real, epoch,cur_step,"real",size=(real_dim, target_shape, target_shape))
85
+ show_tensor_images(fake, epoch,cur_step,"generated",size=(real_dim, target_shape, target_shape))
86
+ mean_gen_loss = 0
87
+ mean_disc_loss = 0
88
+
89
+ torch.save({
90
+ "gen":gen,
91
+ "disc":disc,
92
+ "gen_opt": gen_opt,
93
+ "disc_opt": disc_opt
94
+ },f"checkpoints/Pix2Pix_Epoch{epoch}.pth")
95
+ cur_step += 1
utils.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import matplotlib.pyplot as plt
3
+ from torchvision.utils import make_grid
4
+ import torch
5
+
6
+ def show_tensor_images(image_tensor, epoch,step,otype,num_images=25, size=(1, 28, 28)):
7
+ image_shifted = image_tensor
8
+ image_unflat = image_shifted.detach().cpu().view(-1, *size)
9
+ image_grid = make_grid(image_unflat[:num_images], nrow=5)
10
+ if not os.path.exists(f"/outputs/Epoch{epoch}"):
11
+ os.makedirs(f"/outputs/Epoch{epoch}")
12
+ plt.savefig(os.path.join(f"/outputs/Epoch{epoch}_step_{step}_{otype}"))
13
+ plt.close()
14
+
15
+
16
+ def crop(image, new_shape):
17
+ middle_height = image.shape[2] // 2
18
+ middle_width = image.shape[3] // 2
19
+ starting_height = middle_height - new_shape[2] // 2
20
+ final_height = starting_height + new_shape[2]
21
+ starting_width = middle_width - new_shape[3] // 2
22
+ final_width = starting_width + new_shape[3]
23
+ cropped_image = image[:, :, starting_height:final_height, starting_width:final_width]
24
+ return cropped_image
25
+
26
+
27
+ def get_gen_loss(gen, disc, real, condition, dev_criterion, recon_criterion, lambda_recon):
28
+ gen_pred = gen(condition)
29
+ disc_pred = disc(gen_pred, real)
30
+ gen_adv_loss = dev_criterion(disc_pred, torch.ones_like(disc_pred))
31
+ gen_recon_loss = recon_criterion(real,gen_pred)
32
+ gen_loss = gen_adv_loss + lambda_recon * gen_recon_loss
33
+
34
+ return gen_loss