{"cells":[{"metadata":{},"cell_type":"markdown","source":"## Beginer LSGAN LESSON using Pytorch"},{"metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","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.","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## import module"},{"metadata":{"trusted":true},"cell_type":"code","source":"# basic modules\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm\nimport cv2\nimport matplotlib.animation as animation\nfrom IPython.display import HTML\nimport imgaug\nimport random\nfrom imgaug import augmenters as iaa\nfrom imgaug import parameters as iap\nfrom PIL import Image\n\n#keras modules\nfrom keras.preprocessing.image import img_to_array, load_img\n\n#Pytorch modules\nimport torch\nimport torch.nn as nn\nimport torch.nn.parallel\nimport torch.backends.cudnn as cudnn\nimport torch.optim as optim\nimport torch.utils.data\nimport torchvision.datasets as dset\nimport torchvision.transforms as transforms\nimport torchvision.utils as vutils\nfrom torchvision.utils import save_image\nfrom torch.nn.utils import spectral_norm\n\n#Crop images using bounding box\nimport xml.etree.ElementTree as ET\nimport glob","execution_count":null,"outputs":[]},{"metadata":{"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","trusted":true},"cell_type":"code","source":"img_list =os.listdir(\"../input/all-dogs/all-dogs/\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(img_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"root_images=\"../input/all-dogs/all-dogs/\"\nroot_annots=\"../input/annotation/Annotation/\"\ncroped_images=\"../croped_images/\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_images=os.listdir(\"../input/all-dogs/all-dogs/\")\nprint(f\"Total images : {len(all_images)}\")\n\nbreeds = glob.glob('../input/annotation/Annotation/*')\nannotation=[]\nfor b in breeds:\n    annotation+=glob.glob(b+\"/*\")\nprint(f\"Total annotation : {len(annotation)}\")\n\nbreed_map={}\nfor annot in annotation:\n    breed=annot.split(\"/\")[-2]\n    index=breed.split(\"-\")[0]\n    breed_map.setdefault(index,breed)\n    \nprint(f\"Total Breeds : {len(breed_map)}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def bounding_box(image):\n    bpath=root_annots+str(breed_map[image.split(\"_\")[0]])+\"/\"+str(image.split(\".\")[0])\n    tree = ET.parse(bpath)\n    root = tree.getroot()\n    objects = root.findall('object')\n    for o in objects:\n        bndbox = o.find('bndbox') # reading bound box\n        xmin = int(bndbox.find('xmin').text)\n        ymin = int(bndbox.find('ymin').text)\n        xmax = int(bndbox.find('xmax').text)\n        ymax = int(bndbox.find('ymax').text)\n        \n    return (xmin,ymin,xmax,ymax)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not os.path.exists(croped_images):\n    os.mkdir(croped_images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i,image in enumerate(all_images):\n    #print(image)\n    bbox=bounding_box(image)\n    im=Image.open(os.path.join(root_images,image))\n    im=im.crop(bbox)\n    im.save(croped_images + image, quality=95)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(os.listdir(\"../croped_images/\"))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## show sample images"},{"metadata":{"trusted":true},"cell_type":"code","source":"temp_img = load_img('../croped_images/n02085620_3423.jpg')\ntemp_img_array  = img_to_array(temp_img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"temp_img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"temp_img_array.shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## sample 15 train images"},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set_style(\"white\")\ncount = 1\nplt.figure(figsize=[20, 20])\nfor img_name in img_list[:15]:\n    #print(\"../input/all-dogs/all-dogs/%s.jpg\" % img_name)\n    img = cv2.imread(\"../croped_images/%s\" % img_name)[...,[2, 1, 0]]\n    plt.subplot(5, 5, count)\n    plt.imshow(img)\n    count += 1\n    \nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"manualSeed = random.randint(1000, 10000)\nprint(\"Random Seed: \", manualSeed)\nrandom.seed(manualSeed)\ntorch.manual_seed(manualSeed)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"if not os.path.exists('../result_images/'):\n    os.mkdir('../result_images/')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Root directory for dataset\ndataroot = \"../\"\nimage_size = 64\nnc = 3\nnz = 128\nngf = 64\nndf = 64\nnum_epochs = 200\nlr = 0.0001\nbeta1 = 0.5\n# Number of GPUs available. Use 0 for CPU mode.\nngpu = 1\n\n# Initial_setting\nworkers = 2\nbatch_size=64  \nnz = 100\nnch_g = 64\nnch_d = 64\nn_epoch = 200\nlr = 0.0002\nbeta1 = 0.5\noutf = '../result_images'\ndisplay_interval = 100\nsave_fake_image_interval = 1500\nplt.rcParams['figure.figsize'] = 10, 6","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## loading datasets"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Dataset Creator\nrand_aff = random.uniform(3.0, 15.0)\nrand_flip = random.uniform(0.3, 1.0)\nrand_trans = random.uniform(0.3, 0.7)\nrand_contr = random.uniform(0.2, 0.9)\nrandom_transforms = [transforms.ColorJitter(contrast=rand_contr), transforms.RandomAffine(degrees=rand_aff)]\n\ndataset = dset.ImageFolder(root=dataroot,\n                          transform=transforms.Compose([\n                          transforms.RandomResizedCrop(64, scale=(0.9, 1.0), ratio=(1., 1.)),\n                          transforms.RandomHorizontalFlip(),\n                          transforms.ColorJitter(brightness=0.05, contrast=0.05, saturation=0.05, hue=0.05),\n                          transforms.ToTensor(),\n                          transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),\n                      ]))  \n\n# Create the dataloader\ndataloader = torch.utils.data.DataLoader(dataset, batch_size=batch_size,\n                                         shuffle=True, num_workers=workers)\n\n# Decide which device we want to run on\ndevice = torch.device(\"cuda:0\" if (torch.cuda.is_available() and ngpu > 0) else \"cpu\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## check train images using torch utils"},{"metadata":{"trusted":true},"cell_type":"code","source":"real_batch = next(iter(dataloader))\nplt.figure(figsize=(8,8))\nplt.axis(\"off\")\nplt.title(\"Training Images\")\nplt.imshow(np.transpose(vutils.make_grid(real_batch[0].to(device)[:64], padding=2, normalize=True).cpu(),(1,2,0)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"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        m.bias.data.fill_(0)\n    elif classname.find('Linear') != -1:        \n        m.weight.data.normal_(0.0, 0.02)\n        m.bias.data.fill_(0)\n    elif classname.find('BatchNorm') != -1:    \n        m.weight.data.normal_(1.0, 0.02)\n        m.bias.data.fill_(0)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## make Generator"},{"metadata":{"trusted":true},"cell_type":"code","source":"class Generator(nn.Module):\n    def __init__(self, nz=100, nch_g=64, nch=3):\n        super(Generator, self).__init__()\n        self.layers = nn.ModuleDict({\n            'layer0': nn.Sequential(\n                spectral_norm(nn.ConvTranspose2d(nz, nch_g * 8, 4, 1, 0)),     \n                nn.BatchNorm2d(nch_g * 8),                      \n                nn.ReLU()                                       \n            ),  # (100, 1, 1) -> (512, 4, 4)\n            'layer1': nn.Sequential(\n                spectral_norm(nn.ConvTranspose2d(nch_g * 8, nch_g * 4, 4, 2, 1)),\n                nn.BatchNorm2d(nch_g * 4),\n                nn.ReLU()\n            ),  # (512, 4, 4) -> (256, 8, 8)\n            'layer2': nn.Sequential(\n                spectral_norm(nn.ConvTranspose2d(nch_g * 4, nch_g * 2, 4, 2, 1)),\n                nn.BatchNorm2d(nch_g * 2),\n                nn.ReLU()\n            ),  # (256, 8, 8) -> (128, 16, 16)\n\n            'layer3': nn.Sequential(\n                spectral_norm(nn.ConvTranspose2d(nch_g * 2, nch_g, 4, 2, 1)),\n                nn.BatchNorm2d(nch_g),\n                nn.ReLU()\n            ),  # (128, 16, 16) -> (64, 32, 32)\n            'layer4': nn.Sequential(\n                spectral_norm(nn.ConvTranspose2d(nch_g, nch, 4, 2, 1)),\n                nn.Tanh()\n            )   # (64, 32, 32) -> (3, 64, 64)\n        })\n\n    def forward(self, z):\n        for layer in self.layers.values():  \n            z = layer(z)\n        return z","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## make Discriminator"},{"metadata":{"trusted":true},"cell_type":"code","source":"class Discriminator(nn.Module):\n    def __init__(self, nch=3, nch_d=64):\n        super(Discriminator, self).__init__()\n        self.layers = nn.ModuleDict({\n            'layer0': nn.Sequential(\n                spectral_norm(nn.Conv2d(nch, nch_d, 4, 2, 1)),     \n                nn.LeakyReLU(negative_slope=0.2)    \n            ),  # (3, 64, 64) -> (64, 32, 32)\n            'layer1': nn.Sequential(\n                spectral_norm(nn.Conv2d(nch_d, nch_d * 2, 4, 2, 1)),\n                nn.BatchNorm2d(nch_d * 2),\n                nn.LeakyReLU(negative_slope=0.2)\n            ),  # (64, 32, 32) -> (128, 16, 16)\n            'layer2': nn.Sequential(\n                spectral_norm(nn.Conv2d(nch_d * 2, nch_d * 4, 4, 2, 1)),\n                nn.BatchNorm2d(nch_d * 4),\n                nn.LeakyReLU(negative_slope=0.2)\n            ),  # (128, 16, 16) -> (256, 8, 8)\n            'layer3': nn.Sequential(\n                spectral_norm(nn.Conv2d(nch_d * 4, nch_d * 8, 4, 2, 1)),\n                nn.BatchNorm2d(nch_d * 8),\n                nn.LeakyReLU(negative_slope=0.2)\n            ),  # (256, 8, 8) -> (512, 4, 4)\n            'layer4': spectral_norm(nn.Conv2d(nch_d * 8, 1, 4, 1, 0))\n            # (512, 4, 4) -> (1, 1, 1)\n        })\n\n    def forward(self, x):\n        for layer in self.layers.values():  \n            x = layer(x)\n        return x.squeeze()     \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('device:', device)\n\nnetG = Generator(nz=nz, nch_g=nch_g).to(device)\nnetG.apply(weights_init)    \nprint(netG)\n\nnetD = Discriminator(nch_d=nch_d).to(device)\nnetD.apply(weights_init)\nprint(netD)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"criterion = nn.MSELoss()\noptimizerD = optim.Adam(netD.parameters(), lr=lr, betas=(beta1, 0.999), weight_decay=1e-5)  \noptimizerG = optim.Adam(netG.parameters(), lr=lr, betas=(beta1, 0.999), weight_decay=1e-5)  \n\nfixed_noise = torch.randn(batch_size, nz, 1, 1, device=device)  # save_fake_image用ノイズ（固定）\nLoss_D_list, Loss_G_list = [], []\n\nsave_fake_image_count = 1","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#####    trainig_loop\nfor epoch in tqdm(range(n_epoch)):\n    for itr, data in enumerate(dataloader):\n        real_image = data[0].to(device)   # 本物画像\n        sample_size = real_image.size(0)  # 画像枚数\n        noise = torch.randn(sample_size, nz, 1, 1, device=device)   # 入力ベクトル生成（正規分布ノイズ）       \n        real_target = torch.full((sample_size,), 1., device=device)   # 目標値（本物）\n        fake_target = torch.full((sample_size,), 0., device=device)   # 目標値（偽物）\n\n        #--------  Update Discriminator  ---------\n        netD.zero_grad()    # 勾配の初期化\n\n        output = netD(real_image)   # Discriminatorが行った、本物画像の判定結果\n        errD_real = criterion(output, real_target)  # 本物画像の判定結果と目標値（本物）の二乗誤差\n        D_x = output.mean().item()  # outputの平均 D_x を計算（後でログ出力に使用）\n\n        fake_image = netG(noise)    # Generatorが生成した偽物画像\n\n        output = netD(fake_image.detach())  # Discriminatorが行った、偽物画像の判定結果\n        errD_fake = criterion(output, fake_target)  # 偽物画像の判定結果と目標値（偽物）の二乗誤差\n        D_G_z1 = output.mean().item()  # outputの平均 D_G_z1 を計算（後でログ出力に使用）\n\n        errD = errD_real + errD_fake    # Discriminator 全体の損失\n        errD.backward()    # 誤差逆伝播\n        optimizerD.step()   # Discriminatoeのパラメーター更新\n\n        #---------  Update Generator   ----------\n        netG.zero_grad()    # 勾配の初期化        \n        output = netD(fake_image)   # 更新した Discriminatorで、偽物画像を判定\n        errG = criterion(output, real_target)   # 偽物画像の判定結果と目標値（本物）の二乗誤差\n        errG.backward()     # 誤差逆伝播\n        D_G_z2 = output.mean().item()  # outputの平均 D_G_z2 を計算（後でログ出力に使用）\n\n        optimizerG.step()   # Generatorのパラメータ更新\n\n        if itr % display_interval == 0:\n            print('[{}/{}][{}/{}] Loss_D: {:.3f} Loss_G: {:.3f} D(x): {:.3f} D(G(z)): {:.3f}/{:.3f}'\n                  .format(epoch + 1, n_epoch,itr + 1, len(dataloader),errD.item(), errG.item(), D_x, D_G_z1, D_G_z2))\n\n            Loss_D_list.append(errD.item())\n            Loss_G_list.append(errG.item())\n\n        if epoch == 0 and itr == 0:     \n            vutils.save_image(real_image, '{}/real_samples.png'.format(outf),normalize=True, nrow=8)\n\n        if itr % save_fake_image_interval == 0 and itr > 0:\n            fake_image = netG(fixed_noise)\n            vutils.save_image(fake_image.detach(), '{}/fake_samples_{:03d}.png'.format(outf, save_fake_image_count),normalize=True, nrow=8)\n            save_fake_image_count +=1\n\n    # ---------  save fake image  ----------\n    fake_image = netG(fixed_noise)  \n    vutils.save_image(fake_image.detach(), '{}/fake_samples_epoch_{:03d}.png'.format(outf, epoch + 1),\n                      normalize=True, nrow=8)\n\n    # ---------  save model  -----------\n    if (epoch + 1) % 10 == 0:   # 10エポックごとにモデルを保存する\n        torch.save(netG.state_dict(), '{}/netG_epoch_{}.pth'.format(outf, epoch + 1))\n        torch.save(netD.state_dict(), '{}/netD_epoch_{}.pth'.format(outf, epoch + 1))\n\n# plot graph\nplt.figure()    \nplt.plot(range(len(Loss_D_list)), Loss_D_list, color='blue', linestyle='-', label='Loss_D')\nplt.plot(range(len(Loss_G_list)), Loss_G_list, color='red', linestyle='-', label='Loss_G')\nplt.legend()\nplt.xlabel('iter (*100)')\nplt.ylabel('loss')\nplt.title('Loss_D and Loss_G')\nplt.grid()\nplt.savefig('Loss_graph.png') ","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## save images"},{"metadata":{"trusted":false},"cell_type":"code","source":"if not os.path.exists('../output_images'):\n    os.mkdir('../output_images')\n    \nim_batch_size = 50\nn_images=10000\n\nfor i_batch in tqdm(range(0, n_images, im_batch_size)):\n    gen_z = torch.randn(im_batch_size, nz, 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'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":false},"cell_type":"code","source":"import shutil\nshutil.make_archive('images', 'zip', '../output_images')","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.6"}},"nbformat":4,"nbformat_minor":1}