{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"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    print(dirname)\n    for filename in filenames:\n#         print(os.path.join(dirname, filename))\n        pass\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":"2021-08-29T19:52:49.707947Z","iopub.execute_input":"2021-08-29T19:52:49.708316Z","iopub.status.idle":"2021-08-29T19:52:49.741254Z","shell.execute_reply.started":"2021-08-29T19:52:49.708287Z","shell.execute_reply":"2021-08-29T19:52:49.740505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torchvision\nfrom torch.utils.data import Dataset, DataLoader","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:20.515500Z","iopub.execute_input":"2021-08-29T20:06:20.516015Z","iopub.status.idle":"2021-08-29T20:06:20.519939Z","shell.execute_reply.started":"2021-08-29T20:06:20.515982Z","shell.execute_reply":"2021-08-29T20:06:20.518761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from glob import glob\nfrom dataclasses import dataclass\nimport PIL\nfrom torchvision import transforms\n\n@dataclass\nclass ImageDataset(Dataset):\n    \n    dirname: str\n        \n    def __post_init__(self):\n        self.filenames = glob(f'{self.dirname}/*.jpg')\n        self.transform = transforms.Compose([\n            transforms.ToTensor(),\n            transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n        ])\n        \n    def __len__(self):\n        return len(self.filenames)\n    \n    def __getitem__(self, idx):\n        filename = self.filenames[idx]\n        img = PIL.Image.open(filename)\n        return self.transform(img)\n    \n    ","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:21.245697Z","iopub.execute_input":"2021-08-29T20:06:21.246248Z","iopub.status.idle":"2021-08-29T20:06:21.254481Z","shell.execute_reply.started":"2021-08-29T20:06:21.246213Z","shell.execute_reply":"2021-08-29T20:06:21.253523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"monet_dataset = ImageDataset(dirname='/kaggle/input/gan-getting-started/monet_jpg')\nphoto_dataset = ImageDataset(dirname='/kaggle/input/gan-getting-started/photo_jpg')","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:21.923134Z","iopub.execute_input":"2021-08-29T20:06:21.923489Z","iopub.status.idle":"2021-08-29T20:06:21.960276Z","shell.execute_reply.started":"2021-08-29T20:06:21.923458Z","shell.execute_reply":"2021-08-29T20:06:21.959407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(monet_dataset), len(photo_dataset)","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:22.314898Z","iopub.execute_input":"2021-08-29T20:06:22.315248Z","iopub.status.idle":"2021-08-29T20:06:22.320536Z","shell.execute_reply.started":"2021-08-29T20:06:22.315220Z","shell.execute_reply":"2021-08-29T20:06:22.319889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\n\nOUTPUT_CHANNELS = 3\n\n@dataclass(eq=False)\nclass Downsample(nn.Module):\n    in_channels: int\n    filters: int\n    size: int\n    apply_instance_norm: bool = True\n        \n        \n    def __post_init__(self):\n        nn.Module.__init__(self)\n        layers = []\n        layers.append(nn.Conv2d(\n            in_channels=self.in_channels,\n            kernel_size=self.size,\n            out_channels=self.filters,\n            stride=2,\n            padding=1,\n            bias=False\n        ))\n        if self.apply_instance_norm:\n            layers.append(nn.InstanceNorm2d(\n                num_features=3\n            ))\n        layers.append(nn.LeakyReLU())\n        self.network = nn.Sequential(*layers)\n    \n    def forward(self, inp):\n        return self.network(inp)\n        \n        \n@dataclass(eq=False)\nclass Upsample(nn.Module):\n    in_channels: int\n    filters: int\n    size: int\n    apply_dropout: bool = False\n        \n        \n    def __post_init__(self):\n        nn.Module.__init__(self)\n        layers = []\n        layers.append(nn.ConvTranspose2d(\n            in_channels=self.in_channels,\n            kernel_size=self.size,\n            out_channels=self.filters,\n            stride=2,\n            padding=1,\n            bias=False\n        ))\n        if self.apply_dropout:\n            layers.append(nn.Dropout(\n                p=0.5\n            ))\n        layers.append(nn.ReLU())\n        self.network = nn.Sequential(*layers)\n    \n    def forward(self, inp):\n        return self.network(inp)\n        \n    ","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:22.642625Z","iopub.execute_input":"2021-08-29T20:06:22.643016Z","iopub.status.idle":"2021-08-29T20:06:22.655854Z","shell.execute_reply.started":"2021-08-29T20:06:22.642983Z","shell.execute_reply":"2021-08-29T20:06:22.655090Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@dataclass(eq=False)\nclass Generator(nn.Module):\n    \n    def __init__(self):\n        nn.Module.__init__(self)\n        self.down_stack = nn.ModuleList([\n            Downsample(3, 64, 4, apply_instance_norm=False), # (bs, 128, 128, 64)\n            Downsample(64, 128, 4), # (bs, 64, 64, 128)\n            Downsample(128, 256, 4), # (bs, 32, 32, 256)\n            Downsample(256, 512, 4), # (bs, 16, 16, 512)\n            Downsample(512, 512, 4), # (bs, 8, 8, 512)\n            Downsample(512, 512, 4), # (bs, 4, 4, 512)\n            Downsample(512, 512, 4), # (bs, 2, 2, 512)\n            Downsample(512, 512, 4, apply_instance_norm=False), # (bs, 1, 1, 512)\n        ])\n        \n        self.up_stack = [\n            Upsample(512, 512, 4, apply_dropout=True), # (bs, 2, 2, 1024)\n            Upsample(1024, 512, 4, apply_dropout=True), # (bs, 4, 4, 1024)\n            Upsample(1024, 512, 4, apply_dropout=True), # (bs, 8, 8, 1024)\n            Upsample(1024, 512, 4), # (bs, 16, 16, 1024)\n            Upsample(1024, 256, 4), # (bs, 32, 32, 512)\n            Upsample(512, 128, 4), # (bs, 64, 64, 256)\n            Upsample(256, 64, 4), # (bs, 128, 128, 128)\n        ]\n        \n        self.last = nn.ConvTranspose2d(\n            in_channels=128,\n            kernel_size=4,\n            out_channels=3,\n            stride=2,\n            padding=1,\n            bias=False\n        )\n        self.output_activation = nn.Tanh()\n    \n    def forward(self, x):\n        skips = []\n        for layer in self.down_stack:\n            x = layer(x)\n            skips.append(x)\n        skips = reversed(skips[:-1])\n        for layer, skip in zip(self.up_stack, skips):\n            x = layer(x)\n            x = torch.cat([x, skip], axis=1)\n        x = self.last(x)\n        x = self.output_activation(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:23.038709Z","iopub.execute_input":"2021-08-29T20:06:23.039104Z","iopub.status.idle":"2021-08-29T20:06:23.051623Z","shell.execute_reply.started":"2021-08-29T20:06:23.039068Z","shell.execute_reply":"2021-08-29T20:06:23.050756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"generator = Generator()\n\nout = generator(monet_dataset[0].unsqueeze(0))","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:23.479390Z","iopub.execute_input":"2021-08-29T20:06:23.479922Z","iopub.status.idle":"2021-08-29T20:06:24.184842Z","shell.execute_reply.started":"2021-08-29T20:06:23.479888Z","shell.execute_reply":"2021-08-29T20:06:24.184022Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"out.shape","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:24.186030Z","iopub.execute_input":"2021-08-29T20:06:24.186463Z","iopub.status.idle":"2021-08-29T20:06:24.191337Z","shell.execute_reply.started":"2021-08-29T20:06:24.186434Z","shell.execute_reply":"2021-08-29T20:06:24.190695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@dataclass(eq=False)\nclass Discriminator(nn.Module):\n    \n    def __post_init__(self):\n        nn.Module.__init__(self)\n        self.down_stack = nn.ModuleList([\n            Downsample(3, 64, 4, apply_instance_norm=False),\n            Downsample(64, 128, 4),\n            Downsample(128, 256, 4),\n        ])\n        \n        self.conv1 = nn.Conv2d(\n            in_channels=256,\n            kernel_size=4,\n            out_channels=512,\n            stride=1,\n            padding=1,\n            bias=False\n        )\n        self.norm = nn.InstanceNorm2d(\n            num_features=3\n        )\n        self.activation = nn.LeakyReLU()\n        \n        self.conv2 = nn.Conv2d(\n            in_channels=512,\n            kernel_size=4,\n            out_channels=1,\n            stride=1,\n            padding=1\n        )\n        \n    def forward(self, x):\n        for layer in self.down_stack:\n            x = layer(x)\n        x = self.conv1(x)\n        x = self.norm(x)\n        x = self.activation(x)\n        x = self.conv2(x)\n        return x\n        ","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:13:42.313299Z","iopub.execute_input":"2021-08-29T20:13:42.313698Z","iopub.status.idle":"2021-08-29T20:13:42.323388Z","shell.execute_reply.started":"2021-08-29T20:13:42.313669Z","shell.execute_reply":"2021-08-29T20:13:42.322516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"disc = Discriminator()\n\ndisc(monet_dataset[0].unsqueeze(0)).shape","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:13:42.739403Z","iopub.execute_input":"2021-08-29T20:13:42.739771Z","iopub.status.idle":"2021-08-29T20:13:42.838314Z","shell.execute_reply.started":"2021-08-29T20:13:42.739741Z","shell.execute_reply":"2021-08-29T20:13:42.837423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from matplotlib.pyplot import imshow\n\ndef show_image(img_tensor):\n    imshow(img_tensor.permute(1, 2, 0))","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:25.240678Z","iopub.execute_input":"2021-08-29T20:06:25.241315Z","iopub.status.idle":"2021-08-29T20:06:25.245582Z","shell.execute_reply.started":"2021-08-29T20:06:25.241277Z","shell.execute_reply":"2021-08-29T20:06:25.244670Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_image(monet_dataset[99])","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:25.692768Z","iopub.execute_input":"2021-08-29T20:06:25.693363Z","iopub.status.idle":"2021-08-29T20:06:25.885392Z","shell.execute_reply.started":"2021-08-29T20:06:25.693327Z","shell.execute_reply":"2021-08-29T20:06:25.884646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pytorch_lightning as pl","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:06:25.975997Z","iopub.execute_input":"2021-08-29T20:06:25.976769Z","iopub.status.idle":"2021-08-29T20:06:25.981593Z","shell.execute_reply.started":"2021-08-29T20:06:25.976720Z","shell.execute_reply":"2021-08-29T20:06:25.980235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import IterableDataset\nfrom random import randint\nimport torch.optim as optim\nimport itertools\n\nclass CycleGANDataset(Dataset):\n    \n    def __init__(self, monet_dataset, photo_dataset):\n        self.monet_dataset = monet_dataset\n        self.photo_dataset = photo_dataset\n    \n    def __getitem__(self, idx):\n        monet = self.monet_dataset[idx]\n        random_photo_idx = randint(0, len(self.photo_dataset))\n        photo = self.photo_dataset[random_photo_idx]\n        return monet, photo\n        \n    def __len__(self):\n        return len(self.monet_dataset)\n    \n\nclass CycleGAN(pl.LightningModule):\n    \n    def __init__(self, lambda_cycle=10):\n        super().__init__()\n        self.save_hyperparameters()\n        self.m_gen = Generator()\n        self.p_gen = Generator()\n        self.m_disc = Discriminator()\n        self.p_disc = Discriminator()\n        self.lambda_cycle = lambda_cycle\n        \n    def training_step(self, batch, batch_idx, optimizer_idx):\n        real_monet, real_photo = batch\n        \n        # photo to monet back to photo\n        fake_monet = self.m_gen(real_photo)\n        cycled_photo = self.p_gen(fake_monet)\n\n        # monet to photo back to monet\n        fake_photo = self.p_gen(real_monet)\n        cycled_monet = self.m_gen(fake_photo)\n\n        # generating itself\n        same_monet = self.m_gen(real_monet)\n        same_photo = self.p_gen(real_photo)\n\n        # discriminator used to check, inputing real images\n        disc_real_monet = self.m_disc(real_monet)\n        disc_real_photo = self.p_disc(real_photo)\n\n        # discriminator used to check, inputing fake images\n        disc_fake_monet = self.m_disc(fake_monet)\n\n    \n    def configure_optimizers(self):\n        return [\n            optim.AdamW(\n                itertools.chain(*[\n                    self.m_gen.parameters(),\n                    self.p_gen.parameters(),\n                ]),\n                lr=1e-4\n            ),\n            optim.AdamW(\n                itertools.chain(*[\n                    self.m_disc.parameters(),\n                    self.p_disc.parameters()\n                ]),\n                lr=1e-4\n            )\n        ]\n    \n    def train_dataloader(self):\n        return DataLoader(CycleGANDataset(monet_dataset, photo_dataset), shuffle=True)","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:13:14.459685Z","iopub.execute_input":"2021-08-29T20:13:14.460057Z","iopub.status.idle":"2021-08-29T20:13:14.474617Z","shell.execute_reply.started":"2021-08-29T20:13:14.460028Z","shell.execute_reply":"2021-08-29T20:13:14.473573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer = pl.Trainer(fast_dev_run=True)","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:13:15.190636Z","iopub.execute_input":"2021-08-29T20:13:15.191037Z","iopub.status.idle":"2021-08-29T20:13:15.198702Z","shell.execute_reply.started":"2021-08-29T20:13:15.191010Z","shell.execute_reply":"2021-08-29T20:13:15.197803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"module = CycleGAN()\ntrainer.fit(module)","metadata":{"execution":{"iopub.status.busy":"2021-08-29T20:13:15.457048Z","iopub.execute_input":"2021-08-29T20:13:15.457717Z","iopub.status.idle":"2021-08-29T20:13:19.332631Z","shell.execute_reply.started":"2021-08-29T20:13:15.457678Z","shell.execute_reply":"2021-08-29T20:13:19.331597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}