{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":21755,"databundleVersionId":1475600,"sourceType":"competition"}],"dockerImageVersionId":30822,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:23.167112Z","iopub.execute_input":"2024-12-21T11:35:23.16753Z","iopub.status.idle":"2024-12-21T11:35:39.468796Z","shell.execute_reply.started":"2024-12-21T11:35:23.167486Z","shell.execute_reply":"2024-12-21T11:35:39.46761Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\n\nimport torchvision.transforms as transforms\nfrom torchvision.utils import make_grid\n\nfrom torch.utils.data import DataLoader\nfrom torchvision import datasets\nfrom torch.autograd import Variable\n\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch\n\nimport cv2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:39.47072Z","iopub.execute_input":"2024-12-21T11:35:39.471116Z","iopub.status.idle":"2024-12-21T11:35:46.254011Z","shell.execute_reply.started":"2024-12-21T11:35:39.47109Z","shell.execute_reply":"2024-12-21T11:35:46.253039Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import glob\ndata_dir = '/kaggle/input/gan-getting-started/'\nprint(len(glob.glob(os.path.join(data_dir+'/monet_jpg')+'/*.*')))\nlen(glob.glob(os.path.join(data_dir+'/photo_jpg')+'/*.*'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.255596Z","iopub.execute_input":"2024-12-21T11:35:46.256018Z","iopub.status.idle":"2024-12-21T11:35:46.285389Z","shell.execute_reply.started":"2024-12-21T11:35:46.255991Z","shell.execute_reply":"2024-12-21T11:35:46.284366Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"monet_image_path = glob.glob(os.path.join(data_dir+'/monet_jpg')+'/*.*')\nshape = cv2.imread(monet_image_path[0]).shape\nshape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.286503Z","iopub.execute_input":"2024-12-21T11:35:46.286899Z","iopub.status.idle":"2024-12-21T11:35:46.327965Z","shell.execute_reply.started":"2024-12-21T11:35:46.28686Z","shell.execute_reply":"2024-12-21T11:35:46.326923Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img_height = 256\nimg_width = 256\nchannels = 3\n\nfrom PIL import Image\n\ntransforms_ = [\n    transforms.Resize(int(img_height*1.12), Image.BICUBIC),\n    transforms.RandomCrop((img_height, img_width)),\n    transforms.RandomHorizontalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n]\ndef to_rgb(image):\n    rgb_image = Image.new(\"RGB\", image.size)\n    rgb_image.paste(image)\n    return rgb_image","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.329105Z","iopub.execute_input":"2024-12-21T11:35:46.329454Z","iopub.status.idle":"2024-12-21T11:35:46.33584Z","shell.execute_reply.started":"2024-12-21T11:35:46.3294Z","shell.execute_reply":"2024-12-21T11:35:46.334679Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import Dataset\n\nclass ImageDataset(Dataset):\n    def __init__(self, root, transforms_=None, unaligned=False, mode='train'):\n        self.transform = transforms.Compose(transforms_)\n        self.unaligned = unaligned\n        self.mode = mode\n        if self.mode == 'train':\n            self.files_A = sorted(glob.glob(os.path.join(root+'/monet_jpg')+'/*.*')[:250])\n            self.files_B = sorted(glob.glob(os.path.join(root+'/photo_jpg')+'/*.*')[:250])\n        elif self.mode == 'test':\n            self.files_A = sorted(glob.glob(os.path.join(root+'/monet_jpg')+'/*.*')[250:])\n            self.files_B = sorted(glob.glob(os.path.join(root+'/photo_jpg')+'/*.*')[250:301])\n\n    def  __getitem__(self, index):\n        image_A = Image.open(self.files_A[index % len(self.files_A)])\n        if self.unaligned:\n            image_B = Image.open(self.files_B[np.random.randint(0, len(self.files_B)-1)])\n        else:\n            image_B = Image.open(self.files_B[index % len(self.files_B)])\n        if image_A.mode != 'RGB':\n            image_A = to_rgb(image_A)\n        if image_B.mode != 'RGB':\n            image_B = to_rgb(image_B)\n            \n        item_A = self.transform(image_A)\n        item_B = self.transform(image_B)\n        return {'A':item_A, 'B':item_B}\n    \n    def __len__(self):\n        return max(len(self.files_A), len(self.files_B))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.336972Z","iopub.execute_input":"2024-12-21T11:35:46.337354Z","iopub.status.idle":"2024-12-21T11:35:46.355991Z","shell.execute_reply.started":"2024-12-21T11:35:46.337313Z","shell.execute_reply":"2024-12-21T11:35:46.35485Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataloader = DataLoader(\n    ImageDataset(data_dir, transforms_=transforms_, unaligned=True),\n    batch_size=1, # 1\n    shuffle=True\n)\n\nval_dataloader = DataLoader(\n    ImageDataset(data_dir, transforms_=transforms_, unaligned=True, mode='test'),\n    batch_size=5,\n    shuffle=True\n)  ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.357087Z","iopub.execute_input":"2024-12-21T11:35:46.357522Z","iopub.status.idle":"2024-12-21T11:35:46.416229Z","shell.execute_reply.started":"2024-12-21T11:35:46.357482Z","shell.execute_reply":"2024-12-21T11:35:46.415063Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ResidualBlock(nn.Module):\n    def __init__(self, in_features):\n        super(ResidualBlock, self).__init__()\n        \n        self.block = nn.Sequential(\n            nn.ReflectionPad2d(1), # Pads the input tensor using the reflection of the input boundary\n            nn.Conv2d(in_features, in_features, 3),\n            nn.InstanceNorm2d(in_features), \n            nn.ReLU(inplace=True),\n            nn.ReflectionPad2d(1),\n            nn.Conv2d(in_features, in_features, 3),\n            nn.InstanceNorm2d(in_features)\n        )\n\n    def forward(self, x):\n        return x + self.block(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.41967Z","iopub.execute_input":"2024-12-21T11:35:46.419966Z","iopub.status.idle":"2024-12-21T11:35:46.425627Z","shell.execute_reply.started":"2024-12-21T11:35:46.419942Z","shell.execute_reply":"2024-12-21T11:35:46.424545Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class GeneratorResNet(nn.Module):\n    def __init__(self, input_shape, num_residual_block):\n        super(GeneratorResNet, self).__init__()\n        \n        channels = input_shape[0]\n        \n        # Initial Convolution Block\n        out_features = 64\n        model = [\n            nn.ReflectionPad2d(channels),\n            nn.Conv2d(channels, out_features, 7),\n            nn.InstanceNorm2d(out_features),\n            nn.ReLU(inplace=True)\n        ]\n        in_features = out_features\n        \n        # Downsampling\n        for _ in range(2):\n            out_features *= 2\n            model += [\n                nn.Conv2d(in_features, out_features, 3, stride=2, padding=1),\n                nn.InstanceNorm2d(out_features),\n                nn.ReLU(inplace=True)\n            ]\n            in_features = out_features\n        # Residual blocks\n        for _ in range(num_residual_block):\n            model += [ResidualBlock(out_features)]\n            \n        # Upsampling\n        for _ in range(2):\n            out_features //= 2\n            model += [\n                nn.Upsample(scale_factor=2), # --> width*2, heigh*2\n                nn.Conv2d(in_features, out_features, 3, stride=1, padding=1),\n                nn.ReLU(inplace=True)\n            ]\n            in_features = out_features\n            \n        # Output Layer\n        model += [nn.ReflectionPad2d(channels),\n                  nn.Conv2d(out_features, channels, 7),\n                  nn.Tanh()\n                 ]\n        \n        # Unpacking\n        self.model = nn.Sequential(*model) \n        \n    def forward(self, x):\n        return self.model(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.427353Z","iopub.execute_input":"2024-12-21T11:35:46.427864Z","iopub.status.idle":"2024-12-21T11:35:46.451679Z","shell.execute_reply.started":"2024-12-21T11:35:46.427704Z","shell.execute_reply":"2024-12-21T11:35:46.450676Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self, input_shape):\n        super(Discriminator, self).__init__()\n        \n        channels, height, width = input_shape\n        \n        # Calculate output shape of image discriminator (PatchGAN)\n        self.output_shape = (1, height//2**4, width//2**4)\n        \n        def discriminator_block(in_filters, out_filters, normalize=True):\n            layers = [nn.Conv2d(in_filters, out_filters, 4, stride=2, padding=1)]\n            if normalize:\n                layers.append(nn.InstanceNorm2d(out_filters))\n            layers.append(nn.LeakyReLU(0.2, inplace=True))\n            return layers\n        \n        self.model = nn.Sequential(\n            *discriminator_block(channels, 64, normalize=False),\n            *discriminator_block(64, 128),\n            *discriminator_block(128,256),\n            *discriminator_block(256,512),\n            nn.ZeroPad2d((1,0,1,0)),\n            nn.Conv2d(512, 1, 4, padding=1)\n        )\n        \n    def forward(self, img):\n        return self.model(img)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.452818Z","iopub.execute_input":"2024-12-21T11:35:46.453133Z","iopub.status.idle":"2024-12-21T11:35:46.481551Z","shell.execute_reply.started":"2024-12-21T11:35:46.453107Z","shell.execute_reply":"2024-12-21T11:35:46.480528Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion_GAN = torch.nn.MSELoss()\ncriterion_cycle = torch.nn.L1Loss()\ncriterion_identity = torch.nn.L1Loss()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.482617Z","iopub.execute_input":"2024-12-21T11:35:46.483013Z","iopub.status.idle":"2024-12-21T11:35:46.508071Z","shell.execute_reply.started":"2024-12-21T11:35:46.482975Z","shell.execute_reply":"2024-12-21T11:35:46.506874Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"input_shape = (channels, img_height, img_width) # (3,256,256)\nn_residual_blocks = 9 # suggested default, number of residual blocks in generator\n\nG_AB = GeneratorResNet(input_shape, n_residual_blocks)\nG_BA = GeneratorResNet(input_shape, n_residual_blocks)\nD_A = Discriminator(input_shape)\nD_B = Discriminator(input_shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.509091Z","iopub.execute_input":"2024-12-21T11:35:46.509441Z","iopub.status.idle":"2024-12-21T11:35:46.875866Z","shell.execute_reply.started":"2024-12-21T11:35:46.509382Z","shell.execute_reply":"2024-12-21T11:35:46.874722Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cuda = torch.cuda.is_available()\n\nif cuda:\n    G_AB = G_AB.cuda()\n    G_BA = G_BA.cuda()\n    D_A = D_A.cuda()\n    D_B = D_B.cuda()\n    \n    criterion_GAN.cuda()\n    criterion_cycle.cuda()\n    criterion_identity.cuda()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.876891Z","iopub.execute_input":"2024-12-21T11:35:46.877189Z","iopub.status.idle":"2024-12-21T11:35:46.887201Z","shell.execute_reply.started":"2024-12-21T11:35:46.877162Z","shell.execute_reply":"2024-12-21T11:35:46.886173Z"}},"outputs":[],"execution_count":null},{"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":"2024-12-21T11:35:46.887916Z","iopub.execute_input":"2024-12-21T11:35:46.888177Z","iopub.status.idle":"2024-12-21T11:35:46.908794Z","shell.execute_reply.started":"2024-12-21T11:35:46.888154Z","shell.execute_reply":"2024-12-21T11:35:46.9075Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"G_AB.apply(weights_init_normal)\nG_BA.apply(weights_init_normal)\nD_A.apply(weights_init_normal)\nD_B.apply(weights_init_normal)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:46.910469Z","iopub.execute_input":"2024-12-21T11:35:46.910894Z","iopub.status.idle":"2024-12-21T11:35:47.155692Z","shell.execute_reply.started":"2024-12-21T11:35:46.910854Z","shell.execute_reply":"2024-12-21T11:35:47.154693Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import itertools\nlr = 0.0002\nb1 = 0.5\nb2 = 0.999\n\noptimizer_G = torch.optim.Adam(\n    itertools.chain(G_AB.parameters(), G_BA.parameters()), lr=lr, betas=(b1,b2)\n)\noptimizer_D_A = torch.optim.Adam(\n    D_A.parameters(), lr=lr, betas=(b1,b2)\n)\noptimizer_D_B = torch.optim.Adam(\n    D_B.parameters(), lr=lr, betas=(b1,b2)\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:47.156821Z","iopub.execute_input":"2024-12-21T11:35:47.157194Z","iopub.status.idle":"2024-12-21T11:35:47.164045Z","shell.execute_reply.started":"2024-12-21T11:35:47.157159Z","shell.execute_reply":"2024-12-21T11:35:47.162879Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class LambdaLR:\n    def __init__(self, n_epochs, offset, decay_start_epoch):\n        assert (n_epochs - decay_start_epoch) > 0\n        self.n_epochs = n_epochs\n        self.offset = offset\n        self.decay_start_epoch = decay_start_epoch\n        \n    def step(self, epoch):\n        return 1.0 - max(0, epoch+self.offset - self.decay_start_epoch)/(self.n_epochs - self.decay_start_epoch)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:47.164785Z","iopub.execute_input":"2024-12-21T11:35:47.165053Z","iopub.status.idle":"2024-12-21T11:35:47.185311Z","shell.execute_reply.started":"2024-12-21T11:35:47.165031Z","shell.execute_reply":"2024-12-21T11:35:47.183985Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"n_epochs = 10\nepoch = 0\ndecay_epoch = 5\n\n\nlr_scheduler_G = torch.optim.lr_scheduler.LambdaLR(\n    optimizer_G,\n    lr_lambda=LambdaLR(n_epochs, epoch, decay_epoch).step\n)\n\nlr_scheduler_D_A = torch.optim.lr_scheduler.LambdaLR(\n    optimizer_D_A,\n    lr_lambda=LambdaLR(n_epochs, epoch, decay_epoch).step\n)\nlr_scheduler_D_B = torch.optim.lr_scheduler.LambdaLR(\n    optimizer_D_B,\n    lr_lambda=LambdaLR(n_epochs, epoch, decay_epoch).step\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:47.186376Z","iopub.execute_input":"2024-12-21T11:35:47.186865Z","iopub.status.idle":"2024-12-21T11:35:47.207867Z","shell.execute_reply.started":"2024-12-21T11:35:47.186819Z","shell.execute_reply":"2024-12-21T11:35:47.206616Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nTensor = torch.cuda.FloatTensor if cuda else torch.Tensor\n\ndef sample_images():\n    imgs = next(iter(val_dataloader))\n    G_AB.eval()\n    G_BA.eval()\n    real_A = imgs['A'].type(Tensor) # A : monet\n    fake_B = G_AB(real_A).detach()\n    real_B = imgs['B'].type(Tensor) # B : photo\n    fake_A = G_BA(real_B).detach()\n    # Arange images along x-axis\n    real_A = make_grid(real_A, nrow=5, normalize=True)\n    fake_B = make_grid(fake_B, nrow=5, normalize=True)\n    real_B = make_grid(real_B, nrow=5, normalize=True)\n    fake_A = make_grid(fake_A, nrow=5, normalize=True)\n    # Arange images along y-axis    \n    image_grid = torch.cat((real_A, fake_B, real_B, fake_A), 1)\n    plt.imshow(image_grid.cpu().permute(1,2,0))\n    plt.title('Real A vs Fake B | Real B vs Fake A')\n    plt.axis('off')\n    plt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:47.209148Z","iopub.execute_input":"2024-12-21T11:35:47.20955Z","iopub.status.idle":"2024-12-21T11:35:47.22701Z","shell.execute_reply.started":"2024-12-21T11:35:47.209485Z","shell.execute_reply":"2024-12-21T11:35:47.22603Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"temp_imgs = next(iter(val_dataloader))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:47.228301Z","iopub.execute_input":"2024-12-21T11:35:47.228726Z","iopub.status.idle":"2024-12-21T11:35:47.626076Z","shell.execute_reply.started":"2024-12-21T11:35:47.228685Z","shell.execute_reply":"2024-12-21T11:35:47.625107Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"G_AB.eval() # test mode \nG_BA.eval() # test mode\nprint(temp_imgs['A'].shape)\nprint(temp_imgs['B'].shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:47.62714Z","iopub.execute_input":"2024-12-21T11:35:47.62757Z","iopub.status.idle":"2024-12-21T11:35:47.635789Z","shell.execute_reply.started":"2024-12-21T11:35:47.627528Z","shell.execute_reply":"2024-12-21T11:35:47.634687Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"temp_real_A = temp_imgs['A'].type(Tensor) # A : monet\ntemp_fake_B = G_AB(temp_real_A).detach()\ntemp_real_B = temp_imgs['B'].type(Tensor) # B : photo\ntemp_fake_A = G_BA(temp_real_B).detach()\n\nprint(temp_real_A.shape)\nprint(temp_fake_B.shape)\nprint(temp_real_B.shape)\nprint(temp_fake_A.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:47.636666Z","iopub.execute_input":"2024-12-21T11:35:47.636993Z","iopub.status.idle":"2024-12-21T11:35:59.5087Z","shell.execute_reply.started":"2024-12-21T11:35:47.636965Z","shell.execute_reply":"2024-12-21T11:35:59.507644Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"temp_real_A = make_grid(temp_real_A, nrow=5, normalize=True)\ntemp_real_B = make_grid(temp_real_B, nrow=5, normalize=True)\ntemp_fake_A = make_grid(temp_fake_A, nrow=5, normalize=True)\ntemp_fake_B = make_grid(temp_fake_B, nrow=5, normalize=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:59.509637Z","iopub.execute_input":"2024-12-21T11:35:59.509964Z","iopub.status.idle":"2024-12-21T11:35:59.529391Z","shell.execute_reply.started":"2024-12-21T11:35:59.509925Z","shell.execute_reply":"2024-12-21T11:35:59.528255Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(temp_real_A.cpu().permute(1,2,0))\nplt.title('Real A')\nplt.axis('off')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:59.530514Z","iopub.execute_input":"2024-12-21T11:35:59.530971Z","iopub.status.idle":"2024-12-21T11:35:59.807696Z","shell.execute_reply.started":"2024-12-21T11:35:59.530927Z","shell.execute_reply":"2024-12-21T11:35:59.806551Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(temp_real_A.shape)\nprint(temp_fake_B.shape)\nprint(temp_real_B.shape)\nprint(temp_fake_A.shape)\n\ntemp_image_grid = torch.cat((temp_real_A, temp_fake_A, temp_real_B, temp_fake_B), 1)\nprint(temp_image_grid.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:59.808735Z","iopub.execute_input":"2024-12-21T11:35:59.809084Z","iopub.status.idle":"2024-12-21T11:35:59.818728Z","shell.execute_reply.started":"2024-12-21T11:35:59.809054Z","shell.execute_reply":"2024-12-21T11:35:59.81752Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(temp_image_grid.cpu().permute(1,2,0))\nplt.title('Real A | Fake B | Real B | Fake A ')\nplt.axis('off')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:35:59.822578Z","iopub.execute_input":"2024-12-21T11:35:59.822886Z","iopub.status.idle":"2024-12-21T11:36:00.316886Z","shell.execute_reply.started":"2024-12-21T11:35:59.822858Z","shell.execute_reply":"2024-12-21T11:36:00.315685Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nfrom tqdm import tqdm\nimport warnings\n\nfor epoch in range(epoch, n_epochs):\n    for i, batch in enumerate(tqdm(dataloader)):\n        \n        # Set model input\n        real_A = batch['A'].type(Tensor)\n        real_B = batch['B'].type(Tensor)\n        \n        # Adversarial ground truths\n        valid = Tensor(np.ones((real_A.size(0), *D_A.output_shape))) # requires_grad = False. Default.\n        fake = Tensor(np.zeros((real_A.size(0), *D_A.output_shape))) # requires_grad = False. Default.\n        \n# -----------------\n# Train Generators\n# -----------------\n        G_AB.train() # train mode\n        G_BA.train() # train mode\n        \n        optimizer_G.zero_grad() # Integrated optimizer(G_AB, G_BA)\n        \n        # Identity Loss\n        loss_id_A = criterion_identity(G_BA(real_A), real_A) # If you put A into a generator that creates A with B,\n        loss_id_B = criterion_identity(G_AB(real_B), real_B) # then of course A must come out as it is.\n                                                             # Taking this into consideration, add an identity loss that simply compares 'A and A' (or 'B and B').\n        loss_identity = (loss_id_A + loss_id_B)/2\n        \n        # GAN Loss\n        fake_B = G_AB(real_A) # fake_B is fake-photo that generated by real monet-drawing\n        loss_GAN_AB = criterion_GAN(D_B(fake_B), valid) # tricking the 'fake-B' into 'real-B'\n        fake_A = G_BA(real_B)\n        loss_GAN_BA = criterion_GAN(D_A(fake_A), valid) # tricking the 'fake-A' into 'real-A'\n        \n        loss_GAN = (loss_GAN_AB + loss_GAN_BA)/2\n        \n        # Cycle Loss\n        recov_A = G_BA(fake_B) # recov_A is fake-monet-drawing that generated by fake-photo\n        loss_cycle_A = criterion_cycle(recov_A, real_A) # Reduces the difference between the restored image and the real image\n        recov_B = G_AB(fake_A)\n        loss_cycle_B = criterion_cycle(recov_B, real_B)\n        \n        loss_cycle = (loss_cycle_A + loss_cycle_B)/2\n        \n# ------> Total Loss\n        loss_G = loss_GAN + (10.0*loss_cycle) + (5.0*loss_identity) # multiply suggested weight(default cycle loss weight : 10, default identity loss weight : 5)\n        \n        loss_G.backward()\n        optimizer_G.step()\n        \n# -----------------\n# Train Discriminator A\n# -----------------\n\n        optimizer_D_A.zero_grad()\n    \n        loss_real = criterion_GAN(D_A(real_A), valid) # train to discriminate real images as real\n        loss_fake = criterion_GAN(D_A(fake_A.detach()), fake) # train to discriminate fake images as fake\n        \n        loss_D_A = (loss_real + loss_fake)/2\n        \n        loss_D_A.backward()\n        optimizer_D_A.step()\n\n# -----------------\n# Train Discriminator B\n# -----------------\n        optimizer_D_B.zero_grad()\n    \n        loss_real = criterion_GAN(D_B(real_B), valid) # train to discriminate real images as real\n        loss_fake = criterion_GAN(D_B(fake_B.detach()), fake) # train to discriminate fake images as fake\n        \n        loss_D_B = (loss_real + loss_fake)/2\n        \n        loss_D_B.backward()\n        optimizer_D_B.step()\n        \n# ------> Total Loss\n        loss_D = (loss_D_A + loss_D_B)/2\n    \n# -----------------\n# Show Progress\n# -----------------\n        if (i+1) % 50 == 0:\n            sample_images()\n            print('[Epoch %d/%d] [Batch %d/%d] [D loss : %f] [G loss : %f - (adv : %f, cycle : %f, identity : %f)]'\n                    %(epoch+1,n_epochs,       # [Epoch -]\n                      i+1,len(dataloader),   # [Batch -]\n                      loss_D.item(),       # [D loss -]\n                      loss_G.item(),       # [G loss -]\n                      loss_GAN.item(),     # [adv -]\n                      loss_cycle.item(),   # [cycle -]\n                      loss_identity.item(),# [identity -]\n                     ))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:36:00.318713Z","iopub.execute_input":"2024-12-21T11:36:00.319152Z","iopub.status.idle":"2024-12-21T11:37:16.657591Z","shell.execute_reply.started":"2024-12-21T11:36:00.319109Z","shell.execute_reply":"2024-12-21T11:37:16.655864Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for i, batch in enumerate(dataloader):\n    print('iter : {}  A.size : {}'.format(i,batch['A'].size()))\n    print('iter : {}  B.size : {}'.format(i,batch['B'].size()))\n    if i == 10:\n        break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:37:16.658195Z","iopub.status.idle":"2024-12-21T11:37:16.658583Z","shell.execute_reply":"2024-12-21T11:37:16.658408Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"photo_dir = os.path.join(data_dir, 'photo_jpg')\nfiles = [os.path.join(photo_dir, name) for name in os.listdir(photo_dir)]\nlen(files)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:37:16.65932Z","iopub.status.idle":"2024-12-21T11:37:16.659799Z","shell.execute_reply":"2024-12-21T11:37:16.659609Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"save_dir = '/kaggle/working'\nif not os.path.exists(save_dir):\n    os.makedirs(save_dir)\n    \nfor file in os.listdir(save_dir):\n    os.remove(os.path.join(save_dir, file))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:37:16.660811Z","iopub.status.idle":"2024-12-21T11:37:16.661111Z","shell.execute_reply":"2024-12-21T11:37:16.660992Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"batch_size = 1\n\ngenerate_transforms = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n])\n\nto_image = transforms.ToPILImage()\n\nG_BA.eval()\nfor i in range(0, len(files), batch_size):\n    # read images\n    imgs = []\n    for j in range(i, min(len(files), i + batch_size)):\n        img = Image.open(files[j])\n        img = generate_transforms(img)\n        imgs.append(img)\n    imgs = torch.stack(imgs, 0).type(Tensor)\n    \n    # generate\n    fake_imgs = G_BA(imgs).detach().cpu()\n    \n    # save\n    for j in range(fake_imgs.size(0)):\n        img = fake_imgs[j].squeeze().permute(1, 2, 0)\n        img_arr = img.numpy()\n        img_arr = (img_arr - np.min(img_arr)) * 255 / (np.max(img_arr) - np.min(img_arr))\n        img_arr = img_arr.astype(np.uint8)\n        \n        img = to_image(img_arr)\n        _, name = os.path.split(files[i+j])\n        img.save(os.path.join(save_dir, name))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:37:16.662139Z","iopub.status.idle":"2024-12-21T11:37:16.662638Z","shell.execute_reply":"2024-12-21T11:37:16.662403Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# compress the generated images into a zip file named images.zip\nimport shutil\n\nshutil.make_archive('images', 'zip', save_dir)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:37:16.663462Z","iopub.status.idle":"2024-12-21T11:37:16.663925Z","shell.execute_reply":"2024-12-21T11:37:16.663736Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"shutil.move('images.zip','kaggle/working/images.zip')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-21T11:37:16.664857Z","iopub.status.idle":"2024-12-21T11:37:16.665288Z","shell.execute_reply":"2024-12-21T11:37:16.6651Z"}},"outputs":[],"execution_count":null}]}