{"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":"!mkdir /kaggle/working/generative-dog-images\n!unzip /kaggle/input/generative-dog-images/all-dogs.zip -d /kaggle/working/generative-dog-images > /dev/null 2>&1\n!unzip /kaggle/input/generative-dog-images/Annotation.zip -d /kaggle/working/generative-dog-images > /dev/null 2>&1","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:32:22.230553Z","iopub.execute_input":"2021-10-26T02:32:22.231002Z","iopub.status.idle":"2021-10-26T02:32:42.79357Z","shell.execute_reply.started":"2021-10-26T02:32:22.230876Z","shell.execute_reply":"2021-10-26T02:32:42.792377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport torch\nimport torch.nn as nn\nfrom torchvision import transforms\nfrom torchvision.utils import make_grid\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport xml.etree.ElementTree as ET ","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:32:42.796123Z","iopub.execute_input":"2021-10-26T02:32:42.796461Z","iopub.status.idle":"2021-10-26T02:32:44.211037Z","shell.execute_reply.started":"2021-10-26T02:32:42.796425Z","shell.execute_reply":"2021-10-26T02:32:44.210316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"all_dogs_dir = '/kaggle/working/generative-dog-images/all-dogs'\nannotation_dir = '/kaggle/working/generative-dog-images/Annotation'","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:32:44.212564Z","iopub.execute_input":"2021-10-26T02:32:44.213056Z","iopub.status.idle":"2021-10-26T02:32:44.218428Z","shell.execute_reply.started":"2021-10-26T02:32:44.213013Z","shell.execute_reply":"2021-10-26T02:32:44.217144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_bndbox(filename, square=False):\n    tree = ET.parse(filename)\n    root = tree.getroot()\n    box = root.find('object').find('bndbox')\n    xmin = int(box.find('xmin').text)\n    ymin = int(box.find('ymin').text)\n    xmax = int(box.find('xmax').text)\n    ymax = int(box.find('ymax').text)\n    \n    if square:\n        center_x, center_y = (xmin + xmax)//2, (ymin+ymax)//2\n        max_w = max(xmax-xmin, ymax-ymin)\n        xmin = center_x - max_w//2\n        xmax = xmin + max_w\n        ymin = center_y - max_w//2\n        ymax = ymin + max_w\n        \n    return xmin, ymin, xmax, ymax  ","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:32:44.22051Z","iopub.execute_input":"2021-10-26T02:32:44.221236Z","iopub.status.idle":"2021-10-26T02:32:44.328687Z","shell.execute_reply.started":"2021-10-26T02:32:44.221188Z","shell.execute_reply":"2021-10-26T02:32:44.327906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dogs_dir = '/kaggle/working/dogs'\nif not os.path.exists(dogs_dir):\n    os.makedirs(dogs_dir)\n\nfor breed in os.listdir(annotation_dir):\n    for dog in os.listdir(os.path.join(annotation_dir, breed)):\n        bndbox = get_bndbox(os.path.join(annotation_dir, breed, dog), square=True)\n        jpg_name = os.path.join(all_dogs_dir, dog+'.jpg')\n        if os.path.exists(jpg_name):\n            img = Image.open(jpg_name).crop(bndbox)\n            img.save(os.path.join(dogs_dir, dog+'.jpg'))\nprint('number of dogs:', len(os.listdir(dogs_dir)))","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:32:44.33126Z","iopub.execute_input":"2021-10-26T02:32:44.331825Z","iopub.status.idle":"2021-10-26T02:35:41.71018Z","shell.execute_reply.started":"2021-10-26T02:32:44.33178Z","shell.execute_reply":"2021-10-26T02:35:41.708976Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset, DataLoader\n\nclass DogDataset(Dataset):\n    def __init__(self, data_dir, transforms=None):\n        self.files = [os.path.join(data_dir, file) for file in os.listdir(data_dir)]\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.files)\n    \n    def __getitem__(self, index):\n        img = Image.open(self.files[index])\n        if self.transforms is not None:\n            img = self.transforms(img)\n        return img","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:41.71152Z","iopub.execute_input":"2021-10-26T02:35:41.711779Z","iopub.status.idle":"2021-10-26T02:35:41.719757Z","shell.execute_reply.started":"2021-10-26T02:35:41.71175Z","shell.execute_reply":"2021-10-26T02:35:41.718756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_size = (64, 64)\nimage_transforms = transforms.Compose([\n    transforms.ToTensor(),\n    transforms.Resize(img_size),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n])\n\nbatch_size = 128\ntrainloader = DataLoader(\n    DogDataset(data_dir=dogs_dir, transforms=image_transforms),\n    batch_size = batch_size,\n    shuffle = True,\n    num_workers = 3,\n)","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:41.720941Z","iopub.execute_input":"2021-10-26T02:35:41.721202Z","iopub.status.idle":"2021-10-26T02:35:41.792261Z","shell.execute_reply.started":"2021-10-26T02:35:41.721152Z","shell.execute_reply":"2021-10-26T02:35:41.791496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DCGAN","metadata":{}},{"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, z_channels, out_channels=3):\n        super(Generator, self).__init__()\n        \n        convs = []\n        channels = [z_channels, 1024, 512, 256, 128, 64]\n        for i in range(1, len(channels)):\n            convs.append(nn.ConvTranspose2d(channels[i-1], channels[i], 2, stride=2, bias=False))\n            convs.append(nn.BatchNorm2d(channels[i]))\n            convs.append(nn.ReLU(inplace=True))\n        convs.append(nn.ConvTranspose2d(channels[-1], out_channels, 2, stride=2, bias=False))\n        convs.append(nn.Tanh())\n        \n        self.convs = nn.Sequential(*convs)\n        \n    def forward(self, x):\n        return self.convs(x)","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:41.793192Z","iopub.execute_input":"2021-10-26T02:35:41.793931Z","iopub.status.idle":"2021-10-26T02:35:41.804104Z","shell.execute_reply.started":"2021-10-26T02:35:41.793894Z","shell.execute_reply":"2021-10-26T02:35:41.80305Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self):\n        super(Discriminator, self).__init__()\n        channels = [3, 64, 128, 256, 512] # size: 64->32->16->8->4\n        convs = []\n        for i in range(1, len(channels)):\n            convs.append(nn.Conv2d(channels[i-1], channels[i], 3, padding=1, stride=2, bias=False))\n            if i != 1:\n                convs.append(nn.BatchNorm2d(channels[i]))\n            convs.append(nn.LeakyReLU(0.2, inplace=True))\n        \n        convs.append(nn.Conv2d(channels[-1], 1, 4, bias=False))\n        convs.append(nn.Sigmoid())\n        \n        self.convs = nn.Sequential(*convs)\n    \n    def forward(self, x):\n        x = self.convs(x)\n        return x.view(-1)","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:41.806183Z","iopub.execute_input":"2021-10-26T02:35:41.806606Z","iopub.status.idle":"2021-10-26T02:35:41.819485Z","shell.execute_reply.started":"2021-10-26T02:35:41.806543Z","shell.execute_reply":"2021-10-26T02:35:41.818285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def weights_init(m):\n    classname = m.__class__.__name__\n    if classname.find('Conv') != -1:\n        m.weight.data.normal_(0.0, 0.02)\n    elif classname.find('BatchNorm') != -1:\n        m.weight.data.normal_(1.0, 0.02)\n        m.bias.data.fill_(0)","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:41.820737Z","iopub.execute_input":"2021-10-26T02:35:41.821558Z","iopub.status.idle":"2021-10-26T02:35:41.838887Z","shell.execute_reply.started":"2021-10-26T02:35:41.821515Z","shell.execute_reply":"2021-10-26T02:35:41.83784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"z_channels = 100\nG = Generator(z_channels, 3)\nG.apply(weights_init)\nD = Discriminator()\nD.apply(weights_init)\ncriterion = nn.BCELoss()\n\ncuda = torch.cuda.is_available()\nif cuda:\n    print('Use GPU')\n    G = G.cuda()\n    D = D.cuda()\n    criterion = criterion.cuda()\nelse:\n    print('No GPU')","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:41.840372Z","iopub.execute_input":"2021-10-26T02:35:41.840872Z","iopub.status.idle":"2021-10-26T02:35:41.993923Z","shell.execute_reply.started":"2021-10-26T02:35:41.840837Z","shell.execute_reply":"2021-10-26T02:35:41.992881Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lr = 0.0002\nb = 0.5\noptimizer_G = torch.optim.Adam(G.parameters(), lr=lr, betas=(b, 0.999))\noptimizer_D = torch.optim.Adam(D.parameters(), lr=lr, betas=(b, 0.999))","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:41.995457Z","iopub.execute_input":"2021-10-26T02:35:41.995792Z","iopub.status.idle":"2021-10-26T02:35:42.003468Z","shell.execute_reply.started":"2021-10-26T02:35:41.995749Z","shell.execute_reply":"2021-10-26T02:35:42.00232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def range_rand(low, high, shape):\n    a = torch.rand(shape)\n    a = ((a - torch.min(a)) / (torch.max(a) - torch.min(a)) * (high-low)) + low\n    return a","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:42.00544Z","iopub.execute_input":"2021-10-26T02:35:42.005957Z","iopub.status.idle":"2021-10-26T02:35:42.018898Z","shell.execute_reply.started":"2021-10-26T02:35:42.005907Z","shell.execute_reply":"2021-10-26T02:35:42.017988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fixed_noise = torch.normal(0, 0.1, size=(64, z_channels, 1, 1))\nif cuda:\n    fixed_noise = fixed_noise.cuda()\n\nepoches = 100\ngenerate_imgs = []    \nfor epoch in range(epoches):\n    for i, img in enumerate(trainloader):\n        z = torch.normal(0, 0.1, size=(img.size(0), z_channels, 1, 1))\n        # real = range_rand(0.9, 1, (img.size(0), 1))\n        # fake = range_rand(0, 0.1, (img.size(0), 1))\n        real = torch.ones(img.size(0))\n        fake = torch.zeros(img.size(0))\n        if cuda:\n            img, z = img.cuda(), z.cuda()\n            real, fake = real.cuda(), fake.cuda()\n\n        # train D\n        D.zero_grad()\n        loss_real = criterion(D(img), real)\n        loss_real.backward()\n\n        fake_img = G(z)\n        loss_fake = criterion(D(fake_img.detach()), fake)\n        loss_fake.backward()\n\n        loss_D = (loss_real + loss_fake) / 2\n\n        optimizer_D.step()\n\n        # train G\n        G.zero_grad()\n        loss_G = criterion(D(fake_img), real)\n        loss_G.backward()\n        optimizer_G.step()\n\n    with torch.no_grad():\n        noise_img = G(fixed_noise)\n        generate_imgs.append(noise_img)\n        print(f'[Epoch {epoch+1}/{epoches}] [G loss: {loss_G.item()}] [D loss: {loss_D.item()} | loss_real: {loss_real.item()} loss_fake: {loss_fake.item()}]')","metadata":{"execution":{"iopub.status.busy":"2021-10-26T02:35:42.021885Z","iopub.execute_input":"2021-10-26T02:35:42.022154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.animation as animation\nfrom IPython.display import HTML\n\nfig = plt.figure(figsize=(10,10))\nplt.axis(\"off\")\n\nimgs = []\nfor batch_images in generate_imgs:\n    imgs.append([plt.imshow(make_grid(batch_images[:64], padding=2, normalize=True).cpu().permute(1,2,0))])\n\nani = animation.ArtistAnimation(fig, imgs, interval=1000, repeat_delay=1000, blit=True)\nHTML(ani.to_jshtml())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}