{"cells":[{"metadata":{},"cell_type":"markdown","source":"# GAN Dogs Starter Fork With 256x256 Images\"\n\nThis notebook is modified from the notebook 'GAN dogs starter' by Wendy Kan. (https://www.kaggle.com/wendykan/gan-dogs-starter)\n\nThis version changes the image size from 64x64 to 256x256. We also increase the number of epochs to hopefully improve the quality of the images generated.\n\nTo increase the image size we have to modify the structure of our networks by adding more layers of convolution."},{"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\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# Any results you write to the current directory are saved as output.","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np\nimport torch\nfrom torch import nn, optim\nimport torch.nn.functional as F\nfrom torchvision import datasets, transforms\nfrom torchvision.utils import save_image\nimport os\nimport zipfile\n\n\n\n\nbatch_size = 32\n\n# 256*256 images!\ntransform = transforms.Compose([transforms.Resize(256),\n                                transforms.CenterCrop(256),\n                                transforms.ToTensor(),\n                                transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])\nimport zipfile\npath_to_zip_file = \"/kaggle/input/all-dogs.zip\"\ndirectory_to_extract_to = \"./sample_data/all-dogs\"\n\nwith zipfile.ZipFile(path_to_zip_file, 'r') as zip_ref:\n    zip_ref.extractall(directory_to_extract_to)\n\ntrain_data = datasets.ImageFolder(\"./sample_data/all-dogs\", transform=transform)\ntrain_loader = torch.utils.data.DataLoader(train_data, shuffle=True,\n                                           batch_size=batch_size)\n                                           \nimgs, label = next(iter(train_loader))\nimgs = imgs.numpy().transpose(0, 2, 3, 1)\n\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, nz, nfeats, nchannels):\n        super(Generator, self).__init__()\n\n        # input is Z, going into a convolution\n        self.conv1 = nn.ConvTranspose2d(nz, nfeats * 32, 4, 1, 0, bias=False)\n        self.bn1 = nn.BatchNorm2d(nfeats * 32)\n        # state size. (nfeats*8) x 4 x 4\n        \n        self.conv2 = nn.ConvTranspose2d(nfeats * 32, nfeats * 16, 4, 2, 1, bias=False)\n        self.bn2 = nn.BatchNorm2d(nfeats * 16)\n        # state size. (nfeats*8) x 8 x 8\n        \n        self.conv3 = nn.ConvTranspose2d(nfeats * 16, nfeats * 8, 4, 2, 1, bias=False)\n        self.bn3 = nn.BatchNorm2d(nfeats * 8)\n        # state size. (nfeats*4) x 16 x 16\n        \n        self.conv4 = nn.ConvTranspose2d(nfeats * 8, nfeats * 4, 4, 2, 1, bias=False)\n        self.bn4 = nn.BatchNorm2d(nfeats * 4)\n        # state size. (nfeats * 4) x 32 x 32\n        \n        self.conv5 = nn.ConvTranspose2d(nfeats * 4, nfeats * 2, 4, 2, 1, bias=False)\n        self.bn5 = nn.BatchNorm2d(nfeats * 2)\n        # state size. (nfeats) x 64 x 64\n        \n        self.conv6 = nn.ConvTranspose2d(nfeats * 2, nfeats, 4, 2, 1, bias=False)\n        self.bn6 = nn.BatchNorm2d(nfeats)\n        # state size. (nfeats) x 128 x 128\n        \n        self.conv7 = nn.ConvTranspose2d(nfeats, nfeats, 4, 2, 1, bias=False)\n        self.bn7 = nn.BatchNorm2d(nfeats)\n        # state size. (nfeats) x 256 x 256\n        \n        self.conv8 = nn.ConvTranspose2d(nfeats, nchannels, 3, 1, 1, bias=False)\n        # state size. (nchannels) x 256 x 256\n\n    def forward(self, x):\n        x = F.leaky_relu(self.bn1(self.conv1(x)))\n        x = F.leaky_relu(self.bn2(self.conv2(x)))\n        x = F.leaky_relu(self.bn3(self.conv3(x)))\n        x = F.leaky_relu(self.bn4(self.conv4(x)))\n        x = F.leaky_relu(self.bn5(self.conv5(x)))\n        x = F.leaky_relu(self.bn6(self.conv6(x)))\n        x = F.leaky_relu(self.bn7(self.conv7(x)))\n        x = torch.tanh(self.conv8(x))\n        \n        return x\n\n\n\nclass Discriminator(nn.Module):\n    def __init__(self, nchannels, nfeats):\n        super(Discriminator, self).__init__()\n\n        # input is (nchannels) x 256 x 256\n        self.conv1 = nn.Conv2d(nchannels, nfeats, 4, 2, 1, bias=False)\n        # state size. (nfeats) x 128 x 128\n        \n        self.conv2 = nn.Conv2d(nfeats, nfeats * 2, 4, 2, 1, bias=False)\n        self.bn2 = nn.BatchNorm2d(nfeats * 2)\n        # state size. (nfeats*2) x 64 x 64\n        \n        self.conv3 = nn.Conv2d(nfeats * 2, nfeats * 4, 4, 2, 1, bias=False)\n        self.bn3 = nn.BatchNorm2d(nfeats * 4)\n        # state size. (nfeats*2) x 32 x 32\n        \n        self.conv4 = nn.Conv2d(nfeats * 4, nfeats * 8, 4, 2, 1, bias=False)\n        self.bn4 = nn.BatchNorm2d(nfeats * 8)\n        # state size. (nfeats*2) x 16 x 16\n        \n        self.conv5 = nn.Conv2d(nfeats * 8, nfeats * 16, 4, 2, 1, bias=False)\n        self.bn5 = nn.BatchNorm2d(nfeats * 16)\n        # state size. (nfeats*4) x 8 x 8\n       \n        self.conv6 = nn.Conv2d(nfeats * 16, nfeats * 32, 4, 2, 1, bias=False)\n        self.bn6 = nn.BatchNorm2d(nfeats * 32)\n        # state size. (nfeats*8) x 4 x 4\n        \n        self.conv7 = nn.Conv2d(nfeats * 32, 1, 4, 1, 0, bias=False)\n        # state size. 1 x 1 x 1\n        \n    def forward(self, x):\n        x = F.leaky_relu(self.conv1(x), 0.2)\n        x = F.leaky_relu(self.bn2(self.conv2(x)), 0.2)\n        x = F.leaky_relu(self.bn3(self.conv3(x)), 0.2)\n        x = F.leaky_relu(self.bn4(self.conv4(x)), 0.2)\n        x = F.leaky_relu(self.bn5(self.conv5(x)), 0.2)\n        x = F.leaky_relu(self.bn6(self.conv6(x)), 0.2)\n        x = torch.sigmoid(self.conv7(x))\n        \n        return x.view(-1, 1)\n\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nlr = 0.0003\nbeta1 = 0.5\n\nnetG = Generator(100, 32, 3).to(device)\nnetD = Discriminator(3, 48).to(device)\n\ncriterion = nn.BCELoss()\n\noptimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999))\noptimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999))\n\nnz = 100\nfixed_noise = torch.randn(25, nz, 1, 1, device=device)\n\nreal_label = 0.9\nfake_label = 0\nbatch_size = train_loader.batch_size\n\n\n\n### training here\n\nepochs = 50\n\nstep = 0\nfor epoch in range(epochs):\n    for ii, (real_images, train_labels) in enumerate(train_loader):\n        ############################\n        # (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))\n        ###########################\n        # train with real\n        netD.zero_grad()\n        real_images = real_images.to(device)\n        batch_size = real_images.size(0)\n        labels = torch.full((batch_size, 1), real_label, device=device)\n\n        output = netD(real_images)\n        errD_real = criterion(output, labels)\n        errD_real.backward()\n        D_x = output.mean().item()\n\n        # train with fake\n        noise = torch.randn(batch_size, nz, 1, 1, device=device)\n        fake = netG(noise)\n        labels.fill_(fake_label)\n        output = netD(fake.detach())\n        errD_fake = criterion(output, labels)\n        errD_fake.backward()\n        D_G_z1 = output.mean().item()\n        errD = errD_real + errD_fake\n        optimizerD.step()\n\n        ############################\n        # (2) Update G network: maximize log(D(G(z)))\n        ###########################\n        netG.zero_grad()\n        labels.fill_(real_label)  # fake labels are real for generator cost\n        output = netD(fake)\n        errG = criterion(output, labels)\n        errG.backward()\n        D_G_z2 = output.mean().item()\n        optimizerG.step()\n        \n        if step % 500 == 0:\n            print('[%d/%d][%d/%d] Loss_D: %.4f Loss_G: %.4f D(x): %.4f D(G(z)): %.4f / %.4f'\n                  % (epoch + 1, epochs, ii, len(train_loader),\n                     errD.item(), errG.item(), D_x, D_G_z1, D_G_z2))\n            \n            valid_image = netG(fixed_noise)\n        step += 1\n        \n        \n# torch.save(netG.state_dict(), 'generator.pth')\n# torch.save(netD.state_dict(), 'discriminator.pth')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not os.path.exists('./output_images'):\n    os.mkdir('./output_images')\nim_batch_size = 50\nn_images=1000\nfor i_batch in range(0, n_images, im_batch_size):\n    gen_z = torch.randn(im_batch_size, 100, 1, 1, device=device)\n    gen_images = netG(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('./output_images', f'image_{i_batch+i_image:05d}.png'))\n\n\nimport shutil\nshutil.make_archive('images', 'zip', './output_images')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Results:"},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\n\nrandom_array = np.random.randint(n_images, size = 5)\n\nimages[0] = cv2.imread(os.path.join('./output_images', f'image_{random_array[0]:05d}.png'))\nimages[1] = cv2.imread(os.path.join('./output_images', f'image_{random_array[1]:05d}.png')) \nimages[2] = cv2.imread(os.path.join('./output_images', f'image_{random_array[2]:05d}.png')) \nimages[3] = cv2.imread(os.path.join('./output_images', f'image_{random_array[3]:05d}.png')) \nimages[4] = cv2.imread(os.path.join('./output_images', f'image_{random_array[4]:05d}.png')) \n\ndef show_images(image_batch):\n        plt.figure(figsize=(32,32))\n        for n in range(5):\n            ax = plt.subplot(1,5,n+1)\n            plt.imshow(images[n])\n            plt.axis('off')\n        plt.show()\n        \nshow_images(images)","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}