{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":30665,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from __future__ import print_function\nimport warnings\nwarnings.simplefilter('ignore')\n\nimport os\nimport random\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom PIL import Image\nfrom tqdm import tqdm\n\nimport copy","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:35.686205Z","iopub.execute_input":"2024-03-19T18:46:35.686564Z","iopub.status.idle":"2024-03-19T18:46:35.69339Z","shell.execute_reply.started":"2024-03-19T18:46:35.686534Z","shell.execute_reply":"2024-03-19T18:46:35.692264Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Create dataset.","metadata":{}},{"cell_type":"code","source":"class ImagesLoader(Dataset):\n    def __init__(self,path) -> None:\n        self.path = path\n        self.images = os.listdir(path)\n        self.transform = transforms.Compose([\n        transforms.Resize(256),\n        transforms.ToTensor(),\n        ])        \n\n    def __len__(self) -> int:\n        return len(self.images)\n\n    def init(self,stop=10000):\n        imgs = []\n        for idx,_ in enumerate(self.images[:stop]):\n            img = self.images[idx % len(self.images)]\n            image_path = os.path.join(self.path, img)\n            img =  Image.open(image_path).convert('RGB')\n            img = self.transform(img)\n            imgs.append(img)\n        return imgs\n\n    def __getitem__(self, idx):\n        img = self.images[idx % len(self.images)]\n        image_path = os.path.join(self.path, img)\n        img =  Image.open(image_path).convert('RGB')\n        img = self.transform(img)\n        return img\n    ","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:35.698138Z","iopub.execute_input":"2024-03-19T18:46:35.698953Z","iopub.status.idle":"2024-03-19T18:46:35.708988Z","shell.execute_reply.started":"2024-03-19T18:46:35.698922Z","shell.execute_reply":"2024-03-19T18:46:35.708078Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"monet_data=ImagesLoader('../input/gan-getting-started/monet_jpg')\nphoto_data=ImagesLoader('../input/gan-getting-started/photo_jpg')","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:35.710557Z","iopub.execute_input":"2024-03-19T18:46:35.71089Z","iopub.status.idle":"2024-03-19T18:46:35.727396Z","shell.execute_reply.started":"2024-03-19T18:46:35.710862Z","shell.execute_reply":"2024-03-19T18:46:35.726505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(device)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:35.728548Z","iopub.execute_input":"2024-03-19T18:46:35.728961Z","iopub.status.idle":"2024-03-19T18:46:35.734389Z","shell.execute_reply.started":"2024-03-19T18:46:35.728918Z","shell.execute_reply":"2024-03-19T18:46:35.733458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = monet_data.init()\nmonets = torch.stack(images)\n\n\n# images = photo_data.init()\n# photo_data = torch.stack(images)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:35.73627Z","iopub.execute_input":"2024-03-19T18:46:35.736565Z","iopub.status.idle":"2024-03-19T18:46:36.228892Z","shell.execute_reply.started":"2024-03-19T18:46:35.736533Z","shell.execute_reply":"2024-03-19T18:46:36.227871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(monets.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:36.230114Z","iopub.execute_input":"2024-03-19T18:46:36.2304Z","iopub.status.idle":"2024-03-19T18:46:36.235719Z","shell.execute_reply.started":"2024-03-19T18:46:36.230375Z","shell.execute_reply":"2024-03-19T18:46:36.234765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Condensating data set by augmentation. ","metadata":{}},{"cell_type":"code","source":"import torch.nn as nn\nimport torchvision.transforms as T\nfrom pathlib import Path\n\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nimport torch\nimport torchvision.transforms as T\nfrom torchvision.io import read_image\n\n\nplt.rcParams[\"savefig.bbox\"] = 'tight'\ntorch.manual_seed(1)\n\n\ndef show(imgs):\n    fix, axs = plt.subplots(ncols=len(imgs), squeeze=False)\n    for i, img in enumerate(imgs):\n        img = T.ToPILImage()(img.to('cpu'))\n        axs[0, i].imshow(np.asarray(img))\n        axs[0, i].set(xticklabels=[], yticklabels=[], xticks=[], yticks=[])\n\n\ntransforms_crop = torch.nn.Sequential(\n    T.RandomResizedCrop(256,(0.1,0.7)),\n    T.RandomHorizontalFlip(p=0.2),\n)\ntransform_flip=torch.nn.Sequential(\n    T.RandomResizedCrop(256,(0.90,1)),\n    T.RandomHorizontalFlip(p=0.2),\n)\nmonets=monets.to(device)\ndef augment():\n    return torch.cat((transforms_crop(monets),transform_flip(monets)),0)\n\ntransformed=augment()\nprint(transformed.shape)\nshow([transformed[2], monets[2]])\nmonet_train=torch.cat((monets,transformed),0)\n","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:36.236948Z","iopub.execute_input":"2024-03-19T18:46:36.237823Z","iopub.status.idle":"2024-03-19T18:46:36.60661Z","shell.execute_reply.started":"2024-03-19T18:46:36.23779Z","shell.execute_reply":"2024-03-19T18:46:36.605605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TrainDataset(Dataset):\n    def __init__(self, monet_ds, photo_ds):\n        self.monet_ds = monet_ds\n        self.photo_ds = photo_ds\n        \n    def __len__(self):\n        return max(len(self.monet_ds), len(self.photo_ds))\n\n    def __getitem__(self, idx):\n        monet_idx = idx % len(self.monet_ds)\n        photo_idx = idx % len(self.photo_ds)\n    \n        monet_img = self.monet_ds[monet_idx]\n        photo_img = self.photo_ds[photo_idx]\n        \n        return monet_img, photo_img","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:36.607902Z","iopub.execute_input":"2024-03-19T18:46:36.608195Z","iopub.status.idle":"2024-03-19T18:46:36.61457Z","shell.execute_reply.started":"2024-03-19T18:46:36.608169Z","shell.execute_reply":"2024-03-19T18:46:36.613713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show(monet_train[:2])\n\ntrain_dataset=TrainDataset(monet_train,photo_data)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:36.615882Z","iopub.execute_input":"2024-03-19T18:46:36.616155Z","iopub.status.idle":"2024-03-19T18:46:36.845405Z","shell.execute_reply.started":"2024-03-19T18:46:36.61613Z","shell.execute_reply":"2024-03-19T18:46:36.84455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"monet_img, photo_img = train_dataset.__getitem__(0)\nprint(monet_img.shape)\nprint(photo_img.shape)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:36.84814Z","iopub.execute_input":"2024-03-19T18:46:36.848434Z","iopub.status.idle":"2024-03-19T18:46:37.1766Z","shell.execute_reply.started":"2024-03-19T18:46:36.848407Z","shell.execute_reply":"2024-03-19T18:46:37.175645Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"imsize = 256 #512 if torch.cuda.is_available() else 128  # use small size if no gpu\n\nloader = transforms.Compose([\n    transforms.Resize(imsize), \n    transforms.ToTensor()]) \n\nto_pil = T.ToPILImage()\n\ndef image_loader(image):\n    # convert the tensor to PIL image using above transform\n    image = to_pil(image)\n    # fake batch dimension required to fit network's input dimensions\n    image = loader(image).unsqueeze(0)\n    return image.to(device, torch.float)\n\n# define a transform to convert a tensor to PIL image\nto_pil = T.ToPILImage()\n# convert the tensor to PIL image using above transform\nimg = to_pil(monet_train[3])\n# display the PIL image\n\nstyle_img = image_loader(monet_train[3])\ncontent_img = image_loader(photo_data[3])\n\nprint(style_img.size())\nprint(style_img.size())\ncontent_img.clone()\n\nassert style_img.size() == content_img.size(), \\\n    \"we need to import style and content images of the same size\"\n\n","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:37.177765Z","iopub.execute_input":"2024-03-19T18:46:37.178039Z","iopub.status.idle":"2024-03-19T18:46:37.195485Z","shell.execute_reply.started":"2024-03-19T18:46:37.178016Z","shell.execute_reply":"2024-03-19T18:46:37.194701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Blocks","metadata":{}},{"cell_type":"code","source":"import torch.nn as nn\n\nclass ResBlock(nn.Module):\n    def __init__(self, f):\n        super(ResBlock, self).__init__()\n        self.conv = nn.Sequential(\n            nn.Conv2d(f, f, 3, 1, 1), \n            nn.InstanceNorm2d(f),\n            nn.ReLU(),\n            \n            nn.Conv2d(f, f, 3, 1, 1),\n        )\n        \n        self.norm = nn.InstanceNorm2d(f)\n        \n    def forward(self, x):\n        return torch.relu(self.conv(x) + x)\n    ","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:37.196616Z","iopub.execute_input":"2024-03-19T18:46:37.19723Z","iopub.status.idle":"2024-03-19T18:46:37.205116Z","shell.execute_reply.started":"2024-03-19T18:46:37.197194Z","shell.execute_reply":"2024-03-19T18:46:37.204193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Generator","metadata":{}},{"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, f=64, res_blocks=6):\n        super(Generator, self).__init__()\n        layers = []\n            \n        layers.extend([\n            nn.Conv2d(3, f, 7, 1, 3),\n            nn.InstanceNorm2d(f), \n            nn.ReLU(True),\n\n            nn.Conv2d(f, f * 2, 3, 2, 1),\n            nn.InstanceNorm2d(f * 2),\n            nn.ReLU(True),\n\n            nn.Conv2d(f * 2, f * 4, 3, 2, 1),\n            nn.InstanceNorm2d(f * 4),\n            nn.ReLU(True)\n        ])\n            \n        for i in range(res_blocks):\n            layers.append(ResBlock(f * 4))\n        \n        layers.extend([\n            nn.ConvTranspose2d(f * 4, f * 2 * 4, 3, 1, 1),\n            nn.PixelShuffle(2),\n            nn.InstanceNorm2d(f * 2),\n            nn.ReLU(True),\n            \n            nn.ConvTranspose2d(f * 2, f * 4, 3, 1, 1),\n            nn.PixelShuffle(2),\n            nn.InstanceNorm2d(f),\n            nn.ReLU(True),\n    \n            nn.ReflectionPad2d(3),\n            nn.Conv2d(f, 3, 7, 1, 0),\n            nn.Tanh()\n            \n        ])\n         \n        self.conv = nn.Sequential(*layers)\n\n    def forward(self, x):\n        return self.conv(x)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:37.206413Z","iopub.execute_input":"2024-03-19T18:46:37.2067Z","iopub.status.idle":"2024-03-19T18:46:37.217145Z","shell.execute_reply.started":"2024-03-19T18:46:37.206643Z","shell.execute_reply":"2024-03-19T18:46:37.216313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Discriminator","metadata":{}},{"cell_type":"code","source":"import torch.nn.functional as F\nclass Discriminator(nn.Module):\n    def __init__(self, in_channels=3, ndf=64):\n        super(Discriminator, self).__init__()\n        self.conv1 = nn.Conv2d(in_channels, ndf, kernel_size=4, stride=2, padding=1)\n        self.conv2 = nn.Conv2d(ndf, ndf * 2, kernel_size=4, stride=2, padding=1)\n        self.conv3 = nn.Conv2d(ndf * 2, ndf * 4, kernel_size=4, stride=2, padding=1)\n        self.conv4 = nn.Conv2d(ndf * 4, ndf * 8, kernel_size=4, stride=1, padding=1)\n        self.conv5 = nn.Conv2d(ndf * 8, 1, kernel_size=4, stride=1, padding=1)\n\n    def forward(self, x):\n        x = F.leaky_relu(self.conv1(x), negative_slope=0.2)\n        x = F.leaky_relu(self.conv2(x), negative_slope=0.2)\n        x = F.leaky_relu(self.conv3(x), negative_slope=0.2)\n        x = F.leaky_relu(self.conv4(x), negative_slope=0.2)\n        x = self.conv5(x)\n        return x\n","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:37.218081Z","iopub.execute_input":"2024-03-19T18:46:37.218333Z","iopub.status.idle":"2024-03-19T18:46:37.232243Z","shell.execute_reply.started":"2024-03-19T18:46:37.218302Z","shell.execute_reply":"2024-03-19T18:46:37.231295Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"disc_M = Discriminator().to(device)\ndisc_P = Discriminator().to(device)\n\ngen_M = Generator().to(device)\ngen_P = Generator().to(device)\n\nopt_disc = torch.optim.Adam(\n    list(disc_M.parameters()) + list(disc_P.parameters()),\n    lr=2e-4,\n    betas=(0.5, 0.999)\n)\n\nopt_gen = torch.optim.Adam(\n    list(gen_M.parameters()) + list(gen_P.parameters()),\n    lr=2e-4,\n    betas=(0.5, 0.999)\n)\n\nl1 = nn.L1Loss()\nmse = nn.MSELoss()\nloader = DataLoader(train_dataset , batch_size=1, shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2024-03-19T18:46:37.233626Z","iopub.execute_input":"2024-03-19T18:46:37.234055Z","iopub.status.idle":"2024-03-19T18:46:37.467112Z","shell.execute_reply.started":"2024-03-19T18:46:37.234018Z","shell.execute_reply":"2024-03-19T18:46:37.466326Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_epochs = 1\nD_loss_arr=[]\nG_loss_arr=[]\n\nfor epoch in range(num_epochs):\n    loop = tqdm(loader, leave=True)\n    \n    for idx, (monet, photo) in enumerate(loop):\n        #limit beacuse we have no gpu \n        monet = monet.to(device)\n        photo = photo.to(device)\n#         print(\"monet \",monet.shape)\n#         print(\"photo \",photo.shape)\n        fake_photo = gen_P(monet)\n#         print(\"fake_photo\",fake_photo.shape)\n        D_P_real = disc_P(photo)\n#         print(\"D_P_real\",D_P_real.shape)\n        D_P_fake = disc_P(fake_photo.detach())\n#         print(\"D_P_fake\",D_P_fake.shape)\n        D_P_real_loss = mse(D_P_real, torch.ones(len(D_P_real)).to(device))\n#         print(\"D_P_real_loss\",D_P_real_loss.shape)\n        D_P_fake_loss = mse(D_P_fake, torch.zeros(len(D_P_fake)).to(device))\n#         print(\"D_P_fake_loss\",D_P_fake_loss.shape)\n        D_P_loss = D_P_real_loss + D_P_fake_loss\n\n        fake_monet = gen_M(photo)\n#         print(\"fake_monet\",fake_monet.shape)\n        D_M_real = disc_M(monet)\n#         print(\"D_M_real\",D_M_real.shape)\n        D_M_fake = disc_M(fake_monet.detach())\n#         print(\"D_M_fake\",D_M_fake.shape)\n        D_M_real_loss = mse(D_M_real, torch.ones(len(D_M_real)).to(device))     \n        #pdb.set_trace()\n        D_M_fake_loss = mse(D_M_fake, torch.zeros(len(D_M_fake)).to(device))\n        D_M_loss = D_M_real_loss + D_M_fake_loss\n\n        D_loss = (D_P_loss + D_M_loss) / 2\n        D_loss_arr.append(D_loss.item())\n        opt_disc.zero_grad()\n        D_loss.backward()\n        opt_disc.step()\n\n        D_P_fake = disc_P(fake_photo)\n        D_M_fake = disc_M(fake_monet)\n        loss_G_P = mse(D_P_fake, torch.ones(len(D_P_fake)).to(device))\n        loss_G_M = mse(D_M_fake, torch.ones(len(D_M_fake)).to(device))\n\n        cycle_photo = gen_P(fake_monet)\n        cycle_monet = gen_M(fake_photo)\n        cycle_photo_loss = l1(photo, cycle_photo)\n        cycle_monet_loss = l1(monet, cycle_monet)\n\n        identity_photo = gen_P(photo)\n        identity_monet = gen_M(monet)\n        identity_photo_loss = l1(photo, identity_photo)\n        identity_monet_loss = l1(monet, identity_monet)\n\n        G_loss = (\n            loss_G_P \n            + loss_G_M \n            + cycle_photo_loss * 10\n            + cycle_monet_loss * 10\n             + identity_photo_loss\n            + identity_monet_loss\n        )\n        G_loss_arr.append(G_loss.item())\n        opt_gen.zero_grad()\n        G_loss.backward()\n        opt_gen.step()\n        \n        if idx % 2000 == 0:\n            print(\n                'G_P_loss:', loss_G_P.cpu().detach().item(), \n                'G_M_loss:', loss_G_M.cpu().detach().item(), \n                'D_M_loss:', D_M_loss.cpu().detach().item(), \n                'D_P_loss:', D_P_loss.cpu().detach().item()\n            )\n            print(f\"G_loss {idx} = \",G_loss)\n            print(f\"D_loss {idx} = \",D_loss)\n    print(f\"Final epoch {epoch} G_loss {idx} = \",G_loss)\n    print(f\"Final epoch {epoch} D_loss {idx} = \",D_loss)","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-03-19T18:46:37.468597Z","iopub.execute_input":"2024-03-19T18:46:37.46899Z","iopub.status.idle":"2024-03-19T19:16:59.848975Z","shell.execute_reply.started":"2024-03-19T18:46:37.468951Z","shell.execute_reply":"2024-03-19T19:16:59.848031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for idx, (monet, photo) in enumerate(loader):\n    monet = monet.to(device)\n    photo = photo.to(device)\n    fake_photo = gen_P(monet)\n    fake_monet = gen_M(photo).cpu().detach()[0]\n    \n    plt.subplot(121)\n    plt.imshow(photo.cpu().detach()[0].squeeze().permute(1, 2, 0) )\n    plt.subplot(122)\n    plt.imshow(fake_monet.squeeze().permute(1, 2, 0) )\n        \n    plt.show()\n    if idx == 4:\n        break","metadata":{"execution":{"iopub.status.busy":"2024-03-19T19:17:51.654009Z","iopub.execute_input":"2024-03-19T19:17:51.65472Z","iopub.status.idle":"2024-03-19T19:17:53.666902Z","shell.execute_reply.started":"2024-03-19T19:17:51.654686Z","shell.execute_reply":"2024-03-19T19:17:53.665932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import PIL\n! mkdir ./images2\n","metadata":{"execution":{"iopub.status.busy":"2024-03-19T19:17:53.668644Z","iopub.execute_input":"2024-03-19T19:17:53.668973Z","iopub.status.idle":"2024-03-19T19:17:55.041873Z","shell.execute_reply.started":"2024-03-19T19:17:53.668946Z","shell.execute_reply":"2024-03-19T19:17:55.040672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"photo_data=ImagesLoader('../input/gan-getting-started/photo_jpg')\nimport PIL\ni = 1\nprint(len(train_dataset))\nfor photo in tqdm(photo_data):\n    \n    photo = photo.to(device)\n    prediction = gen_M(photo[None, :]).cpu().detach()[0]\n    prediction = ( prediction).permute(1, 2, 0).numpy().astype(np.uint8)\n#     plt.imshow(prediction)\n    im = PIL.Image.fromarray(prediction)\n    im.save(\"./images2/\" + str(i) + \".jpg\")\n    i += 1","metadata":{"execution":{"iopub.status.busy":"2024-03-19T19:17:55.043348Z","iopub.execute_input":"2024-03-19T19:17:55.043638Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\nshutil.make_archive('/kaggle/working/images/', 'zip', '/kaggle/working/images2/')","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}