{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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 in \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 \"../input/\" directory.\n# For example, running this (by clicking run or pressing Shift+Enter) will list the files in the input directory\n\nimport os\nprint(os.listdir(\"../input\"))\n\n# Any results you write to the current directory are saved as output.\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport matplotlib.image as mpimg\nimport time","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"kernel_start_time = time.perf_counter()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Redefine print to output logs during commit\n__print__ = print\ndef print(string):\n    os.system(f'echo \\\"{string}\\\"')\n    __print__(string)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torch\nfrom torch import nn\nfrom torch import optim\nfrom torch import utils\nfrom tqdm import tqdm\nimport torch.nn.functional as F\nfrom torchvision.utils import save_image\nfrom torchvision import datasets, transforms","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_DIR = '../input/all-dogs/'\nIMG_SIZE = 64\nWORKERS = 8\nBATCH_SIZE = 64\nDEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\nREAL_LABEL = 0.9\nFAKE_LABEL = 0.1\nNZ = 100\nNZ_SHAPE = [100, 1, 1]\nNGF = 64\nNDF = 64\nNC = 3\nLRG = 1e-3\nLRD = 5e-4\nBETAS = (0.5, 0.999)\nEPOCHS = 800\nSHOW_EVERY = 50\nIMGS_TO_DISPLAY = 8\nOUTPUT_DIR = 'output_images_1'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DEVICE","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show_generated_img(netG, noise):\n    sample = []\n    gen_images = netG(noise).to(\"cpu\").clone().detach()\n    for tensor in gen_images:\n        gen_image = tensor.numpy().transpose(1, 2, 0)\n        sample.append(gen_image)\n\n    figure, axes = plt.subplots(1, len(sample), figsize=(64, 64))\n    for index, axis in enumerate(axes):\n        axis.axis('off')\n        image_array = (sample[index] + 1.) / 2.\n        axis.imshow(image_array)\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def pbar_desc(epoch, dloss, gloss):\n    return f'{epoch:04d}/{EPOCHS} | D: {dloss:.3f}  G:{gloss:.3f}'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Conv2dDCGAN(nn.Module):\n    def __init__(self, inf, outf, kernel_size, stride, padding, bias):\n        super().__init__()\n        self.conv = nn.Conv2d(inf, outf, kernel_size, stride, padding, bias=bias)\n        nn.init.normal_(self.conv.weight.data, 0.0, 0.02)\n\n    def forward(self, x):\n        return self.conv(x)\n\n\nclass BatchNorm2dDCGAN(nn.Module):\n    def __init__(self, features):\n        super().__init__()\n        self.bn = nn.BatchNorm2d(features)\n        nn.init.normal_(self.bn.weight.data, 1.0, 0.02)\n        nn.init.constant_(self.bn.bias.data, 0.0)\n\n    def forward(self, x):\n        return self.bn(x)\n    \nclass UpscaleBlockLRelu(nn.Module):\n    def __init__(self, inf, outf, ksz, st, pad, upscale):\n        super().__init__()\n\n        self.conv = Conv2dDCGAN(inf, outf, ksz, st, pad, bias=False)\n        self.bn = BatchNorm2dDCGAN(outf // upscale ** 2)\n        self.ps = nn.PixelShuffle(upscale)\n        self.prelu = nn.LeakyReLU(negative_slope=0.05)\n\n    def forward(self, x):\n        x = self.conv(x)\n        x = self.ps(x)\n        x = self.bn(x)\n        x = self.prelu(x)\n        return x\n    \nclass DownsampleBlock(nn.Module):\n    def __init__(self, inf, outf, ksz, st, pad):\n        super().__init__()\n\n        self.conv = Conv2dDCGAN(inf, outf, ksz, st, pad, bias=False)\n\n        self.bn = BatchNorm2dDCGAN(outf)\n\n    def forward(self, x):\n        x = self.conv(x)\n        x = self.bn(x)\n        x = F.leaky_relu(x, 0.2, inplace=True)\n\n        return x","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, nz, ngf, nc, block_cls):\n        super().__init__()\n\n        self.b1 = block_cls(nz, ngf * 8 * 16, 1, 1, 0, 4)  # Upscale by 4\n        self.b2 = block_cls(ngf * 8, ngf * 4 * 4, 3, 1, 1, 2) # Upscale by 2\n        self.b3 = block_cls(ngf * 4, ngf * 2 * 4, 3, 1, 1, 2) # Upscale by 2\n        self.b4 = block_cls(ngf * 2, ngf * 4, 3, 1, 1, 2)  # Upscale by 2\n        self.b5 = block_cls(ngf, ngf * 4, 3, 1, 1, 2) # Upscale by 2\n\n        self.conv = Conv2dDCGAN(ngf, nc, 3, 1, 1, bias=False)\n\n    def forward(self, x):\n        x = self.b1(x)   # (ngf x 8) x 4 x 4\n        x = self.b2(x)   # (ngf x 4) x 8 X 8\n        x = self.b3(x)   # (ngf x 2) x 16 x 16\n        x = self.b4(x)   # ngf x 32 X 32\n        x = self.b5(x)   # ngf X 64 x 64\n        x = self.conv(x)\n        return torch.tanh(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self, nc, ndf, sigmoid=True):\n        super().__init__()\n\n        self.start_conv = Conv2dDCGAN(nc, ndf, 4, 2, 1, bias=False)\n\n        self.b1 = DownsampleBlock(ndf, ndf * 2, 3, 2, 1)\n        self.b2 = DownsampleBlock(ndf * 2, ndf * 4, 3, 2, 1)\n        self.b3 = DownsampleBlock(ndf * 4, ndf * 8, 3, 2, 1)\n\n        self.end_conv = Conv2dDCGAN(ndf * 8, 1, 4, 1, 0, bias=False)\n        self.sigmoid = sigmoid\n\n    def forward(self, x):\n        x = self.start_conv(x)  # ndf x 32 x 32\n        x = F.leaky_relu(x, 0.2, inplace=True)\n        x = self.b1(x)    # (ndf x 2) x 16 x 16\n        x = self.b2(x)    # (ndf x 4) x 8 x 8\n        x = self.b3(x)    # (ndf x 8) x 4 x 4\n        x = self.end_conv(x)  # 1 x 1 x 1\n        x = x.view(x.size(0))\n\n        if not self.sigmoid:\n            return x\n        return torch.sigmoid(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ds = datasets.ImageFolder(root=DATA_DIR,\n                            transform=transforms.Compose([\n                                transforms.Resize(IMG_SIZE),\n                                transforms.CenterCrop(IMG_SIZE),\n                                transforms.ToTensor(),\n                                transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])\n                                ])\n                            )\n\ndl = utils.data.DataLoader(ds, batch_size=BATCH_SIZE, shuffle=True, num_workers=WORKERS)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"G = Generator(NZ, NGF, NC, UpscaleBlockLRelu)\nD = Discriminator(NC, NDF, sigmoid=False)\n\nG.to(DEVICE)\nD.to(DEVICE)\n\noptG = optim.Adam(G.parameters(), lr=LRG, betas=BETAS)\noptD = optim.Adam(D.parameters(), lr=LRD, betas=BETAS)\n\n# criterion = nn.BCELoss().to(DEVICE)\nstart_epoch = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fixed_noise = torch.randn(*([IMGS_TO_DISPLAY] + NZ_SHAPE)).to(DEVICE)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for epoch in range(start_epoch, EPOCHS + 1):\n    \n    if time.perf_counter() - kernel_start_time > 32000:\n            print(\"Time limit reached! Stopping kernel!\")\n            break\n            \n    # pbar = tqdm(dl, desc=pbar_desc(epoch, 0.0, 0.0))\n    print(f'Epoch {epoch}')\n    losses = []\n    for batch, _ in dl:\n\n        batch = batch.to(DEVICE)\n        optD.zero_grad()\n\n        # Train the discriminator\n        for param in D.parameters():\n            param.requires_grad = True\n\n        # Train on real images\n        num_images = batch.size(0)\n        rlabels = torch.full((num_images,), REAL_LABEL).to(DEVICE)\n        real_d_predictions = D(batch)\n        # d_real_loss = criterion(real_d_predictions, rlabels)\n\n        # Train on fake images\n        z = torch.randn(*([num_images] + NZ_SHAPE)).to(DEVICE)\n        fake = G(z).detach()\n        # flabels = torch.full((num_images,), FAKE_LABEL).to(DEVICE)\n        fake_d_predictions = D(fake)\n        # d_fake_loss = criterion(fake_d_predictions, flabels)\n\n        d_loss = (torch.mean((real_d_predictions - torch.mean(fake_d_predictions) - rlabels) ** 2) +\n                  torch.mean((fake_d_predictions - torch.mean(real_d_predictions) + rlabels) ** 2))/2\n        d_loss.backward(retain_graph=True)\n\n        optD.step()\n\n        losses.append(d_loss.item())\n\n        # Train the generator\n        for param in D.parameters():\n            param.requires_grad = False\n\n        optG.zero_grad()\n\n        rlabels = torch.full((num_images,), REAL_LABEL).to(DEVICE)\n        z = torch.randn(*([num_images] + NZ_SHAPE)).to(DEVICE)\n        fake = G(z)\n        predictions = D(fake)\n        g_loss = (torch.mean((real_d_predictions - torch.mean(predictions) + rlabels) ** 2) +\n                  torch.mean((predictions - torch.mean(real_d_predictions) - rlabels) ** 2))/2\n        g_loss.backward()\n        optG.step()\n        # pbar.set_description(pbar_desc(epoch, d_loss.item(), g_loss.item()))\n\n    # Display generated images \n\n#     if epoch % SHOW_EVERY == 0 or epoch == 1:\n#         show_generated_img(G, fixed_noise)","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"import shutil\nif os.path.exists(f'../{OUTPUT_DIR}'):\n    shutil.rmtree(f'../{OUTPUT_DIR}')\nos.mkdir(f'../{OUTPUT_DIR}')\nim_batch_size = 50\nn_images=10000\nprint(f'Generating {n_images} images')\nfor i_batch in tqdm(range(0, n_images, im_batch_size)):\n    gen_z = torch.randn(*([im_batch_size] + NZ_SHAPE)).to(DEVICE)\n    gen_images = G(gen_z)\n    images = gen_images.to(\"cpu\").clone().detach()\n    images = images.numpy().transpose(0, 2, 3, 1)\n    for i_image in range(gen_images.size(0)):\n        save_image(gen_images[i_image, :, :, :], os.path.join(f'../{OUTPUT_DIR}', f'image_{i_batch+i_image:05d}.png'))\n\n\nshutil.make_archive('images', 'zip', f'../{OUTPUT_DIR}')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}