{"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":30683,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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","execution":{"iopub.status.busy":"2024-04-18T20:56:27.734166Z","iopub.execute_input":"2024-04-18T20:56:27.734550Z","iopub.status.idle":"2024-04-18T20:56:29.632994Z","shell.execute_reply.started":"2024-04-18T20:56:27.734521Z","shell.execute_reply":"2024-04-18T20:56:29.632075Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.634529Z","iopub.execute_input":"2024-04-18T20:56:29.634818Z","iopub.status.idle":"2024-04-18T20:56:29.640067Z","shell.execute_reply.started":"2024-04-18T20:56:29.634795Z","shell.execute_reply":"2024-04-18T20:56:29.639200Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.641270Z","iopub.execute_input":"2024-04-18T20:56:29.641700Z","iopub.status.idle":"2024-04-18T20:56:29.681070Z","shell.execute_reply.started":"2024-04-18T20:56:29.641670Z","shell.execute_reply":"2024-04-18T20:56:29.680310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.683087Z","iopub.execute_input":"2024-04-18T20:56:29.683351Z","iopub.status.idle":"2024-04-18T20:56:29.693920Z","shell.execute_reply.started":"2024-04-18T20:56:29.683330Z","shell.execute_reply":"2024-04-18T20:56:29.693004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.694914Z","iopub.execute_input":"2024-04-18T20:56:29.695194Z","iopub.status.idle":"2024-04-18T20:56:29.701645Z","shell.execute_reply.started":"2024-04-18T20:56:29.695172Z","shell.execute_reply":"2024-04-18T20:56:29.700788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.702852Z","iopub.execute_input":"2024-04-18T20:56:29.703665Z","iopub.status.idle":"2024-04-18T20:56:29.714262Z","shell.execute_reply.started":"2024-04-18T20:56:29.703639Z","shell.execute_reply":"2024-04-18T20:56:29.713459Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.715356Z","iopub.execute_input":"2024-04-18T20:56:29.715661Z","iopub.status.idle":"2024-04-18T20:56:29.779025Z","shell.execute_reply.started":"2024-04-18T20:56:29.715638Z","shell.execute_reply":"2024-04-18T20:56:29.778317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.779934Z","iopub.execute_input":"2024-04-18T20:56:29.780162Z","iopub.status.idle":"2024-04-18T20:56:29.786141Z","shell.execute_reply.started":"2024-04-18T20:56:29.780141Z","shell.execute_reply":"2024-04-18T20:56:29.785273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.787263Z","iopub.execute_input":"2024-04-18T20:56:29.787595Z","iopub.status.idle":"2024-04-18T20:56:29.799811Z","shell.execute_reply.started":"2024-04-18T20:56:29.787566Z","shell.execute_reply":"2024-04-18T20:56:29.798943Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.805362Z","iopub.execute_input":"2024-04-18T20:56:29.806140Z","iopub.status.idle":"2024-04-18T20:56:29.815866Z","shell.execute_reply.started":"2024-04-18T20:56:29.806102Z","shell.execute_reply":"2024-04-18T20:56:29.814952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.816897Z","iopub.execute_input":"2024-04-18T20:56:29.817156Z","iopub.status.idle":"2024-04-18T20:56:29.828916Z","shell.execute_reply.started":"2024-04-18T20:56:29.817134Z","shell.execute_reply":"2024-04-18T20:56:29.828152Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion_GAN = torch.nn.MSELoss()\ncriterion_cycle = torch.nn.L1Loss()\ncriterion_identity = torch.nn.L1Loss()","metadata":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.830006Z","iopub.execute_input":"2024-04-18T20:56:29.830654Z","iopub.status.idle":"2024-04-18T20:56:29.841203Z","shell.execute_reply.started":"2024-04-18T20:56:29.830621Z","shell.execute_reply":"2024-04-18T20:56:29.840464Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:29.842281Z","iopub.execute_input":"2024-04-18T20:56:29.842626Z","iopub.status.idle":"2024-04-18T20:56:30.135481Z","shell.execute_reply.started":"2024-04-18T20:56:29.842598Z","shell.execute_reply":"2024-04-18T20:56:30.134678Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.136869Z","iopub.execute_input":"2024-04-18T20:56:30.137204Z","iopub.status.idle":"2024-04-18T20:56:30.178808Z","shell.execute_reply.started":"2024-04-18T20:56:30.137173Z","shell.execute_reply":"2024-04-18T20:56:30.178030Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.179737Z","iopub.execute_input":"2024-04-18T20:56:30.179990Z","iopub.status.idle":"2024-04-18T20:56:30.186302Z","shell.execute_reply.started":"2024-04-18T20:56:30.179967Z","shell.execute_reply":"2024-04-18T20:56:30.185400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.187369Z","iopub.execute_input":"2024-04-18T20:56:30.187652Z","iopub.status.idle":"2024-04-18T20:56:30.207395Z","shell.execute_reply.started":"2024-04-18T20:56:30.187631Z","shell.execute_reply":"2024-04-18T20:56:30.206339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.208502Z","iopub.execute_input":"2024-04-18T20:56:30.209035Z","iopub.status.idle":"2024-04-18T20:56:30.216795Z","shell.execute_reply.started":"2024-04-18T20:56:30.209005Z","shell.execute_reply":"2024-04-18T20:56:30.215842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.217865Z","iopub.execute_input":"2024-04-18T20:56:30.218159Z","iopub.status.idle":"2024-04-18T20:56:30.226116Z","shell.execute_reply.started":"2024-04-18T20:56:30.218137Z","shell.execute_reply":"2024-04-18T20:56:30.225260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.227144Z","iopub.execute_input":"2024-04-18T20:56:30.227479Z","iopub.status.idle":"2024-04-18T20:56:30.235909Z","shell.execute_reply.started":"2024-04-18T20:56:30.227448Z","shell.execute_reply":"2024-04-18T20:56:30.235157Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.237007Z","iopub.execute_input":"2024-04-18T20:56:30.237349Z","iopub.status.idle":"2024-04-18T20:56:30.245946Z","shell.execute_reply.started":"2024-04-18T20:56:30.237318Z","shell.execute_reply":"2024-04-18T20:56:30.244885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"temp_imgs = next(iter(val_dataloader))","metadata":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.246994Z","iopub.execute_input":"2024-04-18T20:56:30.247253Z","iopub.status.idle":"2024-04-18T20:56:30.336675Z","shell.execute_reply.started":"2024-04-18T20:56:30.247232Z","shell.execute_reply":"2024-04-18T20:56:30.335728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.337773Z","iopub.execute_input":"2024-04-18T20:56:30.338037Z","iopub.status.idle":"2024-04-18T20:56:30.344896Z","shell.execute_reply.started":"2024-04-18T20:56:30.338014Z","shell.execute_reply":"2024-04-18T20:56:30.343957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.345979Z","iopub.execute_input":"2024-04-18T20:56:30.346232Z","iopub.status.idle":"2024-04-18T20:56:30.437151Z","shell.execute_reply.started":"2024-04-18T20:56:30.346211Z","shell.execute_reply":"2024-04-18T20:56:30.436268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.438312Z","iopub.execute_input":"2024-04-18T20:56:30.438674Z","iopub.status.idle":"2024-04-18T20:56:30.508521Z","shell.execute_reply.started":"2024-04-18T20:56:30.438642Z","shell.execute_reply":"2024-04-18T20:56:30.507771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.imshow(temp_real_A.cpu().permute(1,2,0))\nplt.title('Real A')\nplt.axis('off')","metadata":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.509720Z","iopub.execute_input":"2024-04-18T20:56:30.510351Z","iopub.status.idle":"2024-04-18T20:56:30.693653Z","shell.execute_reply.started":"2024-04-18T20:56:30.510318Z","shell.execute_reply":"2024-04-18T20:56:30.692720Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.694815Z","iopub.execute_input":"2024-04-18T20:56:30.695108Z","iopub.status.idle":"2024-04-18T20:56:30.700760Z","shell.execute_reply.started":"2024-04-18T20:56:30.695077Z","shell.execute_reply":"2024-04-18T20:56:30.699877Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:30.701845Z","iopub.execute_input":"2024-04-18T20:56:30.702186Z","iopub.status.idle":"2024-04-18T20:56:31.293688Z","shell.execute_reply.started":"2024-04-18T20:56:30.702163Z","shell.execute_reply":"2024-04-18T20:56:31.292725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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        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":{"execution":{"iopub.status.busy":"2024-04-18T20:56:31.299044Z","iopub.execute_input":"2024-04-18T20:56:31.299358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"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_count":null,"outputs":[]},{"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)\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"shutil.move('images.zip','kaggle/working/images.zip')","metadata":{},"execution_count":null,"outputs":[]}]}