{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport os\nfrom tqdm import tqdm\n\nfrom PIL import Image\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision\nimport torchvision.transforms as T\nfrom torch.utils.data import Dataset, DataLoader, random_split\nfrom torch.utils.data import RandomSampler\nfrom torchvision.utils import save_image\n\nimport shutil\nimport zipfile","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:29:27.642690Z","iopub.execute_input":"2025-08-06T22:29:27.642993Z","iopub.status.idle":"2025-08-06T22:29:27.647667Z","shell.execute_reply.started":"2025-08-06T22:29:27.642967Z","shell.execute_reply":"2025-08-06T22:29:27.646986Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ndevice","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:25:41.260428Z","iopub.execute_input":"2025-08-06T21:25:41.261332Z","iopub.status.idle":"2025-08-06T21:25:41.356560Z","shell.execute_reply.started":"2025-08-06T21:25:41.261304Z","shell.execute_reply":"2025-08-06T21:25:41.355989Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Dataset","metadata":{}},{"cell_type":"code","source":"class pictures_dataset(Dataset):\n    def __init__(self, photo_dir, monet_dir, transform):\n        super().__init__()\n        self.photo_dir = photo_dir\n        self.photo_images = os.listdir(photo_dir)\n\n        self.monet_dir = monet_dir\n        self.monet_images = os.listdir(monet_dir)\n\n        self.transform = transform\n\n    def __len__(self):\n        \n        return max(len(self.monet_images), len(self.photo_images))\n\n    def __getitem__(self, idx):\n        \n        photo_image = Image.open(os.path.join(self.photo_dir, \n                                              self.photo_images[idx % len(self.photo_images)]\n                                             ))\n        photo_image = self.transform(photo_image)\n\n        monet_image = Image.open(os.path.join(self.monet_dir, \n                                              self.monet_images[idx % len(self.monet_images)]\n                                             ))\n        monet_image = self.transform(monet_image)\n        \n        return photo_image, monet_image\n        ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:25:41.359849Z","iopub.execute_input":"2025-08-06T21:25:41.360022Z","iopub.status.idle":"2025-08-06T21:25:41.369725Z","shell.execute_reply.started":"2025-08-06T21:25:41.360007Z","shell.execute_reply":"2025-08-06T21:25:41.369019Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"photo_dir = '/kaggle/input/gan-getting-started/photo_jpg/'\nmonet_dir = '/kaggle/input/gan-getting-started/monet_jpg/'\n\ntransform = T.Compose([\n    T.Resize((256,256)),\n    T.ToTensor(),\n    T.Normalize(0.5, 0.5)\n])\n\ndataset = pictures_dataset(photo_dir, monet_dir, transform)\na = dataset.__getitem__(1)\nprint(len(dataset))\nprint(a[0].shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:25:42.993366Z","iopub.execute_input":"2025-08-06T21:25:42.993640Z","iopub.status.idle":"2025-08-06T21:25:43.146380Z","shell.execute_reply.started":"2025-08-06T21:25:42.993607Z","shell.execute_reply":"2025-08-06T21:25:43.145626Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Generator","metadata":{}},{"cell_type":"code","source":"class conv_block(nn.Module):\n    def __init__(self,\n                in_channels, \n                out_channels, \n                kernel_size, \n                stride=1, \n                padding=0,\n                dropout_ratio=0.5,\n                use_dropout=False,\n                use_activation=True, \n                use_norm=True,\n                downsample=True\n                ):\n        super().__init__()\n\n        if downsample:\n            layer = nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, \n                              stride=stride, padding=padding, padding_mode=\"reflect\")\n        else:\n            layer = nn.ConvTranspose2d(in_channels, out_channels, kernel_size=kernel_size, \n                              stride=stride, padding=padding, output_padding=1)\n        \n\n        self.layers = nn.Sequential(\n            layer,\n            nn.InstanceNorm2d(out_channels) if use_norm else nn.Identity(),\n            nn.Dropout(dropout_ratio) if use_dropout else nn.Identity(),\n            nn.ReLU(inplace=True) if use_activation else nn.Identity()\n        )\n        \n\n    def forward(self, x):\n        return self.layers(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:25:44.283222Z","iopub.execute_input":"2025-08-06T21:25:44.283498Z","iopub.status.idle":"2025-08-06T21:25:44.289513Z","shell.execute_reply.started":"2025-08-06T21:25:44.283477Z","shell.execute_reply":"2025-08-06T21:25:44.288670Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class residual_block(nn.Module):\n    def __init__(self, \n                 channels, \n                 kernel_size, \n                 stride=1, \n                 padding=0\n                ):\n        super().__init__()\n\n        self.layers = nn.Sequential(\n            conv_block(channels, channels, kernel_size=3, padding=1),\n            conv_block(channels, channels, kernel_size=3, padding=1, use_activation=False)\n        )\n        \n\n    def forward(self, x):\n        return self.layers(x) + x","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:11.604245Z","iopub.execute_input":"2025-08-06T21:27:11.604820Z","iopub.status.idle":"2025-08-06T21:27:11.609274Z","shell.execute_reply.started":"2025-08-06T21:27:11.604796Z","shell.execute_reply":"2025-08-06T21:27:11.608482Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, num_res_blocks) -> None:\n        super(Generator, self).__init__()\n\n        self.encoder = nn.Sequential(\n            conv_block(3, 64, kernel_size=7, stride=1, padding=3, use_norm=False),\n            conv_block(64, 128, kernel_size=3, stride=2, padding=1),\n            conv_block(128, 256, kernel_size=3, stride=2, padding=1),\n        )\n        \n        self.residual_blocks = nn.Sequential(\n            *[residual_block(256, kernel_size=3, stride=2, padding=1) for _ in range(num_res_blocks)]\n        )\n\n        self.decoder = nn.Sequential(\n            conv_block(256, 128, kernel_size=3, stride=2, padding=1, downsample=False),\n            conv_block(128, 64, kernel_size=3, stride=2, padding=1, downsample=False),\n            conv_block(64, 3, kernel_size=7, stride=1, padding=3, use_activation=False, use_norm=False)\n        )\n        \n\n    def forward(self, x):\n        x = self.encoder(x)\n        x = self.residual_blocks(x)\n        x = self.decoder(x)\n\n        return torch.tanh(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:15.331626Z","iopub.execute_input":"2025-08-06T21:27:15.332309Z","iopub.status.idle":"2025-08-06T21:27:15.338527Z","shell.execute_reply.started":"2025-08-06T21:27:15.332284Z","shell.execute_reply":"2025-08-06T21:27:15.337845Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# generator test\n\ngnet = Generator(num_res_blocks=6)\ny = gnet(torch.randn(1, 3, 256, 256))\nprint(y.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:17.667874Z","iopub.execute_input":"2025-08-06T21:27:17.668145Z","iopub.status.idle":"2025-08-06T21:27:18.472803Z","shell.execute_reply.started":"2025-08-06T21:27:17.668123Z","shell.execute_reply":"2025-08-06T21:27:18.472026Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Discriminator","metadata":{}},{"cell_type":"code","source":"class conv_leaky_block(nn.Module):\n    def __init__(self, \n                 in_channels, \n                 out_channels, \n                 kernel_size, \n                 stride=1, \n                 padding=0, \n                 use_activation=True, \n                 use_norm=True):\n        super().__init__()\n\n        self.layers = nn.Sequential(\n            nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, \n                      stride=stride, padding=padding, bias=True, padding_mode=\"reflect\"),\n            nn.InstanceNorm2d(out_channels) if use_norm else nn.Identity(),\n            nn.LeakyReLU(0.2, inplace=True) if use_activation else nn.Identity()\n        )\n\n    def forward(self, x):\n        return self.layers(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:21.686898Z","iopub.execute_input":"2025-08-06T21:27:21.687145Z","iopub.status.idle":"2025-08-06T21:27:21.692409Z","shell.execute_reply.started":"2025-08-06T21:27:21.687129Z","shell.execute_reply":"2025-08-06T21:27:21.691465Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self):\n        super().__init__()\n\n        self.layers = nn.Sequential(\n            conv_leaky_block(3, 64, kernel_size=4, stride=2, padding=1, use_norm=False),\n            conv_leaky_block(64, 128, kernel_size=4, stride=2),\n            conv_leaky_block(128, 256, kernel_size=4, stride=2),\n            conv_leaky_block(256, 512, kernel_size=4, stride=2),\n            conv_leaky_block(512, 1, kernel_size=4, stride=1, padding=1, \n                             use_activation=False, use_norm=False)\n        )\n\n\n    def forward(self, x):\n        x = self.layers(x)\n\n        return torch.sigmoid(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:22.533198Z","iopub.execute_input":"2025-08-06T21:27:22.533925Z","iopub.status.idle":"2025-08-06T21:27:22.538771Z","shell.execute_reply.started":"2025-08-06T21:27:22.533890Z","shell.execute_reply":"2025-08-06T21:27:22.538040Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# discriminator test\n\ndnet = Discriminator()\ny = dnet(torch.randn(1, 3, 256, 256))\nprint(y.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:24.560740Z","iopub.execute_input":"2025-08-06T21:27:24.561442Z","iopub.status.idle":"2025-08-06T21:27:24.624587Z","shell.execute_reply.started":"2025-08-06T21:27:24.561417Z","shell.execute_reply":"2025-08-06T21:27:24.623960Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"code","source":"# def weights_init_normal(m):\n#     classname = m.__class__.__name__\n#     if classname.find('Conv') != -1:\n#         torch.nn.init.normal_(m.weight.data, 0.0, 0.02) # reset Conv2d's weight(tensor) with Gaussian Distribution\n#         if hasattr(m, 'bias') and m.bias is not None:\n#             torch.nn.init.constant_(m.bias.data, 0.0) # reset Conv2d's bias(tensor) with Constant(0)\n#         elif classname.find('BatchNorm2d') != -1:\n#             torch.nn.init.normal_(m.weight.data, 1.0, 0.02) # reset BatchNorm2d's weight(tensor) with Gaussian Distribution\n#             torch.nn.init.constant_(m.bias.data, 0.0) # reset BatchNorm2d's bias(tensor) with Constant(0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:25.736878Z","iopub.execute_input":"2025-08-06T21:27:25.737415Z","iopub.status.idle":"2025-08-06T21:27:25.741006Z","shell.execute_reply.started":"2025-08-06T21:27:25.737391Z","shell.execute_reply":"2025-08-06T21:27:25.740176Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def save_checkpoint(epoch, model, optimizer, filename=\"models/checkpoint.pth.tar\"):\n    print(\"=> Saving checkpoint\")\n    checkpoint = {\n        'epoch': epoch,\n        \"state_dict\": model.state_dict(),\n        \"optimizer\": optimizer.state_dict(),\n        # 'loss': loss,\n    }\n    torch.save(checkpoint, filename)\n\n\ndef load_checkpoint(checkpoint_file, epoch, model, optimizer, lr):\n    print(\"=> Loading checkpoint\")\n    checkpoint = torch.load(checkpoint_file, map_location=device)\n    model.load_state_dict(checkpoint[\"state_dict\"])\n    optimizer.load_state_dict(checkpoint[\"optimizer\"])\n    epoch = checkpoint['epoch'] + 1  # +1 if you want to start from the next epoch\n    # loss = checkpoint.get('loss', None)\n\n\n    for param_group in optimizer.param_groups:\n        param_group[\"lr\"] = lr\n\n\ndef seed_everything(seed=42):\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:27.341133Z","iopub.execute_input":"2025-08-06T21:27:27.341408Z","iopub.status.idle":"2025-08-06T21:27:27.348256Z","shell.execute_reply.started":"2025-08-06T21:27:27.341387Z","shell.execute_reply":"2025-08-06T21:27:27.347517Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BATCH_SIZE = 1\nLEARNING_RATE = 1e-5\nLAMBDA_CYCLE = 10\nLAMBDA_IDENTITY = 5\nNUM_WORKERS = -1\nNUM_EPOCHS = 5\nLOAD_MODEL = False\nSAVE_MODEL = True\nCHECKPOINT_GENERATOR_mtp = \"/kaggle/working/gen_mtp.pth.tar\"\nCHECKPOINT_GENERATOR_ptm = \"/kaggle/working/gen_ptm.pth.tar\"\nCHECKPOINT_DISCRIMINATOR_m = \"/kaggle/working/disc_m.pth.tar\"\nCHECKPOINT_DISCRIMINATOR_p = \"/kaggle/working/disc_p.pth.tar\"\n\ndataloader = DataLoader(dataset, batch_size=1, num_workers=0, shuffle=True,)\n\ndisc_m = Discriminator().to(device)\ndisc_p = Discriminator().to(device)\ngen_mtp = Generator(num_res_blocks=6).to(device)\ngen_ptm = Generator(num_res_blocks=6).to(device)\n\noptimizer_dis = torch.optim.Adam(list(disc_p.parameters()) + list(disc_m.parameters()), lr=LEARNING_RATE, betas=(0.5, 0.999),)\noptimizer_gen = torch.optim.Adam(list(gen_ptm.parameters()) + list(gen_mtp.parameters()), lr=LEARNING_RATE, betas=(0.5, 0.999),)\n\nL1_loss = nn.L1Loss()\nMSE_Loss = nn.MSELoss()\n\nstart_epoch=0\n\n\nif LOAD_MODEL:\n    load_checkpoint(CHECKPOINT_GENERATOR_mtp, start_epoch, gen_mtp, optimizer_gen, LEARNING_RATE)\n    load_checkpoint(CHECKPOINT_GENERATOR_ptm, start_epoch, gen_ptm, optimizer_gen, LEARNING_RATE)\n    load_checkpoint(CHECKPOINT_DISCRIMINATOR_m, start_epoch, disc_m, optimizer_dis, LEARNING_RATE)\n    load_checkpoint(CHECKPOINT_DISCRIMINATOR_p, start_epoch, disc_p, optimizer_dis, LEARNING_RATE)\n\n# test loading after 1 epoch save","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:32.095403Z","iopub.execute_input":"2025-08-06T21:27:32.096192Z","iopub.status.idle":"2025-08-06T21:27:32.453877Z","shell.execute_reply.started":"2025-08-06T21:27:32.096165Z","shell.execute_reply":"2025-08-06T21:27:32.453086Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dis_loss = []\ngen_loss = []\ndisc_m.train()\ndisc_p.train()\ngen_mtp.train()\ngen_ptm.train()\n\nfor epoch in range(start_epoch, NUM_EPOCHS):\n    for i, (photo_real, monet_real) in enumerate(dataloader):\n        \n        photo_img, monet_img = photo_real.to(device), monet_real.to(device)\n\n        ### GENERATOR LOSSES ###\n\n        # Forward pass through generator\n        fake_photo = gen_mtp(monet_img)\n        fake_monet = gen_ptm(photo_img)\n        \n        cycl_monet = gen_ptm(fake_photo)\n        cycl_photo = gen_mtp(fake_monet)\n        \n        id_monet = gen_ptm(monet_img)\n        id_photo = gen_mtp(photo_img)\n        \n        # Forward pass through discriminators using *non-detached* fake images for generator loss\n        monet_disc_fake_for_gen = disc_m(fake_monet)\n        photo_disc_fake_for_gen = disc_p(fake_photo)\n        \n        # Identity losses\n        idt_loss_monet = L1_loss(id_monet, monet_img) * LAMBDA_IDENTITY \n        idt_loss_photo = L1_loss(id_photo, photo_img) * LAMBDA_IDENTITY \n        \n        # Cycle consistency losses\n        cycle_loss_monet = L1_loss(cycl_monet, monet_img) * LAMBDA_CYCLE\n        cycle_loss_photo = L1_loss(cycl_photo, photo_img) * LAMBDA_CYCLE\n        \n        # Adversarial losses\n        real_label = torch.ones_like(monet_disc_fake_for_gen).to(device)\n        adv_loss_monet = MSE_Loss(monet_disc_fake_for_gen, real_label)\n        adv_loss_photo = MSE_Loss(photo_disc_fake_for_gen, real_label)\n        \n        # Total generator loss\n        total_gen_loss = (\n            cycle_loss_monet + cycle_loss_photo +\n            adv_loss_monet + adv_loss_photo +\n            idt_loss_monet + idt_loss_photo\n        )\n        \n        optimizer_gen.zero_grad()\n        total_gen_loss.backward()\n        optimizer_gen.step()\n        \n        ### DISCRIMINATOR LOSSES ###\n        \n        # Recompute fake images, but DETACH them\n        fake_photo_detached = fake_photo.detach()\n        fake_monet_detached = fake_monet.detach()\n        \n        # Discriminator outputs\n        monet_disc_real = disc_m(monet_img)\n        photo_disc_real = disc_p(photo_img)\n        monet_disc_fake = disc_m(fake_monet_detached)\n        photo_disc_fake = disc_p(fake_photo_detached)\n        \n        monet_real_loss = MSE_Loss(monet_disc_real, torch.ones_like(monet_disc_real))\n        monet_fake_loss = MSE_Loss(monet_disc_fake, torch.zeros_like(monet_disc_fake))\n        photo_real_loss = MSE_Loss(photo_disc_real, torch.ones_like(photo_disc_real))\n        photo_fake_loss = MSE_Loss(photo_disc_fake, torch.zeros_like(photo_disc_fake))\n        \n        monet_disc_loss = monet_real_loss + monet_fake_loss\n        photo_disc_loss = photo_real_loss + photo_fake_loss\n        total_disc_loss = (monet_disc_loss + photo_disc_loss) / 2\n        \n        optimizer_dis.zero_grad()\n        total_disc_loss.backward()\n        optimizer_dis.step()\n        \n\n        dis_loss.append(total_disc_loss.item())\n        gen_loss.append(total_gen_loss.item())\n\n        if i % 100 == 0:\n            print(\n                f\"[{epoch+1}/{NUM_EPOCHS}][{i}/{len(dataloader)}]\"\n                f\"\\t Loss_D: {total_disc_loss.item()} \\t Loss_G: {total_gen_loss.item()}\"\n                # f\"\\t D(x): {D_x} \\t D(G(z)): {D_G_z1} / {D_G_z2}\"\n            )\n\n    \n    if SAVE_MODEL:\n        save_checkpoint(epoch, gen_mtp, optimizer_gen, filename=CHECKPOINT_GENERATOR_mtp)\n        save_checkpoint(epoch, gen_ptm, optimizer_gen, filename=CHECKPOINT_GENERATOR_ptm)\n        save_checkpoint(epoch, disc_m, optimizer_dis, filename=CHECKPOINT_DISCRIMINATOR_m)\n        save_checkpoint(epoch, disc_p, optimizer_dis, filename=CHECKPOINT_DISCRIMINATOR_p)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T21:27:36.090483Z","iopub.execute_input":"2025-08-06T21:27:36.091250Z","iopub.status.idle":"2025-08-06T22:27:08.896394Z","shell.execute_reply.started":"2025-08-06T21:27:36.091220Z","shell.execute_reply":"2025-08-06T22:27:08.895341Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.plot(dis_loss, label = \"Discriminator loss\")\nplt.plot(gen_loss, label = \"Generator loss\")\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:27:15.880949Z","iopub.execute_input":"2025-08-06T22:27:15.881207Z","iopub.status.idle":"2025-08-06T22:27:16.144741Z","shell.execute_reply.started":"2025-08-06T22:27:15.881189Z","shell.execute_reply":"2025-08-06T22:27:16.143950Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Testing","metadata":{}},{"cell_type":"code","source":"photo_dir = '/kaggle/input/gan-getting-started/photo_jpg/'\n\ndir = '/kaggle/input/random-human-face-dataset/human_face_cropped/train/'\nphotos = os.listdir(photo_dir)\npath = photo_dir+photos[0]\n# img = Image.open(path)\nimg = Image.open(path).convert(\"RGB\")\nprint(img.size)\nimg","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:27:23.554316Z","iopub.execute_input":"2025-08-06T22:27:23.554575Z","iopub.status.idle":"2025-08-06T22:27:23.582504Z","shell.execute_reply.started":"2025-08-06T22:27:23.554548Z","shell.execute_reply":"2025-08-06T22:27:23.581754Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Get a sample from the dataset\nphoto_tensor, _ = dataset[0]\n\n# Unnormalize: [-1, 1] → [0, 1]\nunnormalized = (photo_tensor * 0.5) + 0.5\n\n# Convert to numpy image\nimg = unnormalized.permute(1, 2, 0).clamp(0, 1).numpy()\n\n# Plot\nplt.imshow(img)\nplt.title(\"Photo Image\")\nplt.axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:27:25.008166Z","iopub.execute_input":"2025-08-06T22:27:25.008421Z","iopub.status.idle":"2025-08-06T22:27:25.180980Z","shell.execute_reply.started":"2025-08-06T22:27:25.008401Z","shell.execute_reply":"2025-08-06T22:27:25.180195Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def unnormalize(t):\n    return (t * 0.5) + 0.5  # reverse normalization from [-1,1] to [0,1]\n\nfrom_checkpoint = False\nidx = 0","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:27:26.791946Z","iopub.execute_input":"2025-08-06T22:27:26.792208Z","iopub.status.idle":"2025-08-06T22:27:26.796249Z","shell.execute_reply.started":"2025-08-06T22:27:26.792188Z","shell.execute_reply":"2025-08-06T22:27:26.795502Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if from_checkpoint:\n    gen_ptm = Generator(num_res_blocks=6).to(device)\n    # Load the saved checkpoint\n    checkpoint = torch.load(\"gen_ptm.pth.tar\", map_location=device)\n    gen_ptm.load_state_dict(checkpoint[\"state_dict\"])\n    gen_ptm.eval()\nelse:\n    gen_ptm.eval()\n    \n\nphoto_tensor, _ = dataset[idx]  # get photo image only\nwith torch.no_grad():\n    input_img = photo_tensor.unsqueeze(0).to(device)  # add batch dimension\n    generated = gen_ptm(input_img)\n\n\norig_img = unnormalize(photo_tensor).permute(1, 2, 0).cpu().clamp(0, 1).numpy()\ngen_img = unnormalize(generated.squeeze(0)).permute(1, 2, 0).cpu().clamp(0, 1).numpy()\n\nplt.figure(figsize=(8, 4))\n\nplt.subplot(1, 2, 1)\nplt.title(\"Original Photo\")\nplt.imshow(orig_img)\nplt.axis(\"off\")\n\nplt.subplot(1, 2, 2)\nplt.title(\"Generated Monet\")\nplt.imshow(gen_img)\nplt.axis(\"off\")\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:27:37.144164Z","iopub.execute_input":"2025-08-06T22:27:37.145060Z","iopub.status.idle":"2025-08-06T22:27:37.400420Z","shell.execute_reply.started":"2025-08-06T22:27:37.145000Z","shell.execute_reply":"2025-08-06T22:27:37.399756Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from_checkpoint = False\n\nif from_checkpoint:\n    gen_mtp = Generator(num_res_blocks=6).to(device)\n    # Load the saved checkpoint\n    checkpoint = torch.load(\"gen_mtp.pth.tar\", map_location=device)\n    gen_mtp.load_state_dict(checkpoint[\"state_dict\"])\n    gen_mtp.eval()\nelse:\n    gen_mtp.eval()\n    \n\n_, monet_tensor = dataset[idx]  # get photo image only\nwith torch.no_grad():\n    input_img = monet_tensor.unsqueeze(0).to(device)  # add batch dimension\n    generated = gen_mtp(input_img)\n\n\norig_img = unnormalize(monet_tensor).permute(1, 2, 0).cpu().clamp(0, 1).numpy()\ngen_img = unnormalize(generated.squeeze(0)).permute(1, 2, 0).cpu().clamp(0, 1).numpy()\n\nplt.figure(figsize=(8, 4))\n\nplt.subplot(1, 2, 1)\nplt.title(\"Original Monet\")\nplt.imshow(orig_img)\nplt.axis(\"off\")\n\nplt.subplot(1, 2, 2)\nplt.title(\"Generated Photo\")\nplt.imshow(gen_img)\nplt.axis(\"off\")\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:27:55.984732Z","iopub.execute_input":"2025-08-06T22:27:55.985247Z","iopub.status.idle":"2025-08-06T22:27:56.230753Z","shell.execute_reply.started":"2025-08-06T22:27:55.985227Z","shell.execute_reply":"2025-08-06T22:27:56.230112Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Submission","metadata":{}},{"cell_type":"code","source":"gen_ptm.eval()\n\n# Directory to temporarily save generated images\noutput_dir = \"/kaggle/working/monet_generated\"\nos.makedirs(output_dir, exist_ok=True)\n\nprint(\"Generating Monet-style images...\")\nfor idx, (photo_tensor, _) in tqdm(enumerate(dataloader), total=len(dataset)):\n    photo_tensor = photo_tensor.to(device)\n    \n    with torch.no_grad():\n        generated = gen_ptm(photo_tensor)\n    \n    save_path = os.path.join(output_dir, f\"monet_{idx:04d}.png\")\n    save_image((generated + 1) / 2, save_path) # unnormalize\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:29:32.690384Z","iopub.execute_input":"2025-08-06T22:29:32.690639Z","iopub.status.idle":"2025-08-06T22:34:00.668444Z","shell.execute_reply.started":"2025-08-06T22:29:32.690619Z","shell.execute_reply":"2025-08-06T22:34:00.667870Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Zip the folder\nzip_filename = \"/kaggle/working/images.zip\"\nwith zipfile.ZipFile(zip_filename, 'w') as zipf:\n    for root, _, files in os.walk(output_dir):\n        for file in files:\n            filepath = os.path.join(root, file)\n            zipf.write(filepath, arcname=file)\n\nprint(f\"All images saved and zipped as {zip_filename}\")\n\n# Optional: clean up the temporary folder\nshutil.rmtree(output_dir)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-06T22:34:02.788915Z","iopub.execute_input":"2025-08-06T22:34:02.789155Z","iopub.status.idle":"2025-08-06T22:34:05.919991Z","shell.execute_reply.started":"2025-08-06T22:34:02.789139Z","shell.execute_reply":"2025-08-06T22:34:05.919376Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}