{"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":"from __future__ import print_function\n#%matplotlib inline\nimport argparse\nimport os\nimport random\nimport time\nimport ast\nimport os\nimport json\nimport pandas as pd\nimport importlib\nimport cv2\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport matplotlib.animation as animation\nfrom IPython.display import HTML\nfrom shutil import copyfile\nfrom tqdm.notebook import tqdm\nfrom PIL import Image\nfrom string import Template\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\nfrom torch.autograd import Variable\nimport torch.nn.functional as F\nimport torchvision\nimport torchvision.datasets as dset\nimport torchvision.transforms as transforms\nimport torchvision.utils as vutils\n\n# Reproduce Results\nSEED = 1992\nnp.random.seed(SEED)\nrandom.seed(SEED)\ntorch.manual_seed(SEED)\ntqdm.pandas() # For Progress Bar\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-02-03T17:10:09.47816Z","iopub.execute_input":"2022-02-03T17:10:09.478692Z","iopub.status.idle":"2022-02-03T17:10:11.390829Z","shell.execute_reply.started":"2022-02-03T17:10:09.478652Z","shell.execute_reply":"2022-02-03T17:10:11.389996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 📖 GAN Introduction\n\n\n![gan](https://learn-neural-networks.com/wp-content/uploads/2020/04/gan.jpg)\n\nThe core idea of a GAN is based on the \"indirect\" training through the discriminator, another neural network that is able to tell how much an input is \"realistic\", which itself is also being updated dynamically This basically means that the generator is not trained to minimize the distance to a specific image, but rather to fool the discriminator. This enables the model to learn in an unsupervised manner.(Wiki)<br>\n\n>I have also presented the Neural Style Transfer [Notebook Here](https://www.kaggle.com/marcinstasko/cots-neuralstyle-transfer-pytorch-augumentation)","metadata":{}},{"cell_type":"markdown","source":"Easy Explanation:\n* ***Dimensional noise vector:***   is just the random noise (dough) where the final image will come from. It act like seed for the generator network\n* ***Generator***  Network with create an image from the random noise\n* ***Discriminator*** Network witch classify Real/Fake\n\nGenerator tries to cheat discriminator to generate images with will be real<br>\nIn the same time Discriminator learn the \"cheat\" techniques and it is better to distinguish between Real/Fake\n\n","metadata":{}},{"cell_type":"markdown","source":"## Please Upvote if you find this Helpful\n> This notebook shows how to use generator to generate the new images and handle the results [Unlimited COTS Generator -Pytorch GAN in action](https://www.kaggle.com/marcinstasko/unlimited-cots-generator-pytorch-gan-in-action)<br>\n> Another augumentation method Neural Style transfer [COTS - NeuralStyle Transfer Pytorch Augumentation](https://www.kaggle.com/marcinstasko/cots-neuralstyle-transfer-pytorch-augumentation)","metadata":{}},{"cell_type":"markdown","source":"# 🔨 ETL Pipeline\n>We have to extract the bboxes for the training. For this purpose we will create the pipeline to generate snippets","metadata":{}},{"cell_type":"markdown","source":"## Enviroment Creation","metadata":{}},{"cell_type":"code","source":"# Create the Folder Structure and I/O Locations\n\nTRAIN_PATH = \"../input/tensorflow-great-barrier-reef/train_images\"\nGAN_TRAINING_PATH = \"./GAN\"\nGAN_MODEL_PATH = f\"{GAN_TRAINING_PATH}/Models\"\nGAN_IMAGES_PATH = f\"{GAN_TRAINING_PATH}/Images\"\nBBOX_PATH = \"./BBOX\"\nRAW_BBOX_PATH = f\"{BBOX_PATH}/raw\"\n\n!mkdir {GAN_TRAINING_PATH}\n!mkdir {GAN_MODEL_PATH}\n!mkdir {GAN_IMAGES_PATH}\n!mkdir {BBOX_PATH}\n!mkdir {RAW_BBOX_PATH}\n","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:10:14.077835Z","iopub.execute_input":"2022-02-03T17:10:14.078539Z","iopub.status.idle":"2022-02-03T17:10:17.585732Z","shell.execute_reply.started":"2022-02-03T17:10:14.078497Z","shell.execute_reply":"2022-02-03T17:10:17.584797Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🧹 Data Preprocessing","metadata":{}},{"cell_type":"code","source":"def get_bbox(annots):\n    bboxes = [list(annot.values()) for annot in annots]\n    return bboxes\n\ndef get_path(row):\n    row['image_path'] = f'{TRAIN_PATH}/video_{row.video_id}/{row.video_frame}.jpg'\n    return row\n\ndef csv_preparation(df,min_annots=1):\n    # Taken only annotated photos\n    df[\"num_bbox\"] = df['annotations'].apply(lambda x: str.count(x, 'x'))\n\n    df_train = df[df[\"num_bbox\"]>=min_annots]\n\n    #Annotations \n    df_train['annotations'] = df_train['annotations'].progress_apply(lambda x: ast.literal_eval(x))\n    df_train['bboxes'] = df_train.annotations.progress_apply(get_bbox)\n\n    #Images resolution\n    df_train[\"width\"] = 1280\n    df_train[\"height\"] = 720\n\n    #Path of images\n    df_train = df_train.progress_apply(get_path, axis=1)\n    return df_train\n","metadata":{"execution":{"iopub.status.busy":"2022-02-03T16:13:48.281981Z","iopub.execute_input":"2022-02-03T16:13:48.282264Z","iopub.status.idle":"2022-02-03T16:13:48.290487Z","shell.execute_reply.started":"2022-02-03T16:13:48.282226Z","shell.execute_reply":"2022-02-03T16:13:48.289785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Data Preparation\ntrain_raw = pd.read_csv(\"../input/tensorflow-great-barrier-reef/train.csv\")\n\ndf_train = csv_preparation(train_raw,min_annots=1)\n\ndf_train.head()","metadata":{"execution":{"iopub.status.busy":"2022-02-03T16:13:48.291983Z","iopub.execute_input":"2022-02-03T16:13:48.292404Z","iopub.status.idle":"2022-02-03T16:13:51.896715Z","shell.execute_reply.started":"2022-02-03T16:13:48.292364Z","shell.execute_reply":"2022-02-03T16:13:51.89558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 📁 Generate Data for GAN\n","metadata":{}},{"cell_type":"code","source":"def save_bbox(df, bb_path):\n    annotion_id = 0\n    for ann_row in df.itertuples():\n        img = cv2.imread(ann_row.image_path)\n        bbox_list = ann_row.bboxes\n        \n        for bbox in bbox_list:\n            b_width = bbox[2]\n            b_height = bbox[3]\n\n            # some boxes in COTS are outside the image height and width\n            if (bbox[0] + bbox[2] > 1280):\n                b_width = bbox[0] - 1280 \n            if (bbox[1] + bbox[3] > 720):\n                b_height = bbox[1] - 720 \n\n            box = img[bbox[1]:bbox[1]+b_height, bbox[0]:bbox[0]+b_width]\n\n            annotion_id += 1\n            try:\n                cv2.imwrite(f'{RAW_BBOX_PATH}/{annotion_id}.jpg', box)\n            except:\n                pass","metadata":{"execution":{"iopub.status.busy":"2022-02-03T16:13:51.903387Z","iopub.execute_input":"2022-02-03T16:13:51.903807Z","iopub.status.idle":"2022-02-03T16:13:51.918045Z","shell.execute_reply.started":"2022-02-03T16:13:51.903767Z","shell.execute_reply":"2022-02-03T16:13:51.91535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# To save the time we will query the data to get urls where bbox exist\nsave_bbox(df_train.loc[df_train.num_bbox>0], BBOX_PATH)","metadata":{"execution":{"iopub.status.busy":"2022-02-03T16:13:51.919466Z","iopub.execute_input":"2022-02-03T16:13:51.919702Z","iopub.status.idle":"2022-02-03T16:16:05.505434Z","shell.execute_reply.started":"2022-02-03T16:13:51.919667Z","shell.execute_reply":"2022-02-03T16:16:05.504655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Count how many files in folder\n!ls {RAW_BBOX_PATH} |wc -l","metadata":{"execution":{"iopub.status.busy":"2022-02-03T16:16:05.506864Z","iopub.execute_input":"2022-02-03T16:16:05.50714Z","iopub.status.idle":"2022-02-03T16:16:06.189913Z","shell.execute_reply.started":"2022-02-03T16:16:05.507104Z","shell.execute_reply":"2022-02-03T16:16:06.189124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🚅 Training Procedure\n","metadata":{}},{"cell_type":"markdown","source":"## ⚙ Training Configuration","metadata":{}},{"cell_type":"code","source":"# Parameters to define the model.\nparams = {\n    \"bsize\" :   16,        # Batch size during training.\n    'imsize' :  64,       # Spatial size of training images. All images will be resized to this size during preprocessing.\n    'nc' :      3,        # Number of channles in the training images. For coloured images this is 3.\n    'nz' :      100,      # Size of the Z latent vector (the input to the generator).\n    'ngf' :     64,       # Size of feature maps in the generator. The depth will be multiples of this.\n    'ndf' :     64,       # Size of features maps in the discriminator. The depth will be multiples of this.\n    'nepochs' : 75,      # Number of training epochs.\n    'lr' :      0.0001,   # Learning rate for optimizers\n    'beta1' :   0.5,      # Beta1 hyperparam for Adam optimizer\n    'save_epoch' : 5}     # Save step.","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:10:35.651791Z","iopub.execute_input":"2022-02-03T17:10:35.65238Z","iopub.status.idle":"2022-02-03T17:10:35.657686Z","shell.execute_reply.started":"2022-02-03T17:10:35.652341Z","shell.execute_reply":"2022-02-03T17:10:35.656817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device =torch.device('cuda')\nrandom_transforms = [transforms.RandomRotation(degrees=5)]\n\ntransform = transforms.Compose([\n                                transforms.Resize(params['imsize']),\n                                transforms.CenterCrop(params['imsize']),\n                                transforms.RandomApply(random_transforms, p=0.3),\n                                transforms.RandomHorizontalFlip(p=0.5),\n                                transforms.ToTensor(),\n                                transforms.Normalize((0.5, 0.5, 0.5),(0.5, 0.5, 0.5))\n                                ])\ntrain_data = torchvision.datasets.ImageFolder(BBOX_PATH, transform=transform)\n\ndataloader = torch.utils.data.DataLoader(train_data,\n                                          shuffle=True,\n                                          batch_size=params['bsize']\n                                         )\n\nimgs, label = next(iter(dataloader))\nimgs = imgs.numpy().transpose(0, 2, 3, 1)\n","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:10:36.691213Z","iopub.execute_input":"2022-02-03T17:10:36.692005Z","iopub.status.idle":"2022-02-03T17:10:36.911853Z","shell.execute_reply.started":"2022-02-03T17:10:36.691969Z","shell.execute_reply":"2022-02-03T17:10:36.911062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Generate sample batch\nsample_batch = next(iter(dataloader))\n\n# Plot the training images.\nplt.figure(figsize=(8, 8))\nplt.axis(\"off\")\nplt.title(\"Training Images\")\nplt.imshow(np.transpose(vutils.make_grid(\n    sample_batch[0].to(device)[ : params['bsize']], padding=2, normalize=True).cpu(), (1, 2, 0)))\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:10:37.709779Z","iopub.execute_input":"2022-02-03T17:10:37.710277Z","iopub.status.idle":"2022-02-03T17:10:40.899749Z","shell.execute_reply.started":"2022-02-03T17:10:37.710234Z","shell.execute_reply":"2022-02-03T17:10:40.899043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 🔭 Create Generator and Discriminator instances","metadata":{}},{"cell_type":"code","source":"def weights_init(w):\n    \"\"\"\n    Initializes the weights of the layer, w.\n    \"\"\"\n    classname = w.__class__.__name__\n    if classname.find('conv') != -1:\n        nn.init.normal_(w.weight.data, 0.0, 0.02)\n    elif classname.find('bn') != -1:\n        nn.init.normal_(w.weight.data, 1.0, 0.02)\n        nn.init.constant_(w.bias.data, 0)\n\n# Define the Generator Network\nclass Generator(nn.Module):\n    def __init__(self, params):\n        super().__init__()\n\n        # Input is the latent vector Z.\n        self.tconv1 = nn.ConvTranspose2d(params['nz'], params['ngf']*8,\n            kernel_size=4, stride=1, padding=0, bias=False)\n        self.bn1 = nn.BatchNorm2d(params['ngf']*8)\n\n        # Input Dimension: (ngf*8) x 4 x 4\n        self.tconv2 = nn.ConvTranspose2d(params['ngf']*8, params['ngf']*4,\n            4, 2, 1, bias=False)\n        self.bn2 = nn.BatchNorm2d(params['ngf']*4)\n\n        # Input Dimension: (ngf*4) x 8 x 8\n        self.tconv3 = nn.ConvTranspose2d(params['ngf']*4, params['ngf']*2,\n            4, 2, 1, bias=False)\n        self.bn3 = nn.BatchNorm2d(params['ngf']*2)\n\n        # Input Dimension: (ngf*2) x 16 x 16\n        self.tconv4 = nn.ConvTranspose2d(params['ngf']*2, params['ngf'],\n            4, 2, 1, bias=False)\n        self.bn4 = nn.BatchNorm2d(params['ngf'])\n\n        # Input Dimension: (ngf) * 32 * 32\n        self.tconv5 = nn.ConvTranspose2d(params['ngf'], params['nc'],\n            4, 2, 1, bias=False)\n        #Output Dimension: (nc) x 64 x 64\n\n    def forward(self, x):\n        x = F.relu(self.bn1(self.tconv1(x)))\n        x = F.relu(self.bn2(self.tconv2(x)))\n        x = F.relu(self.bn3(self.tconv3(x)))\n        x = F.relu(self.bn4(self.tconv4(x)))\n\n        x = F.tanh(self.tconv5(x))\n\n        return x","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:10:40.901062Z","iopub.execute_input":"2022-02-03T17:10:40.90199Z","iopub.status.idle":"2022-02-03T17:10:40.916918Z","shell.execute_reply.started":"2022-02-03T17:10:40.90195Z","shell.execute_reply":"2022-02-03T17:10:40.915968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define the Discriminator Network\nclass Discriminator(nn.Module):\n    def __init__(self, params):\n        super().__init__()\n\n        # Input Dimension: (nc) x 64 x 64\n        self.conv1 = nn.Conv2d(params['nc'], params['ndf'],\n            4, 2, 1, bias=False)\n\n        # Input Dimension: (ndf) x 32 x 32\n        self.conv2 = nn.Conv2d(params['ndf'], params['ndf']*2,\n            4, 2, 1, bias=False)\n        self.bn2 = nn.BatchNorm2d(params['ndf']*2)\n\n        # Input Dimension: (ndf*2) x 16 x 16\n        self.conv3 = nn.Conv2d(params['ndf']*2, params['ndf']*4,\n            4, 2, 1, bias=False)\n        self.bn3 = nn.BatchNorm2d(params['ndf']*4)\n\n        # Input Dimension: (ndf*4) x 8 x 8\n        self.conv4 = nn.Conv2d(params['ndf']*4, params['ndf']*8,\n            4, 2, 1, bias=False)\n        self.bn4 = nn.BatchNorm2d(params['ndf']*8)\n\n        # Input Dimension: (ndf*8) x 4 x 4\n        self.conv5 = nn.Conv2d(params['ndf']*8, 1, 4, 1, 0, bias=False)\n\n    def forward(self, x):\n        x = F.leaky_relu(self.conv1(x), 0.2, True)\n        x = F.leaky_relu(self.bn2(self.conv2(x)), 0.2, True)\n        x = F.leaky_relu(self.bn3(self.conv3(x)), 0.2, True)\n        x = F.leaky_relu(self.bn4(self.conv4(x)), 0.2, True)\n\n        x = torch.sigmoid(self.conv5(x))\n\n        return x","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:10:40.924428Z","iopub.execute_input":"2022-02-03T17:10:40.925056Z","iopub.status.idle":"2022-02-03T17:10:40.936773Z","shell.execute_reply.started":"2022-02-03T17:10:40.925026Z","shell.execute_reply":"2022-02-03T17:10:40.936004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create the generator.\nnetG = Generator(params).to(device)\n\n# Apply the weights_init() function to randomly initialize all\n# weights to mean=0.0, stddev=0.2\nnetG.apply(weights_init)\n# Print the model.\nprint(netG)\n\n# Step 2. Create Discriminator\nnetD = Discriminator(params).to(device)\n# Apply the weights_init() function to randomly initialize all\n\nnetD.apply(weights_init)\n# Print the model.\nprint(netD)\n\n# Binary Cross Entropy loss function.\ncriterion = nn.BCELoss()\n\n#Create the fixed noise\nfixed_noise = torch.randn(params['ngf'], params['nz'], 1, 1, device=device)\n\nreal_label = 1 # You can reduce it to 0.9 or less to more in depth control the training\nfake_label = 0\n\n# Optimizer for the discriminator.\noptimizerD = optim.Adam(netD.parameters(), lr=params['lr'], betas=(params['beta1'], 0.999))\n# Optimizer for the generator.\noptimizerG = optim.Adam(netG.parameters(), lr=params['lr'], betas=(params['beta1'], 0.999))","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:14:49.338116Z","iopub.execute_input":"2022-02-03T17:14:49.338722Z","iopub.status.idle":"2022-02-03T17:14:49.407291Z","shell.execute_reply.started":"2022-02-03T17:14:49.338681Z","shell.execute_reply":"2022-02-03T17:14:49.40653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 📈 Training Loop","metadata":{}},{"cell_type":"code","source":"# # Stores generated images as training progresses.\nimg_list = []\n# # Stores generator losses during training.\nG_losses = []\n# # Stores discriminator losses during training.\nD_losses = []\niters = 0\nprint(\"Gladiators let`s fight:\")\nprint(\"#\"*25)\n\nfor epoch in range(params['nepochs']):\n    for i, data in enumerate(dataloader, 0):\n        # Transfer data tensor to GPU/CPU (device)\n        real_data = data[0].to(device)\n        \n        # Get batch size. Can be different from params['nbsize'] for last batch in epoch.\n        b_size = real_data.size(0)\n        \n        # Make accumalated gradients of the discriminator zero.\n        netD.zero_grad()\n        \n        # Create labels for the real data. (label=1)\n        label = torch.full((b_size, ), real_label, device=device)\n        output = netD(real_data).view(-1)\n        output = output.to(torch.float32)\n        label = label.to(torch.float32)\n        errD_real = criterion(output, label)\n        \n        # Calculate gradients for backpropagation.\n        errD_real.backward()\n        D_x = output.mean().item()\n        \n        # Sample random data from a unit normal distribution.\n        noise = torch.randn(b_size, params['nz'], 1, 1, device=device)\n        # Generate fake data (images).\n        fake_data = netG(noise)\n        # Create labels for fake data. (label=0)\n        label.fill_(fake_label  )\n\n        output = netD(fake_data.detach()).view(-1)\n        \n        errD_fake = criterion(output, label)\n        # Calculate gradients for backpropagation.\n        errD_fake.backward()\n        D_G_z1 = output.mean().item()\n\n        # Net discriminator loss.\n        errD = errD_real + errD_fake\n        # Update discriminator parameters.\n        optimizerD.step()\n        \n        # Make accumalted gradients of the generator zero.\n        netG.zero_grad()\n        # We want the fake data to be classified as real. Hence\n        # real_label are used. (label=1)\n        label.fill_(real_label)\n        # No detach() is used here as we want to calculate the gradients w.r.t.\n        # the generator this time.\n        output = netD(fake_data).view(-1)\n        errG = criterion(output, label)\n        # Gradients for backpropagation are calculated.\n        # Gradients w.r.t. both the generator and the discriminator\n        errG.backward()\n\n        D_G_z2 = output.mean().item()\n        # Update generator parameters.\n        optimizerG.step()\n\n        # Check progress of training.\n        if i%250 == 0:\n            print(torch.cuda.is_available())\n            print('[%d/%d][%d/%d]\\tLoss_D: %.4f\\tLoss_G: %.4f\\tD(x): %.4f\\tD(G(z)): %.4f / %.4f'\n                  % ((epoch), params['nepochs'], i, len(dataloader),\n                     errD.item(), errG.item(), D_x, D_G_z1, D_G_z2))\n\n        # Save the losses for plotting.\n        G_losses.append(errG.item())\n        D_losses.append(errD.item())\n\n        # Check how the generator is doing by saving G's output on a fixed noise.\n        if (iters % 300 == 0) or ((epoch == params['nepochs']-1) and (i == len(dataloader)-1)):\n            with torch.no_grad():\n                fake_data = netG(fixed_noise).detach().cpu()\n                vutils.save_image(real_data, f\"{GAN_IMAGES_PATH}/real_samples.jpg\", normalize=True)\n                vutils.save_image(fake_data.data, f\"{GAN_IMAGES_PATH}/fake_samples_epoch_{epoch}.jpg\", normalize=True)\n            img_list.append(vutils.make_grid(fake_data.data, padding=2, normalize=True))\n        iters +=1\n        \n\n    # Save the model.\n    if epoch % params['save_epoch'] == 0:\n        torch.save({\n            'generator' : netG.state_dict(),\n            'discriminator' : netD.state_dict(),\n            'optimizerG' : optimizerG.state_dict(),\n            'optimizerD' : optimizerD.state_dict(),\n            'params' : params\n            },f\"{GAN_MODEL_PATH}/model_epoch_{epoch}.pth\")","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:14:51.366527Z","iopub.execute_input":"2022-02-03T17:14:51.367128Z","iopub.status.idle":"2022-02-03T17:47:19.110639Z","shell.execute_reply.started":"2022-02-03T17:14:51.367091Z","shell.execute_reply":"2022-02-03T17:47:19.109799Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 🔍 Training History","metadata":{}},{"cell_type":"code","source":"# Plot the training losses.\nplt.figure(figsize=(10,5))\nplt.title(\"Generator and Discriminator Loss During Training\")\nplt.plot(G_losses,label=\"G\")\nplt.plot(D_losses,label=\"D\")\nplt.xlabel(\"iterations\")\nplt.ylabel(\"Loss\")\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:48:43.882192Z","iopub.execute_input":"2022-02-03T17:48:43.882537Z","iopub.status.idle":"2022-02-03T17:48:44.34375Z","shell.execute_reply.started":"2022-02-03T17:48:43.882503Z","shell.execute_reply":"2022-02-03T17:48:44.342976Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save the final trained model.\ntorch.save({\n            'generator' : netG.state_dict(),\n            'discriminator' : netD.state_dict(),\n            'optimizerG' : optimizerG.state_dict(),\n            'optimizerD' : optimizerD.state_dict(),\n            'params' : params\n            }, './model_final.pth')","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:48:47.142164Z","iopub.execute_input":"2022-02-03T17:48:47.143142Z","iopub.status.idle":"2022-02-03T17:48:47.329172Z","shell.execute_reply.started":"2022-02-03T17:48:47.143053Z","shell.execute_reply":"2022-02-03T17:48:47.328194Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# ✨ Animate training progress","metadata":{}},{"cell_type":"code","source":"%matplotlib inline\nimport matplotlib.animation as animation\n\n# Create the gif to show how training was performing :) \nfig = plt.figure(figsize=(8,8))\nplt.axis(\"off\")\nims = [[plt.imshow(np.transpose(i,(1,2,0)), animated=True)] for i in img_list]\nanim = animation.ArtistAnimation(fig, ims, interval=50, repeat_delay=250, blit=True)\nanim.save('gan.gif', dpi=35, writer='imagemagick')","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:48:50.662683Z","iopub.execute_input":"2022-02-03T17:48:50.662971Z","iopub.status.idle":"2022-02-03T17:52:37.041304Z","shell.execute_reply.started":"2022-02-03T17:48:50.66294Z","shell.execute_reply":"2022-02-03T17:52:37.040588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_gif(fname):\n    import base64\n    from IPython import display\n    with open(fname, 'rb') as fd:\n        b64 = base64.b64encode(fd.read()).decode('ascii')\n    return display.HTML(f'<img src=\"data:image/gif;base64,{b64}\" />')\n\n\nshow_gif(\"./gan.gif\")","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:52:37.043343Z","iopub.execute_input":"2022-02-03T17:52:37.044268Z","iopub.status.idle":"2022-02-03T17:52:39.52076Z","shell.execute_reply.started":"2022-02-03T17:52:37.044211Z","shell.execute_reply":"2022-02-03T17:52:39.519787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Please Upvote if you find this Helpful\n> This notebook shows how to use generator to generate the new images and handle the results [Unlimited COTS Generator -Pytorch GAN in action](https://www.kaggle.com/marcinstasko/unlimited-cots-generator-pytorch-gan-in-action)<br>\n> Another augumentation method Neural Style transfer [COTS - NeuralStyle Transfer Pytorch Augumentation](https://www.kaggle.com/marcinstasko/cots-neuralstyle-transfer-pytorch-augumentation)","metadata":{}},{"cell_type":"markdown","source":"# ✂️ Remove Files","metadata":{}},{"cell_type":"code","source":"!rm -r {GAN_TRAINING_PATH}\n!rm -r {RAW_BBOX_PATH}","metadata":{"execution":{"iopub.status.busy":"2022-02-03T17:55:30.579831Z","iopub.execute_input":"2022-02-03T17:55:30.580214Z","iopub.status.idle":"2022-02-03T17:55:32.49622Z","shell.execute_reply.started":"2022-02-03T17:55:30.580175Z","shell.execute_reply":"2022-02-03T17:55:32.495001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}