{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":21755,"databundleVersionId":1475600},{"sourceType":"modelInstanceVersion","sourceId":829144,"databundleVersionId":16637985,"modelInstanceId":630573,"modelId":642484}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport glob\nimport random\nimport zipfile\nfrom itertools import cycle\n\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom PIL import Image\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nfrom torchvision.utils import save_image, make_grid","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:54.488885Z","iopub.execute_input":"2026-04-21T19:35:54.48922Z","iopub.status.idle":"2026-04-21T19:35:54.494066Z","shell.execute_reply.started":"2026-04-21T19:35:54.489191Z","shell.execute_reply":"2026-04-21T19:35:54.493441Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"Device:\", device)\n\n# paths - change if needed\nMONET_DIR = \"/kaggle/input/competitions/gan-getting-started/monet_jpg\"\nPHOTO_DIR = \"/kaggle/input/competitions/gan-getting-started/photo_jpg\"\n\nIMAGE_SIZE = 256        # 128 is better than 64 for this task\nBATCH_SIZE = 4          # increase if GPU allows im wiecej tym szybciej\nEPOCHS = 10             # 10 for test, 20-50 for better results  im wiecej epochow tyym dluzej ale lepiej\nLR = 0.0001            # zwolnic do 01 jak dalej zolte obrazki sa \nLAMBDA_CYCLE = 10.0            # to mozna zmiejszyc jesli lambda identity nic nie da\nLAMBDA_IDENTITY = 4.7         #zmniejszyc dla wiekszego uzycia treningu modelu Lower identity loss usually makes outputs more stylized, less photo-preserving.\nNUM_WORKERS = 4\n\nOUTPUT_DIR = \"monet_outputs\"\nPREVIEW_DIR = \"/kaggle/working/previews\"\nos.makedirs(OUTPUT_DIR, exist_ok=True)\nos.makedirs(PREVIEW_DIR, exist_ok=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:54.49537Z","iopub.execute_input":"2026-04-21T19:35:54.495701Z","iopub.status.idle":"2026-04-21T19:35:54.509572Z","shell.execute_reply.started":"2026-04-21T19:35:54.495635Z","shell.execute_reply":"2026-04-21T19:35:54.508785Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ImageFolderDataset(Dataset):\n    def __init__(self, root_dir, transform=None):\n        self.root_dir = root_dir\n        self.transform = transform\n        self.files = sorted([\n            os.path.join(root_dir, f)\n            for f in os.listdir(root_dir)\n            if f.lower().endswith((\".jpg\", \".jpeg\", \".png\"))\n        ])\n\n    def __len__(self):\n        return len(self.files)\n\n    def __getitem__(self, idx):\n        path = self.files[idx]\n        image = Image.open(path).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        return image, os.path.basename(path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:54.510584Z","iopub.execute_input":"2026-04-21T19:35:54.511039Z","iopub.status.idle":"2026-04-21T19:35:54.521535Z","shell.execute_reply.started":"2026-04-21T19:35:54.511014Z","shell.execute_reply":"2026-04-21T19:35:54.520819Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n])\n\nmonet_dataset = ImageFolderDataset(MONET_DIR, transform=transform)\nphoto_dataset = ImageFolderDataset(PHOTO_DIR, transform=transform)\n\nmonet_loader = DataLoader(\n    monet_dataset,\n    batch_size=BATCH_SIZE,\n    shuffle=True,\n    num_workers=NUM_WORKERS,\n    pin_memory=True\n)\n\nphoto_loader = DataLoader(\n    photo_dataset,\n    batch_size=BATCH_SIZE,\n    shuffle=True,\n    num_workers=NUM_WORKERS,\n    pin_memory=True\n)\n\nprint(\"Monet images:\", len(monet_dataset))\nprint(\"Photo images:\", len(photo_dataset))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:54.522288Z","iopub.execute_input":"2026-04-21T19:35:54.522526Z","iopub.status.idle":"2026-04-21T19:35:54.556034Z","shell.execute_reply.started":"2026-04-21T19:35:54.522492Z","shell.execute_reply":"2026-04-21T19:35:54.555506Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def denorm(x):\n    return (x * 0.5 + 0.5).clamp(0, 1)\n\nmonet_batch, _ = next(iter(monet_loader))\nphoto_batch, _ = next(iter(photo_loader))\n\nplt.figure(figsize=(10, 5))\nplt.subplot(1, 2, 1)\nplt.imshow(np.transpose(make_grid(denorm(monet_batch[:4]), nrow=2).cpu().numpy(), (1, 2, 0)))\nplt.title(\"Monet\")\nplt.axis(\"off\")\n\nplt.subplot(1, 2, 2)\nplt.imshow(np.transpose(make_grid(denorm(photo_batch[:4]), nrow=2).cpu().numpy(), (1, 2, 0)))\nplt.title(\"Photos\")\nplt.axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:54.557215Z","iopub.execute_input":"2026-04-21T19:35:54.55741Z","iopub.status.idle":"2026-04-21T19:35:55.837999Z","shell.execute_reply.started":"2026-04-21T19:35:54.557391Z","shell.execute_reply":"2026-04-21T19:35:55.837112Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ConvBlock(nn.Module):\n    def __init__(self, in_channels, out_channels, down=True, use_act=True, **kwargs):\n        super().__init__()\n        if down:\n            self.block = nn.Sequential(\n                nn.Conv2d(in_channels, out_channels, padding_mode=\"reflect\", **kwargs),\n                nn.InstanceNorm2d(out_channels),\n                nn.ReLU(inplace=True) if use_act else nn.Identity()\n            )\n        else:\n            self.block = nn.Sequential(\n                nn.ConvTranspose2d(in_channels, out_channels, **kwargs),\n                nn.InstanceNorm2d(out_channels),\n                nn.ReLU(inplace=True) if use_act else nn.Identity()\n            )\n\n    def forward(self, x):\n        return self.block(x)\n\n\nclass ResidualBlock(nn.Module):\n    def __init__(self, channels):\n        super().__init__()\n        self.block = nn.Sequential(\n            nn.Conv2d(channels, channels, kernel_size=3, stride=1, padding=1, padding_mode=\"reflect\"),\n            nn.InstanceNorm2d(channels),\n            nn.ReLU(inplace=True),\n            nn.Conv2d(channels, channels, kernel_size=3, stride=1, padding=1, padding_mode=\"reflect\"),\n            nn.InstanceNorm2d(channels),\n        )\n\n    def forward(self, x):\n        return x + self.block(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:55.839529Z","iopub.execute_input":"2026-04-21T19:35:55.83994Z","iopub.status.idle":"2026-04-21T19:35:55.846815Z","shell.execute_reply.started":"2026-04-21T19:35:55.839899Z","shell.execute_reply":"2026-04-21T19:35:55.846051Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, img_channels=3, num_features=64, num_residuals=9):\n        super().__init__()\n\n        self.initial = nn.Sequential(\n            nn.Conv2d(img_channels, num_features, kernel_size=7, stride=1, padding=3, padding_mode=\"reflect\"),\n            nn.InstanceNorm2d(num_features),\n            nn.ReLU(inplace=True),\n        )\n\n        self.down_blocks = nn.Sequential(\n            ConvBlock(num_features, num_features * 2, down=True, kernel_size=3, stride=2, padding=1),\n            ConvBlock(num_features * 2, num_features * 4, down=True, kernel_size=3, stride=2, padding=1),\n        )\n\n        self.res_blocks = nn.Sequential(\n            *[ResidualBlock(num_features * 4) for _ in range(num_residuals)]\n        )\n\n        self.up_blocks = nn.Sequential(\n            ConvBlock(num_features * 4, num_features * 2, down=False, kernel_size=3, stride=2, padding=1, output_padding=1),\n            ConvBlock(num_features * 2, num_features, down=False, kernel_size=3, stride=2, padding=1, output_padding=1),\n        )\n\n        self.last = nn.Conv2d(num_features, img_channels, kernel_size=7, stride=1, padding=3, padding_mode=\"reflect\")\n\n    def forward(self, x):\n        x = self.initial(x)\n        x = self.down_blocks(x)\n        x = self.res_blocks(x)\n        x = self.up_blocks(x)\n        return torch.tanh(self.last(x))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:55.847704Z","iopub.execute_input":"2026-04-21T19:35:55.848084Z","iopub.status.idle":"2026-04-21T19:35:55.867825Z","shell.execute_reply.started":"2026-04-21T19:35:55.848045Z","shell.execute_reply":"2026-04-21T19:35:55.867166Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#kawałek kodu do generatora v2\nclass UpBlock(nn.Module):\n    def __init__(self, in_channels, out_channels):\n        super().__init__()\n        self.block = nn.Sequential(\n            nn.Upsample(scale_factor=2, mode=\"bilinear\", align_corners=False),\n            nn.Conv2d(\n                in_channels,\n                out_channels,\n                kernel_size=3,\n                stride=1,\n                padding=1,\n                padding_mode=\"reflect\"\n            ),\n            nn.InstanceNorm2d(out_channels),\n            nn.ReLU(inplace=True)\n        )\n\n    def forward(self, x):\n        return self.block(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:55.868729Z","iopub.execute_input":"2026-04-21T19:35:55.869233Z","iopub.status.idle":"2026-04-21T19:35:55.884001Z","shell.execute_reply.started":"2026-04-21T19:35:55.869209Z","shell.execute_reply":"2026-04-21T19:35:55.883509Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#generator V2 bez tych kurwa dziwnych granulatow i a la snake skin effect\nclass Generator(nn.Module):\n    def __init__(self, img_channels=3, num_features=64, num_residuals=9):\n        super().__init__()\n\n        self.initial = nn.Sequential(\n            nn.Conv2d(img_channels, num_features, kernel_size=7, stride=1, padding=3, padding_mode=\"reflect\"),\n            nn.InstanceNorm2d(num_features),\n            nn.ReLU(inplace=True),\n        )\n\n        self.down_blocks = nn.Sequential(\n            ConvBlock(num_features, num_features * 2, down=True, kernel_size=3, stride=2, padding=1),\n            ConvBlock(num_features * 2, num_features * 4, down=True, kernel_size=3, stride=2, padding=1),\n        )\n\n        self.res_blocks = nn.Sequential(\n            *[ResidualBlock(num_features * 4) for _ in range(num_residuals)]\n        )\n\n        self.up_blocks = nn.Sequential(\n            UpBlock(num_features * 4, num_features * 2),\n            UpBlock(num_features * 2, num_features),\n        )\n\n        self.last = nn.Conv2d(\n            num_features,\n            img_channels,\n            kernel_size=7,\n            stride=1,\n            padding=3,\n            padding_mode=\"reflect\"\n        )\n\n    def forward(self, x):\n        x = self.initial(x)\n        x = self.down_blocks(x)\n        x = self.res_blocks(x)\n        x = self.up_blocks(x)\n        return torch.tanh(self.last(x))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:55.885885Z","iopub.execute_input":"2026-04-21T19:35:55.886141Z","iopub.status.idle":"2026-04-21T19:35:55.89801Z","shell.execute_reply.started":"2026-04-21T19:35:55.886121Z","shell.execute_reply":"2026-04-21T19:35:55.897517Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self, in_channels=3, features=[64, 128, 256, 512]):\n        super().__init__()\n\n        layers = [\n            nn.Conv2d(in_channels, features[0], kernel_size=4, stride=2, padding=1, padding_mode=\"reflect\"),\n            nn.LeakyReLU(0.2, inplace=True),\n        ]\n\n        in_channels_curr = features[0]\n        for feature in features[1:]:\n            stride = 1 if feature == features[-1] else 2\n            layers += [\n                nn.Conv2d(in_channels_curr, feature, kernel_size=4, stride=stride, padding=1, padding_mode=\"reflect\"),\n                nn.InstanceNorm2d(feature),\n                nn.LeakyReLU(0.2, inplace=True),\n            ]\n            in_channels_curr = feature\n\n        layers += [\n            nn.Conv2d(in_channels_curr, 1, kernel_size=4, stride=1, padding=1, padding_mode=\"reflect\")\n        ]\n\n        self.model = nn.Sequential(*layers)\n\n    def forward(self, x):\n        return self.model(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:55.898779Z","iopub.execute_input":"2026-04-21T19:35:55.899032Z","iopub.status.idle":"2026-04-21T19:35:55.918747Z","shell.execute_reply.started":"2026-04-21T19:35:55.899011Z","shell.execute_reply":"2026-04-21T19:35:55.918174Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"G_PM = Generator().to(device)   # Photo -> Monet\nG_MP = Generator().to(device)   # Monet -> Photo\nD_M = Discriminator().to(device)\nD_P = Discriminator().to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:55.919609Z","iopub.execute_input":"2026-04-21T19:35:55.919865Z","iopub.status.idle":"2026-04-21T19:35:56.175641Z","shell.execute_reply.started":"2026-04-21T19:35:55.919845Z","shell.execute_reply":"2026-04-21T19:35:56.175108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def init_weights(model):\n    for m in model.modules():\n        if isinstance(m, (nn.Conv2d, nn.ConvTranspose2d)):\n            nn.init.normal_(m.weight.data, 0.0, 0.02)\n            if m.bias is not None:\n                nn.init.constant_(m.bias.data, 0)\n\ninit_weights(G_PM)\ninit_weights(G_MP)\ninit_weights(D_M)\ninit_weights(D_P)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:56.176497Z","iopub.execute_input":"2026-04-21T19:35:56.176766Z","iopub.status.idle":"2026-04-21T19:35:56.23189Z","shell.execute_reply.started":"2026-04-21T19:35:56.176742Z","shell.execute_reply":"2026-04-21T19:35:56.231172Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mse_loss = nn.MSELoss()\nl1_loss = nn.L1Loss()\n\nopt_G = optim.Adam(\n    list(G_PM.parameters()) + list(G_MP.parameters()),\n    lr=LR,\n    betas=(0.5, 0.999)\n)\n\nopt_D_M = optim.Adam(D_M.parameters(), lr=LR, betas=(0.5, 0.999))\nopt_D_P = optim.Adam(D_P.parameters(), lr=LR, betas=(0.5, 0.999))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:56.232808Z","iopub.execute_input":"2026-04-21T19:35:56.233005Z","iopub.status.idle":"2026-04-21T19:35:56.238229Z","shell.execute_reply.started":"2026-04-21T19:35:56.232985Z","shell.execute_reply":"2026-04-21T19:35:56.23753Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def save_preview(photo_imgs, fake_monet_imgs, epoch, step=0):\n    photo_imgs = denorm(photo_imgs[:4].detach().cpu())\n    fake_monet_imgs = denorm(fake_monet_imgs[:4].detach().cpu())\n\n    grid_photo = make_grid(photo_imgs, nrow=2)\n    grid_fake = make_grid(fake_monet_imgs, nrow=2)\n\n    plt.figure(figsize=(10, 5))\n    plt.subplot(1, 2, 1)\n    plt.imshow(np.transpose(grid_photo.numpy(), (1, 2, 0)))\n    plt.title(\"Input photos\")\n    plt.axis(\"off\")\n\n    plt.subplot(1, 2, 2)\n    plt.imshow(np.transpose(grid_fake.numpy(), (1, 2, 0)))\n    plt.title(\"Photo -> Monet\")\n    plt.axis(\"off\")\n    plt.show()\n\n    save_image(photo_imgs, f\"{PREVIEW_DIR}/epoch_{epoch:03d}_step_{step:04d}_input.png\", nrow=2)\n    save_image(fake_monet_imgs, f\"{PREVIEW_DIR}/epoch_{epoch:03d}_step_{step:04d}_output.png\", nrow=2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:56.238986Z","iopub.execute_input":"2026-04-21T19:35:56.239165Z","iopub.status.idle":"2026-04-21T19:35:56.247038Z","shell.execute_reply.started":"2026-04-21T19:35:56.239147Z","shell.execute_reply":"2026-04-21T19:35:56.246398Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"g_losses = []\nd_m_losses = []\nd_p_losses = []\n\nsteps_per_epoch = min(len(monet_loader), len(photo_loader))\n\nfor epoch in range(1, EPOCHS + 1):\n    monet_iter = iter(monet_loader)\n    photo_iter = iter(photo_loader)\n\n    for step in range(steps_per_epoch):\n        real_monet, _ = next(monet_iter)\n        real_photo, _ = next(photo_iter)\n\n        real_monet = real_monet.to(device)\n        real_photo = real_photo.to(device)\n\n        # --------------------------\n        # Train Generators\n        # --------------------------\n        opt_G.zero_grad()\n\n        fake_monet = G_PM(real_photo)\n        fake_photo = G_MP(real_monet)\n\n        cycle_photo = G_MP(fake_monet)\n        cycle_monet = G_PM(fake_photo)\n\n        identity_monet = G_PM(real_monet)\n        identity_photo = G_MP(real_photo)\n\n        pred_fake_monet = D_M(fake_monet)\n        pred_fake_photo = D_P(fake_photo)\n\n        valid_monet = torch.ones_like(pred_fake_monet, device=device)\n        valid_photo = torch.ones_like(pred_fake_photo, device=device)\n\n        loss_G_PM = mse_loss(pred_fake_monet, valid_monet)\n        loss_G_MP = mse_loss(pred_fake_photo, valid_photo)\n\n        loss_cycle_monet = l1_loss(cycle_monet, real_monet)\n        loss_cycle_photo = l1_loss(cycle_photo, real_photo)\n        loss_cycle = loss_cycle_monet + loss_cycle_photo\n\n        loss_identity_monet = l1_loss(identity_monet, real_monet)\n        loss_identity_photo = l1_loss(identity_photo, real_photo)\n        loss_identity = loss_identity_monet + loss_identity_photo\n\n        loss_G = (\n            loss_G_PM\n            + loss_G_MP\n            + LAMBDA_CYCLE * loss_cycle\n            + LAMBDA_IDENTITY * loss_identity\n        )\n\n        loss_G.backward()\n        opt_G.step()\n\n        # --------------------------\n        # Train Monet Discriminator\n        # --------------------------\n        opt_D_M.zero_grad()\n\n        pred_real_monet = D_M(real_monet)\n        pred_fake_monet = D_M(fake_monet.detach())\n\n        valid = torch.ones_like(pred_real_monet, device=device)\n        fake = torch.zeros_like(pred_fake_monet, device=device)\n\n        loss_D_M_real = mse_loss(pred_real_monet, valid)\n        loss_D_M_fake = mse_loss(pred_fake_monet, fake)\n        loss_D_M = 0.5 * (loss_D_M_real + loss_D_M_fake)\n\n        loss_D_M.backward()\n        opt_D_M.step()\n\n        # --------------------------\n        # Train Photo Discriminator\n        # --------------------------\n        opt_D_P.zero_grad()\n\n        pred_real_photo = D_P(real_photo)\n        pred_fake_photo = D_P(fake_photo.detach())\n\n        valid = torch.ones_like(pred_real_photo, device=device)\n        fake = torch.zeros_like(pred_fake_photo, device=device)\n\n        loss_D_P_real = mse_loss(pred_real_photo, valid)\n        loss_D_P_fake = mse_loss(pred_fake_photo, fake)\n        loss_D_P = 0.5 * (loss_D_P_real + loss_D_P_fake)\n\n        loss_D_P.backward()\n        opt_D_P.step()\n\n        g_losses.append(loss_G.item())\n        d_m_losses.append(loss_D_M.item())\n        d_p_losses.append(loss_D_P.item())\n\n        if (step + 1) % 50 == 0 or step == 0:\n            print(\n                f\"Epoch [{epoch}/{EPOCHS}] \"\n                f\"Step [{step+1}/{steps_per_epoch}] \"\n                f\"G: {loss_G.item():.4f} \"\n                f\"D_M: {loss_D_M.item():.4f} \"\n                f\"D_P: {loss_D_P.item():.4f}\"\n            )\n\n    with torch.no_grad():\n        sample_photo, _ = next(iter(photo_loader))\n        sample_photo = sample_photo.to(device)\n        sample_fake_monet = G_PM(sample_photo)\n        save_preview(sample_photo, sample_fake_monet, epoch)\n\n    torch.save(G_PM.state_dict(), f\"/kaggle/working/G_PM_epoch_{epoch}.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T19:35:56.247841Z","iopub.execute_input":"2026-04-21T19:35:56.248103Z","iopub.status.idle":"2026-04-21T20:03:41.68955Z","shell.execute_reply.started":"2026-04-21T19:35:56.24807Z","shell.execute_reply":"2026-04-21T20:03:41.688753Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(10, 5))\nplt.plot(g_losses, label=\"G\")\nplt.plot(d_m_losses, label=\"D_M\")\nplt.plot(d_p_losses, label=\"D_P\")\nplt.legend()\nplt.title(\"Training losses\")\nplt.xlabel(\"Step\")\nplt.ylabel(\"Loss\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T20:03:41.691345Z","iopub.execute_input":"2026-04-21T20:03:41.69167Z","iopub.status.idle":"2026-04-21T20:03:41.852013Z","shell.execute_reply.started":"2026-04-21T20:03:41.691613Z","shell.execute_reply":"2026-04-21T20:03:41.851398Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"G_PM.eval()\n\nsample_img, sample_name = photo_dataset[0]\nwith torch.no_grad():\n    x = sample_img.unsqueeze(0).to(device)\n    y = G_PM(x).cpu().squeeze(0)\n\nout = denorm(y)\n\nplt.figure(figsize=(8, 8))\nplt.imshow(np.transpose(out.numpy(), (1, 2, 0)))\nplt.title(f\"Monet-style version of: {sample_name}\")\nplt.axis(\"off\")\nplt.show()\n\nsave_image(out, \"/kaggle/working/one_big_monet_painting.jpg\")\nprint(\"Saved: /kaggle/working/one_big_monet_painting.jpg\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T20:03:41.852848Z","iopub.execute_input":"2026-04-21T20:03:41.853155Z","iopub.status.idle":"2026-04-21T20:03:42.173036Z","shell.execute_reply.started":"2026-04-21T20:03:41.853129Z","shell.execute_reply":"2026-04-21T20:03:42.172459Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"G_PM.eval()\n\n# clean old outputs\nfor f in glob.glob(os.path.join(OUTPUT_DIR, \"*\")):\n    os.remove(f)\n\ninference_transform = transforms.Compose([\n    transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n])\n\nphoto_files = sorted([\n    os.path.join(PHOTO_DIR, f)\n    for f in os.listdir(PHOTO_DIR)\n    if f.lower().endswith((\".jpg\", \".jpeg\", \".png\"))\n])\n\nwith torch.no_grad():\n    for path in photo_files:\n        img = Image.open(path).convert(\"RGB\")\n        x = inference_transform(img).unsqueeze(0).to(device)\n        y = G_PM(x).cpu().squeeze(0)\n        y = denorm(y)\n\n        file_name = os.path.basename(path)\n        out_name = os.path.splitext(file_name)[0] + \".jpg\"\n        save_image(y, os.path.join(OUTPUT_DIR, out_name))\n\nprint(\"Generated images:\", len(os.listdir(OUTPUT_DIR)))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T20:03:42.174039Z","iopub.execute_input":"2026-04-21T20:03:42.174565Z","iopub.status.idle":"2026-04-21T20:08:04.630549Z","shell.execute_reply.started":"2026-04-21T20:03:42.17454Z","shell.execute_reply":"2026-04-21T20:08:04.629738Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"result_files = sorted(os.listdir(OUTPUT_DIR))[:4]\n\nplt.figure(figsize=(12, 12))\nfor i, fname in enumerate(result_files, 1):\n    img = Image.open(os.path.join(OUTPUT_DIR, fname)).convert(\"RGB\")\n    plt.subplot(2, 2, i)\n    plt.imshow(img)\n    plt.title(fname)\n    plt.axis(\"off\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T20:08:04.631754Z","iopub.execute_input":"2026-04-21T20:08:04.632016Z","iopub.status.idle":"2026-04-21T20:08:05.23441Z","shell.execute_reply.started":"2026-04-21T20:08:04.631993Z","shell.execute_reply":"2026-04-21T20:08:05.233421Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#save model\ntorch.save(G_PM.state_dict(), \"/kaggle/working/monetsgan2.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T20:08:05.237262Z","iopub.execute_input":"2026-04-21T20:08:05.23752Z","iopub.status.idle":"2026-04-21T20:08:05.294775Z","shell.execute_reply.started":"2026-04-21T20:08:05.237493Z","shell.execute_reply":"2026-04-21T20:08:05.294043Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"zip_path = \"images.zip\"\n\nwith zipfile.ZipFile(zip_path, \"w\", zipfile.ZIP_DEFLATED) as zipf:\n    for file_name in sorted(os.listdir(OUTPUT_DIR)):\n        file_path = os.path.join(OUTPUT_DIR, file_name)\n        zipf.write(file_path, arcname=file_name)\n\nprint(\"Saved zip:\", zip_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-21T20:08:05.295634Z","iopub.execute_input":"2026-04-21T20:08:05.295973Z","iopub.status.idle":"2026-04-21T20:08:07.381059Z","shell.execute_reply.started":"2026-04-21T20:08:05.295934Z","shell.execute_reply":"2026-04-21T20:08:07.380376Z"}},"outputs":[],"execution_count":null}]}