TubeSum

GANs for Image Generation — Step-by-Step Guide & Transcript

Image Generation using GANs | Deep Learning with PyTorch: Zero to GANs | Part 6 of 6

2h 29m video Published Jan 2, 2021 Transcribed Aug 10, 2026 F freeCodeCamp.org
Intermediate 15 min read For: Learners with basic Python and deep learning knowledge who want to understand GANs and transfer learning.
AI Trust Score 75/100
⚠️ Average / Some Fluff

"Delivers exactly what the title promises — a comprehensive lesson on image generation with GANs, with practical examples and clear explanations."

AI Summary

This lesson, part of the 'Zero to GANs' course, introduces generative adversarial networks (GANs) for image generation. The instructor demonstrates how to build and train a GAN to generate anime faces, explains the underlying concepts of generator and discriminator networks, and covers transfer learning as a powerful technique for image classification.

[00:08]
Course Introduction

Lesson 6 of the 'Zero to GANs' course, focusing on generative adversarial networks (GANs). The course is a collaboration between freeCodeCamp and Jovian.

[00:37]
GANs Overview

GANs can generate high-quality images from random noise, such as handwritten digits and anime faces. The same model architecture can be used for different datasets.

[04:11]
Setting up the Environment

The lesson uses Google Colab with a GPU runtime. Instructions are provided for enabling GPU on Colab, Kaggle, and local machines with NVIDIA GPUs.

[05:22]
Generative Modeling vs. Supervised Learning

GANs are used for generative modeling, an unsupervised learning task, unlike classification and regression which are supervised. The model learns patterns in data to generate new examples.

[06:33]
Real-World GAN Example

The website 'thispersondoesnotexist.com' uses a GAN to generate realistic human faces on every page load.

[08:00]
GAN Architecture

A GAN consists of two neural networks: a generator that creates images from random vectors, and a discriminator that distinguishes between real and generated images.

[09:47]
Training Process

The generator and discriminator are trained in tandem. The discriminator is trained to differentiate real from fake, then the generator is trained to fool the discriminator, repeating this cycle.

[12:14]
Challenges in Training GANs

Training GANs is notoriously difficult due to the delicate balance between the generator and discriminator. They are sensitive to hyperparameters, activation functions, and regularization.

[13:10]
Dataset: Anime Faces

The tutorial uses the 'anime face dataset' from Kaggle, containing about 63,000 cropped images of anime faces.

[14:36]
Downloading Data with opendatasets

The `opendatasets` library is used to download Kaggle datasets. It requires Kaggle API credentials, which can be provided by uploading a `kaggle.json` file.

[19:23]
Data Loading and Preprocessing

Images are resized and center-cropped to 64x64 pixels and normalized to the range [-1, 1] using a mean and standard deviation of 0.5.

[26:44]
GPU Utilities

Functions are defined to get the default device (GPU if available), move data/models to the device, and create a device data loader that automatically transfers batches to the GPU.

[29:36]
Discriminator Model

The discriminator is a convolutional neural network that takes an image and outputs a single number (probability of being real). It uses Leaky ReLU activation and batch normalization.

[40:30]
Generator Model

The generator takes a random latent vector (size 128) and uses transposed convolutions to generate an image. It uses ReLU activation and a Tanh activation at the output to produce pixel values in [-1, 1].

[52:15]
Training the Discriminator

The discriminator is trained using binary cross-entropy loss. It is trained on real images (target=1) and fake images (target=0).

[58:11]
Training the Generator

The generator is trained by passing generated images through the discriminator and setting the target to 1 (fooling the discriminator). The discriminator is kept fixed during this step.

[01:02:36]
Visualizing Training Progress

Sample images are saved after each epoch to visually inspect the generator's progress. A fixed set of latent vectors is used for consistent comparison.

[01:06:47]
Training Loop

The `fit` function trains the GAN for a specified number of epochs. It uses the Adam optimizer with betas (0.5, 0.999) and logs losses and scores.

[01:13:07]
Training Results

After 10 epochs, the generator produces recognizable anime faces. After 25 epochs, the images are nearly indistinguishable from real ones.

[01:17:11]
Creating a Training Video

OpenCV can be used to combine the saved sample images into a video to visualize the training process.

[01:22:02]
MNIST GAN

The same GAN approach can be applied to generate handwritten digits using the MNIST dataset, with simpler linear layers instead of convolutions.

[01:23:39]
Transfer Learning Introduction

Transfer learning uses pre-trained models (e.g., ResNet34 trained on ImageNet) to solve new problems with less data and time.

[01:27:32]
How Transfer Learning Works

A pre-trained model's convolutional layers have learned hierarchical features (edges, shapes, objects). These features can be reused, and only the final classifier layer is replaced and trained.

[01:28:54]
Oxford Pets Dataset

The tutorial uses the Oxford-IIIT Pets dataset with 37 categories and about 200 images per class.

[01:35:05]
Custom Dataset Class

A custom dataset class is created by extending `torch.utils.data.Dataset`, implementing `__init__`, `__len__`, and `__getitem__`.

[01:39:18]
Data Transforms

Images are resized to 224x224, padded, randomly cropped, converted to tensors, and normalized using ImageNet statistics.

[01:47:14]
Building the Model with Transfer Learning

A `PetsModel` class is defined that loads a pre-trained ResNet34 and replaces the final fully connected layer with a new one for 37 classes.

[01:58:30]
Training with Pre-trained Weights

The model with pre-trained weights achieves ~80% accuracy in under 3 minutes, while the model without pre-trained weights only reaches ~24% accuracy.

[02:04:27]
Next Steps and Course Project

The instructor provides guidance on the course project, including finding datasets, defining models, training, and evaluating. He emphasizes using transfer learning for real-world projects.

[02:14:22]
Course Recap

The instructor recaps the entire course, covering tensors, gradient descent, linear regression, logistic regression, feed-forward networks, CNNs, regularization, and GANs.

This lesson provides a comprehensive introduction to GANs, demonstrating how to build and train a model to generate anime faces. It also highlights the power of transfer learning for image classification, achieving high accuracy with minimal training time.

Mentioned in this Video

Tutorial Checklist

1 02:17 Open the notebook on Google Colab by clicking 'Run' and selecting 'Run on Colab'.
2 02:49 Change runtime type to GPU: Click 'Runtime' > 'Change runtime type' > Select 'GPU'.
3 03:31 Run the first cell to install the Jovian library and connect the notebook.
4 14:36 Download the anime face dataset from Kaggle using the `opendatasets` library.
5 19:23 Load the dataset using `ImageFolder` and apply transforms: resize to 64x64, center crop, convert to tensor, and normalize to [-1, 1].
6 26:44 Define GPU utilities: `get_default_device`, `to_device`, and `DeviceDataLoader`.
7 29:36 Define the discriminator model using `nn.Sequential` with Conv2D, BatchNorm, LeakyReLU, and a final Conv2D to output a single number.
8 40:30 Define the generator model using `nn.Sequential` with ConvTranspose2D, BatchNorm, ReLU, and a final ConvTranspose2D with Tanh activation.
9 52:15 Implement the `train_discriminator` function: pass real and fake images, compute binary cross-entropy loss, and update discriminator weights.
10 58:11 Implement the `train_generator` function: generate fake images, pass through discriminator, set target to 1, compute loss, and update generator weights.
11 01:02:36 Create a function to save sample images after each epoch for visual inspection.
12 01:06:47 Define the `fit` function to train the GAN for a specified number of epochs, logging losses and scores.
13 01:13:07 Train the model with a learning rate of 0.0002 for 10 epochs.
14 01:17:11 Use OpenCV to combine saved images into a training video.
15 01:23:39 For transfer learning, download the Oxford Pets dataset and create a custom dataset class.
16 01:47:14 Load a pre-trained ResNet34 model and replace the final fully connected layer with a new one for 37 classes.
17 01:58:30 Train the model using the `fit_one_cycle` function with a learning rate of 0.01 for 6 epochs.

Study Flashcards (15)

What is the purpose of a generator in a GAN?

easy Click to reveal answer

To generate new images from random noise that look like they were drawn from the original dataset.

08:41

What is the role of the discriminator in a GAN?

easy Click to reveal answer

To differentiate between real images (from the dataset) and fake images (generated by the generator).

09:07

What is the training process for a GAN?

medium Click to reveal answer

Train the discriminator to distinguish real from fake, then train the generator to fool the discriminator, repeating this cycle.

09:47

Why is training GANs considered difficult?

medium Click to reveal answer

Because of the delicate balance between the generator and discriminator; if one gets too good, the other cannot improve.

12:14

What is the size of the anime face dataset used in the tutorial?

easy Click to reveal answer

About 63,000 cropped images.

13:10

What normalization is applied to the images before training?

medium Click to reveal answer

Pixel values are normalized to the range [-1, 1] using a mean and standard deviation of 0.5.

20:07

What activation function is used in the discriminator and why?

medium Click to reveal answer

Leaky ReLU, to allow a small gradient flow for negative values, preventing information loss.

37:21

What is the output shape of the generator?

easy Click to reveal answer

3x64x64 (an image with 3 channels and 64x64 pixels).

47:59

What is the purpose of the Tanh activation in the generator's output layer?

medium Click to reveal answer

To scale the output values to the range [-1, 1], matching the normalized real images.

48:17

What loss function is used for the discriminator?

easy Click to reveal answer

Binary cross-entropy loss.

52:29

What is the key trick in training the generator?

medium Click to reveal answer

Using the discriminator as part of the loss function, setting the target to 1 for generated images to fool the discriminator.

58:25

What is transfer learning?

easy Click to reveal answer

Using a pre-trained model (e.g., on ImageNet) and reusing its learned features for a new task, often by replacing the final layer.

01:27:32

What is the Oxford Pets dataset?

easy Click to reveal answer

A dataset with 37 categories of cat and dog breeds, with about 200 images per class.

01:28:54

What accuracy was achieved with transfer learning on the Oxford Pets dataset?

medium Click to reveal answer

About 80% accuracy in under 3 minutes.

02:01:05

What is the main advantage of using pre-trained models?

medium Click to reveal answer

They provide a head start by leveraging features learned from large datasets, leading to faster training and better performance.

02:03:39

💡 Key Takeaways

💡

Generative Modeling vs. Supervised Learning

Clarifies the fundamental difference between GANs and traditional classification/regression models.

05:22
🔧

The Adversarial Training Loop

Explains the core mechanism of GANs: the generator and discriminator improve each other through competition.

09:47
💡

Challenges in GAN Training

Highlights the practical difficulties of training GANs, which is crucial for setting expectations.

12:14
🔧

Leaky ReLU in Discriminator

Shows a specific architectural choice that improves GAN training stability.

37:21
⚖️

Transfer Learning Concept

Demonstrates how pre-trained models can be reused for new tasks, saving time and resources.

01:27:32
📊

Transfer Learning Performance

Provides concrete evidence of the power of transfer learning: 80% vs 24% accuracy.

02:03:39

[00:08] pyo zero to Gans this is an online certification course being organized in collaboration by free code camp and Jovian today we are on lesson six deep learning with pyo 02 Gans and the topic is generative adversarial networks or

[00:23] is generative adversarial networks or Gans my name is Akash and I'm your instructor so over 5 weeks we have been learning various Concepts in deep them all together to train a generative adversarial Network or Gan which can go

[00:37] from producing random images like a random noise like this to producing high quality images of handwritten digits and Anime faces and what's more interesting is that the exact same kind of model will be used to produce both of these

[00:51] images and the only thing that will differ is the data set the models are on now if you have been following along then by completing the three weekly assignments and a course project on the course page and submitting them on the

[01:06] certificate of accomplishment for this course so please visit the course page and let's get started so the course page is zero.com and on this page you can enroll for the course and you can also view the

[01:21] previous lessons lessons 1 through 5 and the previous assignments assignment 1 2 3 and the course project but today we looking at generative adversarial networks and we are also going to cover an additional topic called transfer

[01:34] learning towards the end so let's get started now on the lesson page you will be able to watch a recording and you can catch a Hindi version here as well and the first notebook we are going to use today is called generating anime

[01:49] faces using Gans so let's open it up this is a Jupiter notebook hosted on up this is a Jupiter notebook hosted on the Jovian doai platform and you can see here this notebook has some explanations and below here it also has some code and

[02:05] to run this code you have two options you can run it using free online resources which we have been doing so far or you can run it on your computer locally and you can follow the instructions here we will be using

[02:17] Google collab so I'm going to scroll up here click on the Run button and click run on collab now I click authorize and run on collab this may ask you to connect your Google Drive so that this notebook which was in a read only mode

[02:30] on Jovian can be put onto your Google Drive and executed on Google collab an online platform for running jupyter notebooks and now we can see here we have the same Jupiter notebook except this time it's on Google

[02:49] will run on Google servers where they have given you some free gpus with a have given you some free gpus with a limited will do is click on the runtime button and select change runtime type and then

[03:03] from the change runtime type you want to definitely select GPU now if you have subscribed to collab Pro you can also pick a high Ram machine and when you subscribe to collab

[03:17] Pro you also get Priority Access to higher more powerful gpus so let's do that so now we have selected GPU as our runtime

[03:31] and we can start executing our code so the first thing we need to do is run the first cell which is going to install the Jovian library and connect this collab notebook with the Jovian notebook that we just executed this is

[03:43] so that when we want to capture a snapshot of this jupyter notebook we can do that easily using the Jovian Library so always run this first cell whenever you run a notebook from collab from Jovian onto collab now when you do

[03:58] run the first cell it initializes the runtime which means it connects to the server on Google's infrastructure where all of this code will be executed so today's topic is training generative adversarial networks or Gans

[04:11] in pyo and we've been building towards this step by step and you can see the previous notebooks in the series here we've already seen how to run the code now we we've also seen how to use a GPU which was to go into runtime and change

[04:25] runtime type and select GPU on Google collab but if you're not using Google collab on other platforms you have the option of gpus as well so on kaggle notebooks you have a sidebar from where you can select an enable a GPU now if

[04:39] you have a Linux or a Windows laptop with an Nvidia graphics card installed then you can install the Nvidia Cuda drivers so Cuda is the language used to communicate with GPU so you need to install the Nvidia Cuda drivers and then

[04:52] you need to install the version of pytorch compatible with gpus and then you will be able to use a GPU on Linux and windows on binder and Mac OS you will not be able to use gpus so the models that we train here will

[05:07] take a lot longer to train without gpus but that said you can still run all of but that said you can still run all of this code without a modeling so far we have been using deep neural networks for something called

[05:22] supervised learning which is image classification or classification in ification involves telling which category a particular sample and input belongs to and regression involves predicting a

[05:37] continuous number from an input however generative adversarial networks or Gans as we call them use neural networks for a very different purpose and that is called generative modeling which is an unsupervised

[05:51] learning task so there are no labels or targets and it involves automatically discovering and learning the regularities or patterns in input data in such a way that the model can be used to generate or output new examples that

[06:05] could have been drawn from the original data set so what that means is if you're given a data set of human faces you can then train a model you can train a gan

[06:17] which can learn to generate new human faces which look like they may have been picked from that data set so for instance there are many different there are many different data sets containing human faces online and

[06:33] one of the gas that has been trained on human faces produces images like this high quality images of human faces and in fact you can visit this site this person does not exist.com and this site is connected to a generative adversarial

[06:46] Network running on the cloud and every time you reload this page it makes a request with a random input to that model and that model generates this high quality image of a human face and and this person does not exist so this image

[07:01] has been generated right here right now this very second each time you're getting a new image out of this and you can see that there are so many details it's a very detailed image of a face you can see there is teeth hair and even

[07:13] accessories like glasses and you can even see that there are backgrounds and there are people around as well in a lot of cases now if you wish you can go and check the source code of this so this is a generative adversary Network so you

[07:28] some some explainer videos here as well but we will today be learning something very similar to this so we will not be generating human faces that requires training a model for probably a few days to maybe a few weeks on a really large

[07:43] data set we will do something slightly easier which is generating anime faces so if you watched any anime or cartoons we will generate anime faces using the same technique that has been used here now there are many approaches for

[08:00] generative modeling in general but what is called a gan a generative aders network is something that takes this particular approach towards generative modeling so we have two models here normally so far we have seen that there

[08:15] input to the model and it gives a prediction We compare the predictions gradient descent and that trains the model and then we can use the model for making inferences that is what we have learned so far in the last five weeks

[08:29] that is typically how a classification or regession model works now a different models so two different neural networks there is a generator Network and there is a discriminator network now

[08:41] and there is a discriminator network now the generator Network the input to it is some random input some random Vector so you feed in a random Vector into the generator Network and it generates an image or it at least tries to generate

[08:55] an image so you give it an input and it generates an image if you give it a different input it generates a different image and this is the model that we really want to train we want to make this model better and better at

[09:07] generating images which look like they may have been drawn from a particular data set and to do that we use a second Network called a discriminator so the Network called a discriminator so the discriminator is a model its only job is

[09:21] to be able to differentiate between real images which is images between real images which is images drawn from the actual data set

[09:34] generated by the generator so the discriminator is uh responsible for taking real images and uh generated images and discriminating between them telling which one is which so now we have these two models and the way the

[09:47] interesting it's a very elegant trick that is used to train Gans because there is no real targets here so how do you really make the generator better and the the way to do that is

[10:00] so what we do is we take the discriminator we put in some a batch of real images let's say 128 real images into the discriminator and then we put in a batch of fake images or 128 generated images from the discriminator

[10:15] and then we train the discriminator so we use gradient descent because we know that for real examples the discriminator should predict real and for fake predict fake so we use that fact to train the discriminator so that the the

[10:29] discriminator after training gets good at differentiating between real and generated images then once we have trained the discriminator just a little trained the discriminator just a little bit we then use the discriminator as a

[10:42] part of the loss function of the generator so what we do is we take a generated image from U we take some generated image from the generator we pass them through the discriminator and we try to fool the discriminator so we

[10:55] we try to fool the discriminator so we try to then update the model update the generator model train the generator model so that the generated images get fool the discriminator and we'll see this in a lot more detail but I just

[11:08] want you to capture the intuition here that first we train the discriminator to be able to differentiate between really bad generated images and actual images from the data set then keeping the discriminator fixed we train the

[11:23] generator to produce slightly better images that can fool the discriminator then we train the discriminator once again it can get better at differentiating the slightly better fake images versus real images and then we

[11:37] generator now generates even better images and that is a cycle that we repeat over and over and over batch by batch epok by Epoch and at the end of that process you end up with a generator model which can generate images like

[11:52] model which can generate images like this so This that is why this approach Network because the generat Ator and discriminator are like adversaries the discriminator the discriminator tries to catch the generator's

[12:14] that's what we are going to talk about today but Gans can be notoriously that there is a subtle interplay between the discriminator and the generator if one gets too good then it is no longer an even match between the two so that's

[12:28] where it is training Gans is hard and they are extremely sensitive to hyperparameters activation functions and regularization so in this tutorial we will train a again to generate images of Anime

[12:43] characters faces so by the end of the tutorial we will be able to generate images which look somewhat like this you can see that these are not high quality images of anime faces these are slightly lower in in resolution and you can also

[12:57] they're not perfect but they're getting pretty pretty close and we'll see how to do that and parameters and activations and regularization we will make some very

[13:10] interesting choices which I will talk about uh which you may not have seen so is called the anime faces data set it consist of about 63,000 cropped images

[13:26] consist of about 63,000 cropped images of anime faces unsupervised learning task these images will not have any labels so we we're just going to work with images of anime

[13:41] faces so let's just uh run through a couple of things here we are going to set a project name in a project name variable we will use this later for capturing snapshots and sending our notebook to Jovian we'll see and if you

[13:53] are running this on a platform where you do not have access to a GPU then you may want to where you do not have all the libraries installed then you may want to install the required libraries here if you do not have access to a GPU you can

[14:06] use this CPU versions of pytorch if you have access to a GPU you can use the GPU versions of pytorch on Google collab however none of these are required because all the libraries are already installed so whichever one you need to

[14:19] run just uncomment the the exact line and run it and you will be able to and run it and you will be able to install the do is get the data set and we're going to get the data set from kaggle so if we

[14:36] click this link you can see here that on kaggle this particular user has created this anime faces data set um it has been scraped from this website get you.com and you can see here on on the data tab you will be able to see that

[14:51] present here you can browse them as well there seem to be about 63,000 over 63,000 faces how do we get this into Google collab now now to get a kaggle data set not just this one but any kaggle data set

[15:06] called open data sets so you can see this here it's a sets so you can see this here it's a open source Library developed by Jovian and the open data sets Library provides a helpful function called

[15:20] download so you can just use this function open data sets or OD it's imported often as OD od. download and pass the URL to a kaggle data set so for instance we can take this data set and then pass it to

[15:34] open data sets. download and it will be able to download the data set into Google collab or wherever you're running your jupyter notebook so this is a Library definitely use it in your projects whenever you're working with

[15:47] projects whenever you're working with kaggle and do give it a star as well now there's one other step involved here because open data sets uses the kaggle official API so you need to provide access to your

[16:01] kaggle account you need to capture you need to provide some API credentials so that open data sets can get this data from your kaggle account and the way to from your kaggle account and the way to do that is to go to kaggle.com

[16:16] now on kaggle.com you can then click on your profile and go to the account page so this is on the sidebar you click on account and then on the account page you will see a option here called API

[16:30] there's a section API and you click on create new API token so when you click the button create new API token it is going to download a file called kaggle

[16:46] token which will be used to access your kaggle account from anywhere so the kagle Json file will look something like this I'm not going to open my file here because I don't want to show you the secret key on video

[17:02] so here we have the kagle Json file it will have a username key where the this which will contain your kagle username and it will have a key or the token and that key value will be here it will be a long

[17:16] string now when you run open data sets. download you will be asked to enter your username and enter your kaggle key and you can get them from this kagle Json file and you can paste them so let's see how that works

[17:32] sets Library using pip and then we are importing open data sets as OD and using importing open data sets as OD and using the data set URL that we have set here passing it to od. download so here it's going to ask me

[17:47] for my kagle username and I can enter my kagle username and it is also going to ask me for my kagle key once again I can get that from the kagle Json file now you can enter your kagle key here here but there is one other way to use open

[18:01] data sets which is a little bit easier so I'm just going to stop this cancel this operation here and open the files tab and on the files tab I'm going to click the upload button and I have already downloaded my

[18:15] kagle Json file so I'll simply upload the k. Json the k. Json file into the files tab so now the kagle Json file is available to collab and open data sets can

[18:28] automatically pick pick it up so if we run open data sets. download with the read the kaggle credentials and you can see that it is now downloading the

[18:41] data so the data will get downloaded in a folder which has the same name as the URL portion of the data set indicating that specific data set so let's see here it is not only downloaded but it is also unzipped for

[18:54] you as well so now you can see this folder anime data set anime face data set there is a single folder called images which contains all 63,000 images in jpeg format so if you open this you can see here that there is a

[19:09] this you can see here that there is a big list of images images look like each one is a JPEG image and there are no labels there are

[19:23] no classes so that's why there is a single folder called image so now let's load this data set using the image folder class from torch

[19:40] vision and we will also resize and crop the images to 64 pixels x 64 pixels that will make it a slightly easier for us to work with generating very large images using Gans will often require a lot of training and a much bigger model than we

[19:53] can create here so we will work with 64 pixels x 64 pixels another thing that we're going to do is we're going to normalize the pixel values and if you remember our discussion from C 10 what we did there was we calculated the mean

[20:07] and standard deviation for each of the channels red green and blue and then we used those means to normalize the pixel values this time though we are not going something much simpler we're going to pick a a mean of 05 and a standard

[20:23] deviation of 0.5 as well and here the purpose is not really to normalize pixels across channels but the purpose is to take the pixels which are which have values pixel intensities in the range 0 to 1 and translate them into a

[20:37] range minus one to 1 now this is one of those eccentric things that we do while training Gans it is more convenient for training the discriminator when the pixel values are in the range of minus 1 to 1 which is if there if they are

[20:50] symmetrically distributed around zero rather than being in the range 0 to 1 and we will see this come up again when we generate images from the generator okay so think about that this normalization is not really to change

[21:04] the effects of different channels this is simply to move the pixel intensities from the 01 range to the minus one one range so we import data loader image folder and transforms then we create this we set the image size to 64 we

[21:18] going to use a batch size of 128 for creating our data loader and then we're going to use the means of 0.5 and standard deviations of 0.5 for normalizing the data so here we are creating the image folder with the

[21:31] data directory and then we passing the transform since we are going to have more than one transform we need t. compose and T refers to torch Vision bunch of transforms which means we're going to apply them one after the other

[21:44] the first thing we do is apply t. resize and that is going to resize every face image into 64 pixels by 64 pixels then we are going to take a center crop because it's possible some of these images may be rectangular a center crop

[21:58] is going to pick the Central Square crop out of it the 64x 64 crop then we're going to convert them into tensors so now we end up with image tensors and finally we're going to normalize them using these

[22:11] stats so that the values within the tensors go from the 01 range to the minus one one range so that's our train data set and then here is our training data loader so we have the training data set and then we pass the batch size we

[22:23] also pass shuffle through then this is because each time we want to generate batches from the training data set in each Epoch we want to use the images in a different order and that just helps the randomization helps train and

[22:37] generalize the model faster now we're also going to set num this is simply going to ensure that we use multiple course from our machine to

[22:49] use multiple course from our machine to read the and we have a data set as well so let's create some helper functions to display some sample images from a training batch now here we are going to

[23:05] import P torch and we're going to use the torch Vision utility function make grid and we also going to use PLT uh matplot li. P plot to plot the images so

[23:17] first we're going to define a function dor now remember for training a model we are going to use these image tensors which have been normalized with pixel values in the minus one to one range but to view these images we will have to

[23:29] bring them back into the 01 range so that is what this dor function does it takes the image tensor multiplies it with the standard deviation of 0.5 and adds the mean and that's just going to denormalize it bring it back into the 01

[23:43] range and now we can define a couple of helper functions show images and show batch so show images simply takes a bunch of image tensors and then it a maximum number of images that it should show and it simply plots them so it

[23:58] plots them in a grid like this and then the show batch function takes a data loader and gets a batch of images from the data loader M simply shows the the data loader M simply shows the images so let's look at a batch of

[24:12] data so here is a batch from the training data loader when we call show batch we fetch a batch from the data loader and then we break out but before breaking out we show the images and inside show images we are going to

[24:25] denormalize the images so we are going to take the images and change the pixel values back to 0 to 1 and then we are also going to convert that into a grid here so using the make grid function in torch vision and finally to show it

[24:38] using matte plot lip we need to just flip the dimensions around a little bit and that is why we have this permute function remember in pytorch images have the color channels in the First Dimension whereas matte plot lib

[24:53] requires the color channels to be in the last Dimension and that's why we have now if the show images function does not make sense then that would be it would be a good idea to go back and revise chapters 4 or

[25:07] five we've covered this in a lot more detail there but the idea here is to take a bunch of images and display them in a grid like this so this is our training data you can see that we have many different kinds of faces here you

[25:20] have faces looking forward you have faces looking to the side you have many different hairstyles as well many different hair colors sometimes you have colors of eyes you have male you have female you have both kinds of data you

[25:35] have different Expressions you also have accessories so this is a accessories so this is a fairly a Vari data set it has many different variations even though it is just Anime faces and it's still a

[25:48] challenging data set to work with so let's see how we can train a generator to produce images and let's see how close we can get to these real images in the time that we have today so before we continue I'm just going to

[26:01] install the Jovian library and then create a snapshot now remember that this notebook is running on Google collab and that can shut down anytime so I'm just going to my Jovian profile grabbing my API Key by clicking on the API key

[26:16] button and when I run Jovian docit and provide my API key the Jovian Library captures a snapshot of this notebook and puts it on my Jovian profile so that I can run it later even after this Google collab notebook has shut down okay so

[26:31] always remember to record snapshots of your we Define our models let's just create some utilities for working with gpus

[26:44] once again we've covered these in a lot of detail in the previous lessons so we just see what these functions are and how we'll use them so the first thing is the get default device function now it's always a a good idea to write your code

[26:59] in such a way that it can work with a GPU if one is available otherwise it should use the CPU and that's where we're going to use this get default device function it checks whether a GPU is available using torch. ca. is

[27:11] available and for this to return true three things should hold true the server or the compute or the computer where you're running this code the execution environment should be connected to the hardware which is an Nvidia GPU or

[27:26] graphics card then you should have the Cuda drivers so Cuda is the language used to communicate with GPU so you should have the Cuda drivers installed and third you should have the py to version compatible with gpus so if you

[27:39] have all these three things which are already ensured in collab but you may running this on your computer if you have all these three things then you will get back then we are returning TS short device Cuda which is going to be a

[27:52] pointer to a GPU similarly otherwise if you do not have these if you do not have GPU available then we're going to return to short device CPU and get default device is automatically going to pick a

[28:04] GPU or a CPU based on whichever is available now that's one the second is a two device function so the two device function can take some data or some or a model and then move it onto a given Target

[28:17] device and finally we have this device data loader class so we have data loaders for training and there's no validation data loader here there's just data loader is used with within a for Loop now the device data loader can be

[28:30] used to wrap the training data loader so that whenever a batch is pulled out in a for Loop that batch is immediately moved to the device just in time just before being used so these are the three GPU related

[28:43] utilities that we have so first let's get the default device now if you have everything set up properly and you have a GPU you should see device type Cuda here if you do not see device type Cuda that means you're using a CPU on collab

[28:56] you may want to go and change the Run time type if you see CPU here not just right now but whenever you are working with a deep learning project and we can now move our training data to the data we can now wrap our

[29:10] training data using device data loader so that it automatically transfers batches of data to the GPU when we access them so here we have converted the training data loader into a device data loader by passing the original data

[29:23] loader and the target device which is a GPU the first model that we will Define is the discriminator because it is somewhat

[29:36] easier to understand the discriminator takes an image as an input and it tries to classify that image as a real image or a generated image in this sense it's like any other neural network we've trained so

[29:53] far and we'll use a convolutional neural network which outputs a single number for each image so we give it an image which is a three Channel by 64x 64 image

[30:05] and for that image the discriminator returns a single number as an output and then we will interpret this number as the probability that the discriminator thinks that this this image was drawn from the actual data set

[30:21] right so if the discriminator outputs zero then it is predicting that the and if the discriminator output something close to one like 0.9 then it is 90% sure that the image was picked from the actual data set so that's a

[30:36] pretty straightforward uh classification problem and this kind of classification problem and this kind of classification is often called a binary classification which we've done so far where we had maybe let's say 10

[30:52] categories or 10 digits or 10 categories of everyday objects this is much simpler where there is just one output which is whether the image is real or whether the image is real or not so let's define the

[31:08] convolutional neural network we do not need to extend any classes here we simply going to use the nn. sequential class so we use nn. sequential and into nn. sequential we pass a set of layers and then we can use this discriminator

[31:23] model and when we pass in some input it can go through the layers one by one and come out from the other side so let's look at the layers here so here first of all we're going to start out with an input image of size 3x 64x 64 and of

[31:36] course it's going to be a batch of images not just a single image but we have not added the batch Dimension here because we never affect the the model never really affects the batch dimension for each image in the batch it gives an

[31:49] output of the shape that we'll see so first of all we have a convolutional layer so here we have a con 2D layer and this goes from channels three input channels to 64 output channels and it uses a kernel size of four and a stride

[32:03] of two so this is something interesting that we had not seen earlier we have seen kernel sizes of three and we have seen stride of two or we've seen stride of one so far and normally after a convolutional

[32:16] layer we also have a Max pooling layer so the convolutional layer retains the so the convolutional layer retains the size of the input so if you have a 64x 64 input being passed in then the output is also 64x 64 however when you use a

[32:30] stride of two then the convolution is going to [Music] skip ahead so it's going to use every second pixel to place the kernel so for example the kernel is first placed here

[32:43] is placed here you can see that it is skipping one pixel both in the horizontal and the vertical Direction and that is why the image size reduces to half the output size is half and then the kernel size of four is

[32:56] simply to make sure that we are covering all the pixels properly so this is the part that I will leave for you as an exercise you can see this image here where you have this 6x6 image and it has a padding of one

[33:11] pixel around it and then we passing a kernel of size 3x3 now instead of a 3X3 suppose this was a 4x4 kernel just try and draw it out on paper and see just make sure that it will still be a 3X3 output when you have a stride of two

[33:26] okay so that's what we do here kernel size of four stride of two and we will do that throughout and the output from this after that we have the batch normalization layer and then we have an

[33:39] activation function so the output is going to be 64 channels we go from three channels to 64 channels and then the size of the image the height and width they become half because of the stride of two so that becomes a 32

[33:52] pixel x 32 pixel feature map and then we repeat that process so we go from 3x 64x 64 to 64x 32x 32 and then then we go from 128 by 16 by 16 so we double the channels but we half the

[34:08] height and width using the stride of two once again we go 256 by 8X 8 512x 4X 4 and then the final convolutional layer has zero padding so since we have a 4x4

[34:23] image and on the 4x4 image if you do not have any padding and you using a kernel of size 4 that is going to fit exactly onto the image into exactly one position so the 4x4 image is going to get reduced to a one by one feature map and then

[34:38] another thing that we're doing is we're going from 512 channels to one channel going from 512 channels to one channel so ultimately we take the entire output we take the image which started out as a 3X 64x 64 feature map and then

[34:52] we increase it to a 512x 4x4 feature map But ultimately we reduce it down to a single number using a smart convolutional layer which has a kernel size of four and zero padding okay so

[35:05] you should try and spend some time on just convince yourself that these will be the output sizes take pen and paper try to create each layer separately and then pass try to

[35:18] pass the input of one layer try to pass the image as an input to the first layer input to the second layer that's a good thing about jupyter notebook you can just add more cells you can create these layers layer one layer two layer three

[35:32] and so on and then you can pass an sample image or maybe a batch of images through each of the layers one by one and observe the shapes okay so do spend some time here and it's really it's really important to cultivate the

[35:44] intuition for being able to tell what the output is going to be from a thing for us here is that the image has been reduced to a single number A 1 by one by one tensor and then we we going to

[35:58] flatten it out into a single ve into a single Vector a vector of size one instead of a 1 by 1 by one tensor and finally we're going to apply the sigmoid function so the sigmoid function let's see the graph of the

[36:12] sigmoid function here so this is a sigmoid function this here so this is a sigmoid function this is its formula its formula is 1 + e to the- X so what it does is it takes numbers and it reduces them it squishes

[36:25] them down into a 0 to one range so if you have a large positive number then that is going to come close to one and any positive number is going to then end up in the range point5 to 1 and if you have a large negative number or any

[36:38] negative number that will end up in the range 0 to.5 so that's a sigmoid function because we want to interpret the output of the discriminator which is a single number per image we want to interpret it as a

[36:52] probability and the probability that the image passed was a image drawn from the actual data set the probability that it is a real image and not a generated image and that is why we use sigmoid here and this is how binary

[37:07] classification is different from multiclass classification so when we had 10 classes we used soft Max but when you have a single class you simply use sigmoid now there is one other important detail here and this is about the

[37:21] activation function now so far we have been using the rectified linear unit this is what you may have seen seen in many different models that we have trained or elsewhere we use a rectified linear unit function but here in the

[37:34] discriminator we use something called The Leaky Rel or leaky rectified linear unit activation function so first let's understand what it is so the Leaky reu is a very slight variation on the relu now you may know that the relu is a

[37:49] function which simply ignores negative values so if the input to the r function is -1 -2 -.1 the output is zero but the input if the input to the r function is something positive like 1 2 or three the output is the same number so at more

[38:04] than at greater than z r is the function yal X at less than z r is the function 0er leaky R is slightly different in the sense that it allows a small negative

[38:16] portion to pass through as well so greater at greater than zero it has the same function it has the same formula as Ru which is yal X but if it is less than zero the input then it has a function y ax and typically this a is a small

[38:29] number less than one and that is what is called a leaky value so we are using leaky value with the factor a of0 2 so whenever there are negative values they are going to get multiplied by 0 2 and why do we use it so this is once again

[38:45] one of those eccentric choices that we have to make for have to make for our model to train properly so this is the justification this is given in the in the paper that explains this uh

[39:00] model so what happens is because we use the discriminator as a part of the loss function to train the generator Ru would lead to a lot of outputs from the generator being lost so that's where leaky Ru allows the

[39:17] pass of a small gradient signal even for negative values so not just the positive negative values so not just the positive values but also the negative values and discriminator flow stronger into the generator so the idea here is the image

[39:30] is generated from the generator we want to make sure that once an image has been generated from the generator none of that information is lost when we are using a loss function to train the

[39:42] generator okay so instead of passing a zero slope it passes a small negative zero slope it passes a small negative gradient so think about that and one good way to just come up with the right justification here is to try replacing

[39:54] train the model with the exact same parameters and see if you get a better result or a worse result now if you get a worse result then think about it think about why leaky relu may be helping in the

[40:11] next we can move our model to the device so we simply going to call the two the discriminator and the device and it is going to move all the weights within is going to move all the weights within the discriminator onto the GPU

[40:30] this so now that brings us to our generator Network the input to the matrix of random numbers and this is called a latent tensor so because neural networks are deterministic you give them an input and comes out an output now

[40:45] from the generator we want to generate different random images of anime faces and to do that what we need to do is we need to give it random inputs so the need to give it random inputs so the generator will take a latent tensor

[40:57] which which will be of shape 128x 1 by 1 which is basically 128 random numbers so we will give the generator 128 random numbers or a batch of 128 random numbers

[41:14] numbers a 128 by 1X one tensor is then going to get converted into an image going to get converted into an image tensor of size 3x 28 by 28 okay so it into an image and when you give a different random tensor it will give you

[41:28] would be to change the weights of the generator so that each time you give a random tensor the image that comes out looks like an anime face drawn from the actual data set and that is what we will train the generator to do later but to

[41:42] train the generator to do later but to do this to go from 128x 1X 1 to the shape 3x 28x 28 we need to do something which is the reverse of a convolution right so typically in a convolution you would start out with an image and end up

[41:55] with a certain number of output outputs for instance for the cifar 10 data set we ended up with 10 outputs for the discriminator network here we ended up with one output and here it seems like we starting with 128 numbers and we want

[42:07] to end up with an image so to achieve this we will use something called the con transpose 2D layer from pyo which performs what is called a transposed transposed convolution is also called a deconvolution although there is a subtle

[42:22] check out this blog post that I've linked to here to learn more about it so we're at a point now where you have all the basic concepts in place and any different activation functions or different regularization techniques are

[42:39] things that you can learn about online through blog post by even reading papers reading tutorials reading books to fill in the gaps in your knowledge Because deep learning is such a fast evolving FEI that field that it is not possible

[42:53] to cover all of these Concepts in a single course and in fact even if even if one did all of them would become outdated pretty quickly but what we do have right now is we have a strong grasp of the understanding of

[43:07] the basics things like gradient descent things like um loss functions activation functions layers so at this point I will encourage you to pause the video at some point and go through and read the convolutional transpose 2D layer and see

[43:23] how it works but here is a brief intuition what we do is suppose you have a 3X3 image so you can see the blue the blue squares here represent the pixels of the image we take the 3X3 image and then we pad it so we pad it not just

[43:38] pixels so you can see that there is some padding here between the pixels and there is some padding around the pixels so we do this padding and then we take a 3X3 kernel and then we run it over this padded feature map and now you can see

[43:51] as we run the kernel we from a 3X3 image we go and create a 6x6 a 5x5 image in this case okay and now you can start doing a little bit of the math what happens if you use a kernel of size four what happens if you use a

[44:06] stride of two and so on but this is the basic idea behind a deconvolution or a con transpose dud layer and one other way to look back at this is imagine you were doing a convolution on the output then you would end up with the shape of

[44:21] the input okay so when you apply this reverse technique what kind of a a 3X3 feature map well you would probably have to start with something like a 5x5 output okay so keep that in mind uh it's

[44:38] the exact in terms of the feature map sizes it is the exact opposite of what a convolution does so let's define our generator now so now we have the latent generator now so now we have the latent size of 128 that we're going to use

[44:52] let's we've put that in here now the generator is also going to be be a sequential model and we're going to start out with latent size * 1 by 1 and see if that gives you slightly different results but the basic idea

[45:07] just one vector then you would have just one dimension of control for the generator so you can think of the different latent vectors as controlling different aspects of the generated image maybe the first latent Vector may end up

[45:21] the second latent Vector may end up Third latent Vector may end up controlling the third latent the third element of the latent Vector may end up controlling the shape of the mouth or

[45:34] may end up controlling which way the face is turning so the more I mean it's not exactly this but it's roughly this where some combination of latent vectors controls a specific attribute of the generated image once the generator has

[45:50] been trained so the more latent vectors you have the more variety you can get in your generated images typically something like 64 128 is good enough for simpler images for more detailed images like human faces you may want to use a

[46:03] much bigger latent size so now the generator takes a latent Vector which is of size 128x 128 128 x 1X 1 and of course this is going to be a batch of latent vectors not a batch of latent tensors not just a single latent

[46:18] tensor so it takes this latent tensor and then it uses a con 2D transpose so here you have a con 2D transpose we go from from the latent size number of channels so 128 channels to 512 channels and then we going using a kernel size of

[46:34] four and stride of one so together what these do is these take an image from 1ex these do is these take an image from 1ex one shape to a 4x4 shape and I'll let you work this out by looking into con transpose 2D and of course we have batch

[46:49] norm and then we have the normal relo activation function so for generator we do not need the Leaky Rue only for the discriminator then once again we have another con transpose 2D layer and this time we go

[47:02] transpose 2D layer and this time we go from 512 channels to 256 channels and once again the size of the feature map doubles with a kernel size of four and stride of two and padding of one so now we have 256x 8X 8 and then

[47:16] once again we repeat it and we end up with 128x 16x 16 we repeat that once again and then we end up with 64x 32x end up with 64x 32x 32 and finally we end with 3x 64x 64 so

[47:29] you can see we've first increased the channels to 512 and uh increase the feature Map size to 4x4 and then we double the feature Map size each time but we reduce the number of channels into half each time so at the end we end

[47:44] up with 64x 32x 32 and finally the final layer is going to take these 64 channels and output three channels so the end result of the convolution of the generator function is to take a latent tensor of shape 128x 1X 1 and convert it

[47:59] into a 3X 64x 64 image okay now there's one other interesting detail here you will notice that we have here An Tan H or a now what is that doing what that does is it the

[48:17] hyperbolic tangent function reduces values into the range minus1 to 1 so when a 3X 64x 64 feature map is generated from this convolution it can have values anywhere in the range from minus infinity to Infinity the tan the

[48:31] hyperbolic tangent function reduce them reduces them into the range minus 1 to 1 reduces them into the range minus 1 to 1 so the outputs of the

[48:43] have pixel values in the range minus 1 to 1 now if you recall when we created our data set you may remember that we applied a normalization which converts the real images from a from having a 0 to 1 range

[48:57] of pixel intensities to having them in the range minus 1 to 1 so now you see how it all fits together that images picked from the data set after normalization have pixel intensities in the range minus1 to 1 and they are of

[49:10] shape 3x 64x 64 and images generated from the generator after applying the hyperbolic tangent activation at the last layer will also have the shape 3x 64x 64 and have pixel values in the range minus1 to

[49:24] 1 so we have set up the generator in such a way way that it is going to images which at least have the same ranges of pixel intensities as the discriminator and then the next step will be to train

[49:38] the generator so that it's not only the ranges that match but even the pixels have such such values that when you pick put all the pixels together it looks put all the pixels together it looks like the image of an anime face okay but

[49:51] generator is able to generate images which fall whose values whose pixel in I ities fall within the same range minus 1 to

[50:08] function now we can try out our generator function we can see what kind of images it is generating simply by first generating some random latent first generating some random latent tensors so we create we use torch. randn

[50:20] which is going to create random tensors with values in the range minus one to 1 picked from a gsan distribution but random is the important part here Random tensors so we have a batch size of 128 so we have 128 and then we're

[50:37] going to create tensors of size latent size by 1 by one so here is the output so the fake so our XB or a batch of inputs to the tensor has a shape 128x 3x

[50:49] 64x 64 sorry it has a shape 128 by 128 by 128 by 1 1 by one so batch size is 128 and then the latent size is also 128

[51:01] then we pass them so let's print that out here xb. shape then we pass this batch of data into the generator and let's run the generator here

[51:15] the generator so that the generator converts each latent tensor into an image of shape 3x 64x 64 and then to show these images we can we had earlier so what we're going to do

[51:29] inside show images is we are going to take these fake images and take the pixel values and denormalize them from a minus one one range to a 0 to one range denormalizing when we put them into a grid this is what the images look like

[51:43] which is basically random noise and this is something that you might expect generator so far we have simply set it up so that it can generate these images so it's just generating random pixel values which looks like noise

[52:01] let's also move the generator to the device using the two device function so now we have our discriminator model and then we have a generator model as well and let's train them and first we will train the

[52:15] discriminator and then we will use the discriminator to train the generator now since the discriminator is a binary classification model which is it outputs a single number indicating whether the image is is real or not the probability

[52:29] we can use something called the binary cross entropy loss function the binary Cross entropy that is used for classification problems where there are multiple classes except here it's used for a single class so let's see how

[52:45] to train the model here is a function train discriminator it is going to use um it is going to we are going to give it a batch of real images so this is one be performed by this function so it's going to get a batch of real images as

[53:00] input and it is also going to get an Optimizer and this Optimizer is has been Optimizer and this Optimizer is has been set up to modify the parameters of the discriminator okay so first the first thing that we do is we clear all the

[53:14] gradients within the discriminator so we called optd do0 grad then we pass real images through the discriminator so here we take a batch of real images so this this will be drawn from the data set we'll see how this is used later on but

[53:27] we take the batch of real images and we pass them through the discriminator and then we get a set of predictions now obviously for each image you're going to get a single number so if you have a batch of 128 images you're

[53:39] going to end up with 128 numbers each of them are in the range of 0 to 1 but what we really want the discriminator to predict the target for the real images predict the target for the real images is one so it should be

[53:53] predicting one for each real images so so the probability that the image is are one and now we have predictions and we calculate the loss so now we can call the F do binary cross entropy function

[54:09] and we pass in the real predictions which are the predictions which are made by the discriminator on a set of real images and then we pass in the targets the targets are all one so that gives is the loss which we'll use for gradient

[54:22] descent apart from the loss as an evaluation metric just so that we can visualize we can tell how well the discriminator is doing we are also going to calculate the average prediction that the discriminator made for the batch of

[54:35] images so we're going to take a torch. mean of the real PRS and that is simply going to give us the average of all the predictions for the real images and we going to call that the real score so we want the discriminator real score to get

[54:47] as close to one as possible for it to become good at detecting real images so that's our one part of training the discriminator passing in a need to pass in a batch of fake images

[55:00] to tell the discriminator which images should be classified as fake so then we once again create a batch of latent tensors so here we use a random batch we use tor. randn and we pass in the batch size the latent size in 1 by one and

[55:13] that's going to create latent tensors a batch of latent tensors of size 128 by 1 by one then we're going to put the batch of latent tensors into the generator and end up with a batch of fake images remember as we did uh just here above

[55:28] we're going to end up with a batch of fake images 128x 3x 64x 64 so this has the exact same shape as a batch of real images but initially it is going to be random noise so we take all of these fake images and we know that for these

[55:42] fake images the targets should be zero because the discriminator should be predicting that the probability of these images being real is zero so the targets are zero and then the predictions for

[55:54] the fake images can be gotten by simply passing the fake images into the discriminator so we pass the fake images into the discriminator get some predictions and the targets we set them all to

[56:13] here so you can see that the real targets were torch. ons and here we were using torch. zos and now we can calculate the fake loss or the loss for fake images which is once again F do binary cross entropy pass in fake

[56:25] predictions and fake targets and we end up with the fake loss then we call torch. mean and then we call torch. mean on fake predictions that that also gives us the fake score so we want the score for fake images the average score to be

[56:39] as close to zero as possible so once again this is another evaluation metric that we will keep in mind and now the overall loss for the discriminator is the real loss obtained by passing a batch of real images and the fake loss

[56:52] obtained by passing a batch of fake images and then we call do backward Ward on the loss so remember when we call Dot backward on the loss that computes the gradient of the loss with respect to every single weight of the discriminator

[57:06] so now the gradients are computed and then we called optd do step so this is the discriminator optimizer we are calling do step to perform gradient descent here what this will do is this will modify the weights of the

[57:19] discriminator it's not going to touch the generator yet so it is going to modify the weights of the discriminator make them slightly better so that the discriminator gets slightly better at telling fake images from real

[57:32] telling fake images from real images in the next batch okay so that's our gradient descent we have trained our discriminator using one batch of images from the training set and one batch of fake images generated inside this

[57:44] function and now finally we simply going to return the loss and the real score tracking so that we can track the discriminator training

[57:56] discriminator now let's come to training the straightforward because at the ultimately it was a classification model and the only real subtle part there was using the generator to generate the

[58:11] input to the discriminator now training the generator is not that obvious because the outputs of the generator are images and this is where we employ a rather elegant trick which is to use the discriminator as a part of the loss

[58:25] function and this is how it works we generate a as we have done so we create some random latent tensors put them into the generator and we get back a batch of image tensors 3x 64x

[58:41] image tensors 3x 64x 64 now we pass those images into the discriminator and outome some predictions for each of those images the discriminator is going to make a prediction now the generator's purpose

[58:53] is to fool the discriminator so if we had the perfect generator and we were able to fool the discriminator then the all the discriminator then the all the predictions would be

[59:10] one so what we do is we calculate the loss by setting the target labels to generator's objective is to fool the discriminator then we use that loss to perform gradient descent that is to change the weights of the generator okay

[59:26] so we do not affect the discriminator we change the weights of the generator so that it gets better at generating real life images so what happens is you pass a batch of data get some images pass them through the discriminator set the

[59:40] targets to one and calculate the cross entropy loss then you perform gradient generator the next time the generator is going to generate some images for which the discriminator which has not been affected so for which the discriminator

[59:54] is going to predict something closer to to one so we train the generator to fool the discriminator by using the discriminator as a part of the loss okay so this is the rather elegant trick and think about this a few times why we are

[1:00:07] setting the target labels to one for generated images and if you can understand this you understand the basic idea behind Gans and this is how it looks like in code so in code it's actually really

[1:00:19] simple the train generator function simply takes the optimizer for the generator and first it clears the gradients so opt g.0 grad is going to all the gradients are wiped out and we can start fresh then it's going to

[1:00:35] we generate a batch of latent tensors using torch. randn you can see they have latent size by 1 by one is the shape they have and it's a whole batch then we take that latent tensors pass them into the generator and get back some fake

[1:00:50] images so now we have a batch of fake images now we pass those fake images into the discriminator and get some predictions and then we set the target predictions and then we set the target to one so Target is set to torch. On's

[1:01:02] and then we calculate the loss so this is the loss for the generator overall loss so the calculate the loss and this loss is once again F do binary cross loss is once again F do binary cross entropy where we pass in predictions and

[1:01:15] targets so here you can see that if we were to put all this logic inside this were to put all this logic inside this single line of code the discriminator is are using the discriminator as a function not as a neural network but as

[1:01:28] function not as a neural network but as a function to convert images into numbers and we want those numbers to be close as close to one as possible to close as close to one as possible to make the generator better now we call do

[1:01:41] backward on the loss function now that is going to calculate the derivatives of the gradients of the loss with respect to the parameters of the generator the weights and bias and then we call opt G so the generators Optimizer we call the

[1:01:53] do step function and that is going to update State the weights of the generator so that in the next batch or in the next time we try to train train the generator it's going to generate images which are able to better fool the

[1:02:05] discriminator and keep in mind that we keep the discriminator constant here so the training of the generator and the discriminator is done in tandem first we train the discriminator to get good at separating U fake images from real

[1:02:19] images and then we train the generator to get good at fa at fooling the discriminator using the train generator method and using the train generator method and finally we simply return the loss of the

[1:02:36] functions and before we train the model now one thing we have to remember here is there is no validation set so sometimes it can be hard to interpret getting good is the discriminator

[1:02:48] and that is where we have to do some visual inspection so what we're going to do is we going to save intermediate outputs after every single Epoch we going to generate a batch of images and we're going to save that batch of images

[1:03:03] as a file as a PNG file so let's see how to do that we're going to use a save image function from torch vision and torch vision. utils contains a lot of very useful functions to work with images which is loading

[1:03:16] images saving images converting a grid creating a grid of images and many more so do check them out it also contains many utilities for downloading data from different sources now we're going to put these

[1:03:30] directory samp uh into folder called generator or generated which we are directory and we're going to create this directory here so if we run the code you can see that this directory gets created here it

[1:03:46] is then we have this function called save samples so the save samples save samples so the save samples function is going to first generate uh a tensors so we're going to give it a batch of latent

[1:04:00] tensors and it's going to generate images from the latent tensors then it it is also going to construct a file name so it's going to construct a file name generated Hyphen Images hyphen and this is going to be a

[1:04:12] number.png so it's going to be something like generated images 0000 .png 001.png 002.png and so on and the index is what is going to control that so in some

[1:04:24] sense using the index we are specifying the file name of the generated image and then we are simply going to call save image on the denormalized fake the batch of fake images and we're going to call save image and all save image

[1:04:39] does is converts the batch of images into a grid and then saves that as a into a grid and then saves that as a file a PNG file so it's going to save it that particular directory which is a

[1:04:53] generated directory and finally if we have set show equals true then it is also going to show or display those images so that's our save samples function once again if this does not make sense then

[1:05:06] what all you have to do is just create new code cells and run each line one by one in fact that is how we created the function in the first place first we used four or five cells to step by step create each of these things and then we

[1:05:21] put the code into a function okay so now for let's create a set of latent tensors that we can keep using Epoch tensors that we can keep using Epoch after Epoch because we want to look at

[1:05:34] the outputs of our model so it would be good to look at the outputs on the same set of latent tensors otherwise if you also change the latent tensors you may not be able to compare the performance of the model Epoch after Epoch so let's

[1:05:47] just create a fixed set of latent tensors using torch. randn so we're going to create 64 tensors here of latent size of of latent size comma 1 comma 1 so we're not going to use a full batch of 128 we're just going to have 64

[1:06:01] so that we can display it like this in an 8X 8 grid so let's create those fixed latent tensors which we will use after each Epoch and let's first save a set of samples before we start training so now we're calling save

[1:06:14] samples and we're calling it with the index zero and it is saving the file index zero and it is saving the file generated images 00.png and you can see here in generated if we open this

[1:06:30] has been saved here and now we ready to start training the model so before we do start training the model so before we do that let's just record one more

[1:06:47] and this training Loop this fit function is going to be very different from the is going to be very different from the fit functions we've seen so far and discriminator in Tandem and once again to very quickly revise what that

[1:07:02] going to train the discriminator for a batch so we take some real examples some generated examples put that into the discriminator and then get the results calculate the loss so for the real examples the prediction should be one

[1:07:17] and the generated examples of target the target for real examples is one the target for generated examples is zero We compare the targets with the predictions entropy and update the discriminator so that it gets better at making this

[1:07:31] differentiation then we take some random inputs put them into the generator and then we take the generated images run them through the discriminator and try to then train the generator so that the discriminator predicts one or that is

[1:07:45] the generator fools the discriminator using the fake images okay so we train the discriminator then we train the generator and then we repeat and let's see what that looks like in code so here is a fit function it simply

[1:07:58] takes the number of epoch and the learning rate and then the start index naming the files that are saved at the end of each

[1:08:10] Epoch so first we empty the Cuda cache so this is going to remove any remaining unused data from the GPU so that we have a fresh memory of the GPU to use then we also have these lists where we can track some of the losses

[1:08:23] losses the disc minor losses the real scores and the fake scores and then we have these optimizers so we are going to use the Adam Optimizer here and once again this is one of those things that has that is a little bit eccentric it

[1:08:37] has been found that the adom optimizer with certain configurations so you see these betas here so the Adam Optimizer with all these with these betas so these values of 0.5 and 999 works well for training this

[1:08:51] specific model and you can look through the documentation of item to understand what these betas are this is something that we leaving as an exercise for you so we creating two optimizers one for the discriminator and one for the

[1:09:04] optimizer is going to change the weights of the discriminator and the generators Optimizer is going to change the weights of the generator now we start with the epoch we start with the training and in each

[1:09:17] Epoch we get batches of data from the training data loader and you can see there is this additional wrapper called tqdm here this additional wrapper called tqdm here this tqdm is a helpful widget a Jupiter

[1:09:30] widget it's a helper Library which will show a progress bar for each show a progress bar for each for the for each Epoch so as each batch let me just kick off the training here because it's going to take some time

[1:10:10] see the train generator function has been executed so I'm just going to kick off the training here because it's going to the training here because it's going to take a while

[1:10:29] only 10 epochs right now all right so now we have our uh we go through each batch of data and then for each batch we first train the discriminator so we pass in the batch of real images and note that we are not

[1:10:44] really interested in the targets that we get from the original image data set in only one folder given to the image folder data set which is the images folder so we not there are no real labels for us to use from the data so we

[1:10:58] simply take the real images and put them into the discriminator and then we also train discriminator and that's going to train the discriminator using some real images and some fake images and then return the loss the real score and the

[1:11:11] fake score then we going to train the generator so to train the generator we simply call pass in the optimizer for the generator it is then going to generator pass them through the discriminator set the target to one and

[1:11:25] calculate the loss and then update the weights of the generator okay so the then the generator gets a little better and then we repeat that process so then we and that's pretty much it this is the training Loop essentially then here we

[1:11:39] are simply recording the losses so we append the last Batch's loss we append fake score so that we can study them later and then here we are logging the losses so we are simply printing out the output at the end of the epoch so we

[1:11:54] printing out the total number of epo the generator loss discriminator loss real score and fake score from the last batch and finally here we are saving the sample files so we are saving Epoch plus start idx this is the index that we are

[1:12:10] passing so this is going to as the epox increase the file name is also going to increase the file name is also going to increase from 0000 1 02 03 04 and so on and then we pass in the same fixed latent tensor so that at the end of each

[1:12:25] OC we generate an a set of images using the same latent tensors and then we set show to false because we do not want to display them we just want to save them to file and finally we return the entire

[1:12:39] set of losses real scores and fake score so although this fit function looks big there's really only this much code here which is the actual meat of the training Loop which is to run over the epox get real images and then train the

[1:12:52] discriminator and the generator okay so then we are going to train this model with a learning rate of 0.2 for 10 Epoch and you can see here that we've called the fit function with these 10ox and this learning rate and

[1:13:07] we've also logged these hyper parameters here using jan. log hyper params as you try different experiments make sure to log your hyper parameters for each you get at the end so this is going to take a while but

[1:13:21] let me just show you what that looks like discriminator loss starts to decrease here and the generator loss is pretty

[1:13:34] high but over time you will see that the discriminator loss actually increases that's where it becomes difficult to interpret the losses where sometimes the discriminator loss is high you can also see the real score of

[1:13:49] the real score if that gets closer to one that means the discriminator is getting really good at differentiating between real and fake images and U if the fake score gets close to zero as well but really what is going to tell us

[1:14:03] how the training is proceeding is by looking at these generated images so if looking at these generated images so if we open up this folder here and look at you can see generated images zero that was pretty

[1:14:15] was pretty bad this was just random noise but then bad this was just random noise but then when we look at generated images just one Epoch our discriminator has been trained

[1:14:29] to differentiate between real and fake images and then the generator has been to fool the discriminator so you can see that the generator has started generating images which look somewhat like aneme faces you can see that there

[1:14:42] is hair here and as the latent vectors vary the color of the hair varies structure of the face coming together and then as the latent vectors vary the structure of the face varies as well you can see the basic formations of eyes you

[1:14:56] can see small hints of the nose and you can see small hints of the faces so our trick of generating of uh training the generator and discriminator in tandem is actually working and already just from the first Epoch you

[1:15:11] can you can start to see that our model has started to generate anime like faces although they're not very well defined right now and we let the strain for a while but if you scroll down here you will be able to see that there are some

[1:15:23] of these older um images so after the fifth Epoch you look much more well defined it's starting to look much richer you can see that the hair now has not only the color

[1:15:35] but it also has the shine it also has these strands uh it's still struggling with the eyes the faces are a little bit messy but it has started to generate if you look closely enough you'll also find that there are both male and female uh

[1:15:49] faces here you are seeing different colors of hair you are seeing different colors of eyes then by the 10th Epoch it gets much better so by the 10th Epoch getting really good uh you can see that there are different variations here as

[1:16:03] this is very little hair this probably looks more like a male face and you can see that you there are variations in terms of where the face is turned so this face is turned left and this face is turned right and

[1:16:18] so on still a bit messy of course and by the 20th Epoch it's getting pretty good wouldn't say perfect yet but at least some images look pretty good if you come

[1:16:30] get to the 25th Epoch so by the 25th eoch it's it's looking almost indistinguishable uh indistinguishable from actual images for instance if you pick this image you could pass off this image as something

[1:16:43] that was actually a screenshot from an anime or if you look at this one for hair there's eyes well defined and there's a nose and the face is turned in detailing on the skin and as you continue to train your

[1:16:59] model over multiple epochs try training it for 40 EPO 50 EPO 100 Epoch and see how good the generator gets okay now it would be nice to

[1:17:11] generalize to visualize the training process by combining the sample images generated after each Epoch into a video and this is what we can do using the open CV Library so I'm not going to get into the code here but the basic idea

[1:17:23] here is that it is going to take each of the images and it is going to convert them into a training video and when we train it this is what video and when we train it this is what it looks

[1:17:39] discriminator gets better and the generator gets better at fooling the discriminator you can see that slowly it's starting to improve Epoch by Epoch and better and it goes back and forth

[1:17:54] the quality of images that's probably because the generator still exploring the space of images that are being generated there is always this subtle inter subtle competition going on

[1:18:08] between the generator and the discriminator so keep that in loss changes over time but this is one of those cases where the graph is not

[1:18:20] of those cases where the graph is not really going to be very helpful for us that the generator's loss should get as low as possible as the generator's loss

[1:18:32] generator is going to fool the discriminator better and better but at the same time we do not want the discriminator loss to get too high at have a bad discriminator because if a bad if you have a bad discriminator then

[1:18:46] the generator does not have a lot to work with then here we can plot the real and fake scores as as well so you can see that we actually have a pretty good discriminator probably the discriminator

[1:18:59] could get a little bit worse sometimes you see here it the real score gets to around. 5 7 and the fake score gets to around. 2 or so but in general the discriminator is going doing a decent job at this point when you see something

[1:19:13] like this you may want to maybe train the generator not once but twice per batch and you can try these things you can try to see how you can uh slightly training of the generator and the training of the

[1:19:27] discriminator to get a better result okay so there's a lot here to experiment with in a generative adversarial Network so I will let you experiment here you experiment with the learning rate experiment with the optimizer experiment

[1:19:41] with the training process itself maybe first train the discriminator for a few batches separately and then train the generator for a few batches separately see if there is some kind of a strategy that you can figure out to train the Gan

[1:19:53] faster try training for a longer time try training for 50 Epoch 100 Epoch and see if you get well defined faces and one thing you may have noted here is that it doesn't matter what data you put into this because so far we've not used

[1:20:08] any information about the actual data set here so you could replace the anime faces with a data set of human faces you could replace it with a data set of handwritten digits you could replace it with a data set of paintings and art is

[1:20:21] another very interesting thing that you can generate with Gans and because art is subjective and Abstract sometimes the result are actually quite impressive you can replace it with images of landscape you can replace it with images of dogs

[1:20:34] and cats you can replace it with images of everyday objects so do experiment with this this is a very interesting field and there's a lot of creativity that you can apply here in fact a lot of artists have

[1:20:47] started using Gans to generate images and they've seen they've identified different um controlling the different different aspects of the generated images one other thing to experiment with is the latent tensors so because

[1:21:01] here we've used only 64 latent tensors but you can try to change each latent tensor you can try to vary increase and decrease each specific dimension of a the image so use this notebook as a

[1:21:17] playground try to experiment try to let your curiosity run wild with Gans and results and if you find something interesting do write a blog post about it do let us know about it let people know on the Forum this is a open area of

[1:21:32] research right now so something even if you spend maybe a couple of days working on this you're probably going to discover something new which nobody else discover something new which nobody else has so do spend some time with Gans you

[1:21:44] can see here our training has completed and we have been able to generate images for about 10 epochs so in 10 epochs we are about halfway there it's not that great but in about epox it will get pretty

[1:22:02] lesson page you will be able to see here that there is another another notebook here which is to generate handwritten digits using Gans this is almost exactly the same thing in fact you can use the exact same

[1:22:15] notebook and simply change the data set instead of the instead of the anime faces data set you can use the amness data set uh but here there is A variation on the network as well if you want to see you don't have to use

[1:22:28] convolutional layers for the mnist data set you can actually just use normal can see the discriminator here the discriminator is a lot simpler it is nn. discriminator is a lot simpler it is nn. sequential of nn. linear and Ley Ru and

[1:22:43] also a lot simpler it simply contains three linear layers so you do not need to use convolutions and deconvolutions to create Gans you can actually just do it with simp simple linear layers as well you can see here here the generator

[1:22:58] starts out generating random noise but over time as we train the generator the generator gets better and better and over after 10 Epoch it looks something like this after 50 Epoch it looks like this and after about 300 Epoch and this

[1:23:12] takes it trains much faster so about 300 Epoch in it generates pretty good images Epoch in it generates pretty good images of HR digits okay so do try this out as well and you can watch this video as well

[1:23:25] you can see you can study how the losses change here and you can compare how the varies between this model and the other model that we looked

[1:23:39] other topic closing topic that we will cover today as we wrap up the course and transfer learning is a technique used for computer vision used specifically very commonly with convolutional neural networks so we'll just touch upon this

[1:23:55] networks so we'll just touch upon this briefly and as we go through this also use this um last part as sort of a tutorial for the course project on how to structure a course project so let's open up this notebook on Google

[1:24:20] is click on runtime and select change runtime type and make sure that we have runtime type and make sure that we have the GPU selected here and then we're going to run the first

[1:24:42] initialized so we've learned about convolutional neural networks and if you dig further if you look up online and try to figure out what exactly a convolutional neural network learns you will learn that each kernel so in

[1:24:57] each layer you have many kernels and each kernel actually learns something specific about the image and then as you have layers the the kernels the kernels understanding also becomes layered so what do I mean by that when

[1:25:11] suppose you have an image like this so this is an image of a sign which says 60 then the first layer of kernels is going to identify things like edges so maybe one kernel May identify a edge going towards the top right another kernel May

[1:25:26] identify a vertical Edge another kernel May identify a horizontal Edge another kernel May identify slightly circular edges and so on and then as we pass them through a second layer and through the second layer once again these kernels

[1:25:41] features so what we doing is as we increase the number of channels as we increase the number of channels the number of kernels in each layer also increases and we go from identifying lowlevel features think like edges to

[1:25:55] identifying mid-level features things like shapes so for example the circular like shapes so for example the circular shape the square shape um patterns and then we go to identifying more higher level features like actual let's say

[1:26:07] faces of dogs and then wheels and then cars and things like that so your convolutional neural network builds a layered understanding of your data and as you pass so as you pass your data through the neural network and as you

[1:26:22] train the model over and over uh this is what is called layer visualization if you actually look at each layer and try to see which kind of images activate a find that in a particular layer different kernels get activated by

[1:26:36] different types of images so when it is a lower level layer which is something closer to the input the kernels are very simple they get activated by shapes and then as you go to higher and higher layers they get activated by specific

[1:26:50] patterns and IM and eventually at the topmost layers or or the outermost layers which are closest to the output each layer each kernel is responsible for identifying a specific object or a specific part of an

[1:27:04] object okay and this is a far deeper field than we can get into right now but I have provided some sources here on how a convolutional neural network learns and how to visualize what each layer of a convolutional neural network learns so

[1:27:17] a convolutional neural network learns so do use this information here but keeping network creates a creates a layered understanding of data or and these this data is ultimately images so in some

[1:27:32] understanding of the world so keeping this in mind there is a we can apply and the idea behind transfer learning is very simple we take

[1:27:44] a we take a network a convolutional neural network that has been already trained on a very large data set so there is a data set called the image net which contains 1 million images across

[1:27:57] companies and several research Labs have trained dozens of models in fact hundreds of models on the image net data set so the idea behind transfer learning which is already trained and these are called pre-trained models and we use

[1:28:13] some of the layers of these models to then train models train custom models for a custom data set that we are working with with so the idea here is that the the features learned in the

[1:28:27] mid-level features the high level features they are going to be useful for for solving any image classification problem or any computer vision problem in general the only thing that we may need to change is the classifier at the

[1:28:40] end so remember we have a linear layer at the end of each convolutional uh Network which that linear layer is simply taking the output of the last convolutional layer and then giving it converting that into a vector based on

[1:28:54] the number of classes that are a that we need to learn okay so this is what we're going to see here and for that we're going to use the Oxford trip it pets data set so this is a data set available from the fast AI course by the way which

[1:29:08] is another course that you should definitely check out course. fast.ai and this contains 37 categories so remember C4 10 we worked with 10 categories but this contains 37 categories so that's a pretty large number of categories but it

[1:29:21] only contains about 200 images per class so in total it only contains about 7,000 images and that makes it a pretty hard problem and these images also have large variations in scale pose and lighting so these are breeds of pets cats and dogs

[1:29:37] so that can already be quite difficult to differentiate from because a lot of breeds of dogs look quite similar and many breeds of cats look similar and we have only about 200 images per class compare that with C 10 where we

[1:29:52] class compare that with C 10 where we had 60,000 images and we had only 10 classes so it seems like this should be a much harder problem than C4 10 so let's see how far we can get with this by using what is called a pre-train

[1:30:05] model so first we're going to download the data set so to download the data set here on the on this page course. fast. a/d sets you can get the URL now this is a direct URL this is not a kaggle data set so this is a direct download URL to

[1:30:19] set so this is a direct download URL to the raw file oxer it. tgz and that's why using the download URL function from pytorch torch Vision but if this was a data set hosted on kaggle you could use open data sets and that is the idea here

[1:30:33] for your course project whether you're picking a data set from kakle or you're very simple ways of downloading that data set on kaggle use the open data sets library for uh fast AI data sets use download URL or for any data set

[1:30:48] a direct link for it something that you can open in a browser and that will download the file the same URL can be used with download URL as well then once the file is downloaded we can convert it

[1:31:02] into let's download it first once the file is downloaded we can extract it out and convert it into a folder containing all the

[1:31:17] files this might take a while depending on the size of your data set

[1:31:40] if you refresh the files tab you will see that there is a data folder here and in the data folder we have Oxford Tri it pet and here we have images now unlike the data sets that we have seen so far far in this there is just a

[1:31:56] single folder called images and then the actual so the actual uh class of the actual so the actual uh class of the image is indicated here so for instance

[1:32:08] Abyssinian _ one indicates that this image belongs to the class Abyssinian and this particular image has the ID one so you can see that these are all the Abyssinian images similarly if we scroll down you

[1:32:21] can see Bengal is another breed so each of these is a breed either of cat or dog and then we have Burman and then we have Bombay and then we have a British short hair and we have a bunch of different we have 37 different classes

[1:32:36] actually so this is something very different from the image folder data set that we have seen so far you can see here that here the class is actually part of the file name so what we're going to do is

[1:32:50] we're going to create a helper function called par breed which which can pick up a file name and all that does is it is going to take the file name and it is going to split the file name at the

[1:33:03] the parts of the file name then it is going to ignore the last part of the file name so for instance from Main cone 52 um 52 is going to be ignored and then we are going to join it back using spaces so here for example

[1:33:19] you can see that we go from Japanese _ chinor 23 to Japanese chain which is the chinor 23 to Japanese chain which is the class of this particular file Japanese

[1:33:34] to to view images we can use the pil Library so from pil we import the image class and then to open uh we Define this function open image which takes a path and it is going to open up an image and then convert it into RGB so let's view

[1:33:49] then convert it into RGB so let's view an image here let's call open image an image here let's call open image and um let's call open image with Files and um let's call open image with Files 4 once again and let's try to show it

[1:34:02] 4 once again and let's try to show it so we import matplot lib do pipot as so we import matplot lib do pipot as PLT and we can do PLT do IM

[1:34:22] the data directory here so we see we just say os. path. just say os. path. jooin data

[1:34:36] go now we have the full path of the image so this image represents a few more images here it's always a good idea to look at some images before you do any processing or before you try to train a

[1:34:50] model so now we know how to load an image and now we also know how to get the class of the image which is the breed of the dog or the cat so now the next step here is for us to create a custom data set we can no

[1:35:05] because all the images are in the same folder there are no different folders per class but what we can do is we can create our own custom class by extending create our own custom class by extending the data set class from torch so from

[1:35:18] torch. .data you get the data set class and the data set class here we should probably import it so let's import the data set class

[1:35:41] three functions to be implemented an init function a len function and a get item function so the Len function simply Returns the length of the data set and the get item function is supposed to return given an index the I element from

[1:35:53] the data set so here what we're going to do is uh to the init function or the root which is the root directory where the files are contained and then the transforms that need to be applied so we're going to store the root directory

[1:36:08] but we're also going to get the list of files in the root directory and then if the file name ends with a JPG because sometimes depending on which operating system you're on sometimes there might be some other files there as well so we

[1:36:20] only need to work with images so if the file name ends with JPG then we keep that file name so we get a list of files ending with JPG from the root directory then what we also do is we call pass breed on each file name and that gives

[1:36:34] us a list of classes for each of the files and then we convert that into a set so the set is going to remove duplicates and then we convert it back into a list so this entire line of code is going to give us a list of the unique

[1:36:47] classes that are present in the data set and then finally we also store the where we are getting a list of files from the root directory then in the get item function if we want to get the I item first we get the file name of the I

[1:37:03] file and then we join the root directory with the file name using os. path. jooin to get the full path of the file then we open the image using the full path of the file and whatever transforms have been passed into our into our data set

[1:37:19] uh into our Constructor here we apply those transformed on the open image and finally we also get the index of the class so from self. classes we get the class so from self. classes we get the index of the class name obtained from

[1:37:35] the file using par breed okay so try going through this step by step and try we're trying to show you here is how to create a custom data set you may not always have an image folder you may have sometimes you may have all the all the

[1:37:50] this case and then the class may be a part of the file name sometimes you may file then you will need to load up the CSV file using a library like pandas and inside the get item function and inside the

[1:38:06] the CSV file the data frame and then from the get item function you may need to use the CSV file to actually get the class of the data now what it is is not python code you should be able to figure it out and for a particular data set if

[1:38:21] you're not able to figure out how to load it in in pytorch then simply post on the Forum now the place to post is you go back on the lesson page whichever lesson you have a doubt in and click on the course discussion forum and then on

[1:38:35] the course discussion forum you can ask a question here by clicking new topic or you can also open up a particular topic and ask a question there if you see and ask a question there if you see something

[1:38:50] approach different data sets and spend some time with it it may seem difficult at first but you can see here in total to work with a custom data set it took us only about 15 lines of code you simply defined a Constructor which

[1:39:04] stores all the important information and then you have this Len function and get something like this for your project if you need to so now that we have our pets data set class our custom data set class

[1:39:18] we are going to now pass it in the data directory and we're going to pass in a list of transforms that we need so here we have the transforms the first going to resize the images into size 224 because you have all these images in

[1:39:31] very different shapes and sizes some are tall some are broad some are square some are very large some are very small so we're going to resize them into 224 pixels x 224 pixels then we are going to add a padding of 8 pixels so we're going

[1:39:45] to add a reflection padding and then we also going to do a random crop so first we resize the image into 225x 224 and when we do that when we do resize only the shorter Edge becomes 224 the longer Edge can sometimes be longer than 224 so

[1:40:02] then we do a random crop to ensure that we get a square crop out of the image so longer have rectangular images now we have square images and then we pass those convert those images into tensors using torch. two

[1:40:17] tensor and finally we normalize them using stats from the image net data said so this is one important but subtle thing here we are going to use a model

[1:40:29] net data set the imaginary data set contains 1 million images from uh we're going to use a model that has been trained there and as we did for CA

[1:40:42] trained there and as we did for CA 10 the images the input tensors were normalized before training that model so the model understands not generic RGB images but the model only understands images that have been normalized using

[1:40:55] this mean and the standard deviation so whenever you use a pre-trained model and we'll see what that is you need to know what are the normalization statistics that were used to normalize the data when training the model because if you

[1:41:09] pass unnormalized images that will not make sense to the model because it's possible that the model has been trained with RGB values in the range minus one to 1 but if you're passing in images with which have

[1:41:21] RGB values in the range 0 to 1 the model it may not make sense to the model and hence the pre-training may not be very useful so we apply this normalization using image net stats whenever we are doing transfer learning so we do the

[1:41:35] normalization and that creates our data set for contains 7,390 images we can also check data set.

[1:41:51] 7,390 images we can also check data set. classes here so if we just do data set. different classes that are present in the data the data set let's check the

[1:42:11] here we can also visualize a batch from the data we can also visualize a single image so here we have defined a function called denormalize which can take an image or a batch of images and denormalize it so it takes the

[1:42:24] normalized using the image net statistics and converts them back into normal image tensors where pixel values go in the range 0 to 1 so in the show image function we take an image tensor and we take a label and then we display

[1:42:37] the labels for instance here this is the main and its label is 25 the number main and its label is 25 the number and the text is Main for that specific class and this is what it looks like you

[1:42:50] class and this is what it looks like you can try a few more

[1:43:08] cropping happening it was possible that this was more of a rectangular image which has now been cropped into 224x 224 and you can try changing the crop size but in general you do want to keep the images Square because

[1:43:24] ultimately all of these images from a different from all of these images are going to be stacked together to create a single batch of image tensors and for the batch to be a single tensor each image needs to have the same shape and

[1:43:38] make each image a square so if you convert each image into a square of a images they can be combined into a tensor very easily so that's our data set and then we can create training and validation

[1:43:52] sets out of it so we set the validation percentage to 0.1 or 10% and that gives us the validation set size so we can now use the random split function from toss. use the random split function from toss. u. data to create a training set and a

[1:44:05] validation data set and you can check their length the training set and 739 for the validation set a very small number

[1:44:20] validation set a very small number compared to C 10 1110 is the size but at and some of these classes are hard to differentiate too and next we convert uh we create

[1:44:33] data loaders so we're going to use a batch size of 256 because on the Google collab GPU you can use a larger batch size if you get a Cuda out of memory error you may want to convert it into 128 and then restart restart the

[1:44:47] notebook once again so sometimes if you use too large a batch size that is going to slow down your training or it is going to cause an outof memory error and when you get an outof memory error you have to restart the

[1:45:00] kernel so let's now create data loaders training data loader and validation data loader and then let's create this function show batch and all of these functions from this notebook you can use these utility functions feel free to

[1:45:12] idea here is not that you should be able to write all of this by yourself from scratch that is absolutely not the idea you can use whichever code you need the idea is for you to find an interesting data set go to kaggle go to fast a go to

[1:45:29] Google data set search and a bunch of other places find an interesting data set and then use this code make the necessary modifications to work with that data set

[1:45:41] so here we have the show batch function something that you can reuse and let's look at a batch of data now

[1:46:06] because it is going to process a whole bunch of images and these are pretty large images so this is a batch of data you can see you have cats and dogs and different breeds and some some breeds can be very different to difficult to

[1:46:18] differentiate but I'm sure these three dogs although they look somewhat similar breeds and then sometimes the cropping is a bit odd like in this case you can cropped out in this case you can see the face of the cat has gotten cropped out

[1:46:33] in this case you can hardly see it's only half of the body and that is what makes this even more difficult because these are in different shapes and we are probably Flying Blind to a large extent here when we taking Square crops one

[1:46:47] option to avoid this is to pad the images so that they become Square now I'll leave this as an exercise for you take the rectangular images and then pad them in the right fashion so that they become square and maybe you can use a

[1:47:02] zero padding maybe you can use a reflection padding that's up to you so that way you can retain the entire image inside the

[1:47:14] so now we're ready to train our model and first to define a model we need to learn about transfer learning now you do not have to use transfer learning on your course project you you can train a model from scratch

[1:47:27] wish you can also use transfer learning it's totally up to you um so this is the you're trying to do you may or may not use this part but the idea behind transfer learning is we take this network which has been trained on

[1:47:43] the image net data set and it has a bunch of convolutional layers then Rel convolution then pooling convolution pooling and then finally it has some fully connected layers and it is trained to make predictions it

[1:47:55] is trained to give outputs which correspond to the classes of the image net data set now what we typically do is we take one or more layers from the very end sometimes there's just one fully connected layer sometimes there are two

[1:48:10] three fully connected layers so we can make that cut at any point so we make a cut at least somewhere before the final layer and we replace it with a new classifier okay so this is what it looks like in code so here we have once again

[1:48:27] our image classification based class now if you have not seen this before you can if you have not seen this before you can go back and review lessons 3 4 or five and you will see the exact same class being used there what this defines is

[1:48:40] calculates the loss for a batch of training data it defines the validation step which calculates the loss and accuracy for a batch of validation data and it defines the validation Epoch end which calculates the overall loss for

[1:48:53] the validation set and finally defines the EPO end which uh prints out the losses and accuracies at the end of an Epoch so this is common for all image

[1:49:05] use the cross entropy laws for instance that is common we use the accuracy that is why we have created this Base Class and you can use this in your project so please feel free to use this and because we are working with an image

[1:49:19] classification problem all we need to do is we need to extend the image classification based class so here we're defining a model called the pets model and the pets model is going to use the image classification Base Class

[1:49:33] image classification Base Class here so let's extend this class so we class and then we need to Define just two functions the init or the Constructor function and the forward function now in the Constructor function

[1:49:46] classes so that's one thing and then we're also going to pass in an additional parameter called pre-train equals true and we'll see what that does now the first thing this we've seen earlier is to invoke the initializer of

[1:49:59] invoke the init function of the image classification base which itself extends nn. module from pytorch so this is a necessary line but here is where it becomes different instead of creating our own model where we would do

[1:50:13] something like nn. sequential and inside it put in a bunch of convolutional layers and maybe create residual blocks and maybe create U have activation functions have fully connected layers have flatten and a whole bunch of layers

[1:50:26] instead of doing that we are going from torch Vision we are importing models and we are using models. resnet34 so let's see what resnet 34

[1:50:50] that this returns a model that is already defined for us so it looks like it has a convolutional layer then it has a batch normalization then it has a relue and then it has a max pool 2D and then it has these sequential layers so

[1:51:05] anything that is called a basic block here in resnet 34 is actually a residual block so this is one residual layer which has two convolutional layers and activations and then it is going to add the input back to the output similarly

[1:51:20] you have another residual block you have another residual block then you have more residual blocks and so on so this is a model that is already implemented is a model that is already implemented for us we do not need to write

[1:51:35] can set pre-trained equals true so when you said pre-train equals true so when you said pre-train equals true what that does is it also downloads you can see here that there was a short download here so it is downloading

[1:51:48] weights for this specific model called the resnet 34 model it is downloading the resnet 34 model it is downloading weights from this model when it was trained on the imet data set so somebody very kindly for us has taken

[1:52:03] this model and trained it on the image net data set which contains a million images and um belonging to a thousand classes and they've trained it possibly for days or weeks and they've trained it on multiple gpus possibly on a cloud

[1:52:17] cluster somewhere and they've spent maybe thousands of dollars on it but at the end the combined the the condensed knowledge of all the images in that data set is captured within the weights of the model so the weights of the model

[1:52:31] the resnet 34 you can see this pth file this weights of the model have then been uploaded to pyo's website from at this URL and when you pass pre-train equals true pyos not only instantiates this rest net model but it also then loads

[1:52:47] the weights from this pre-trained model into resnet 34 okay so now at this point when you have models. resnet 34 with pre-trained set to true so this is your resnet that is trained on the image net data set so now if you pass it if you

[1:53:02] pass in an image into this resnet it can come up with a prediction and the prediction will be a number or the prediction will actually be probabilities for thousand classes so it can come up with probabilities for

[1:53:14] thousand classes and then you can interpret those probabilities and you can pick the highest probability as a prediction of the model and it is making net now that is not very useful for us

[1:53:26] data set here and we have only 37 classes not thousand so what we want to do is we want to remove the last layer of this reset 34 model and instead insert our own last output layer our own linear layer or fully connected layer as

[1:53:41] it as it is called and that will have only 37 classes so that's what we going to do here so first we create a network uh first we create model models. resnet34 and then if if pre-train was set to true

[1:53:56] in the Constructor we create the pre-train model and that we set to self. network then inside the network you can see here there are there is layer one layer two and so on and finally there are there is this FC or what is a fully

[1:54:10] connected layer it's also called a l linear layer or a feed forward layer there are different ways of calling it but it's the same thing it's nn. linear layer it takes the last 512 features that we get out of the previous layer

[1:54:22] and it converts them into thousand instead of doing this we are going to replace it so we are going to take nend we going to create a new nn. linear layer the number of input features is going to be the same as the

[1:54:35] old fully connected layers features so instead of we simply take self. network. fc. in features which is going to five which is going to be 512 and here we're going to now have the number of classes or the number of outputs set to 37 which

[1:54:49] Constructor so our pets model takes the reset 34 with pre-trained weights and removes the last layer and replaces it with a fully connected layer or a linear layer with 37

[1:55:04] layer with 37 classes that's it so now we have all the weights for all the layers except the last layer and we have a new layer with new last layer with randomized weights now that is a lot lot better than

[1:55:17] know anything and this is because of the hierarchical learning of convolutional neural networks we know that the first convolutional layer will learn something convolutional layer will learn something like um something like lines and

[1:55:29] convention layer will combine those to identify patterns and shapes and so on and by the time you get to the thir the 32nd layer 33rd layer and by the way resnet 34 is called resnet 34 because it has 34 trainable

[1:55:44] layers so that would be 33 convolutional layers and one linear layer so by the there is a lot of condensed Knowledge from a million images that you can reuse

[1:55:56] okay so that's our convolutional neural network with a pre-trained model which we have modified then we have these utilities for training on a GPU we have get default device which is going to uh give us a pointer to a device based on

[1:56:10] what is available if a GPU is available it gives us a pointer to a GPU otherwise it gives us a pointer to a CPU we have the two device function to move tensors and models to devices and then we have the device data loader helper class what

[1:56:24] move batches of training data into the GPU when we try to access them and then here we have our training Loop now this is something that we've covered in a lot of depth in lessons 3 4 and 5 so I will defer to that you can go back and watch

[1:56:40] those videos uh but the idea here is you can take this cell and you can copy paste it into your uh into your project as well so here we have a evaluate function which calculates for the the model its overall metrics on the

[1:56:54] validation set overall validation loss and accuracy then we here we have the fit function which can take a number of epoch and then train the model using a given learning rate on the training loader and evaluate it on the validation

[1:57:06] loader and use the given optimization function by default which is optim do SGD then we had also defined something called the fit one cycle function which called the fit one cycle function which applies a certain strategy for weing the

[1:57:18] low learning rate and slowly increases it and then decreases it over time so this is something that we learned the one cycle policy is of increasing the learning rate and then decreasing it helps us train the model much faster

[1:57:33] because it helps the model first it points the model in the right direction and then it trains the model it the model makes big steps in the right and then the learning rate decreases as the model Narrows in on a specific

[1:57:46] optimal minimum and there towards the end we train with a very small learning rate for a longer time so then the model can really zero in to the best results so that's our fit fit one cycle function so now let's train our model so we get

[1:58:01] the device the default device and then we train our then we create our training by wrapping the existing training and validation data loaders so the benefit of wrapping them in device data loader um which also takes the device is that

[1:58:16] every time a batch is fetched the batch is automatically moved to the GPU as well okay okay so let's start training the model here and I'm going to kick off both of these trainings for you to

[1:58:30] see so now we create the model and we create it in the exact same way that we had done so we are going to pass to it you can see pets model accepts two arguments it accepts the first argument which is the number of classes then the

[1:58:43] number of output classes we can get using Len data set. classes and then the second argument it accepts is pre-trained so first we will use pre-rain weights so if we set pre-trained equals true then the weights

[1:58:55] of resnet 34 will be downloaded and used so that all the layers except the last one have the weights from the image net training and the last one is randomly initialized and then before we train we evaluate the model on the validation set

[1:59:09] validation data loader and you can see that the loss is 3.8 and the validation accuracy is only about 4.55% and this is something that you would expect because there are 40 classes almost 30 37 classes so a random

[1:59:23] guess on 37 classes would only be about 2 to 3% accurate so even though we are the last layer is still randomly initialized so the predictions are still

[1:59:35] random but when we train the model and here we are going to train the model using fit one cycle when we train the model all the information that is already there in the previous layers is going to be quite useful and only the

[1:59:48] last layer is going to train and change very rapidly so we train the model model for six Epoch with a maximum learning rate of 0.1 remember we using the one decreasing the learning rate over the duration of the epox and then we are

[2:00:02] regularization techniques like gradient clipping weight Decay and we going to use the Adam Optimizer all of these are covered once again in a lot of detail in lesson five so do go back and review it and for your project you can use the one

[2:00:17] cycle policy if you wish and if you wish you can use the normal training loop as it's totally up to you so we call fit one cycle with the given epox maximum validation data loader and the optimization functions and remember in

[2:00:33] lesson five it took us about 5 minutes to train a model from scratch on the cart and data set to get to about 90% accuracy this time we are working with far fewer images so there we had 60,000 this time here we only have about 7,000

[2:00:49] there we had 10 classes here we have only uh we here we have 37 classes and we are working with images of different shapes rectangular images and we are differentiate we have breeds of dogs which look very similar yet within just

[2:01:05] about 2 and a half minutes you will see right now that we get to an accuracy of right now that we get to an accuracy of about

[2:01:19] accuracy of uh 79.9% so Approximately 80% in just under 3 minutes and that's pretty that's pretty good that is

[2:01:31] terms of uh fast training and all this has happened because of transfer learning because we are using an a model that has been

[2:01:44] trained on imet because all of the convolutional layers already know how to convolutional layers already know how to identify shapes and patterns and and faces and features and things like eyes and noses and faces of dogs and so

[2:01:59] on and faces of cats and so on right so only the last layer has been really trained and the rest of the layers also have been modified but not as much and you can see the difference here is when you try to train the same model from

[2:02:11] create a second model and once again this is going to use pets model this is going to use resnet 34 and we are going are going to replace the last layer but this time we are not going to use the

[2:02:24] training so if you do not have the pre-trained weights and then we evaluate the model initially it looks the same it's about 1.8% accurate once again it is as good as random initially because the last layer is randomly initialized

[2:02:39] and in fact all the layers are randomly initialized this time and this time when we train you can see that the accuracy does not really improve to the same extent so you can see after the first Epoch we get to about 0.02 and after the

[2:02:52] Epoch we get to about 0.02 and after the second Epoch we get to about um 0.05 which is 5% accuracy and then we are only about getting to 10% accuracy here you can see by the third Epoch we were already up to 20% accuracy and then it

[2:03:05] picked up really fast it went from 20% to 61% to 76% to 79% so let's wait for a couple of minutes and see what the see what minutes and see what the see what happens here

[2:03:25] about 13% and as you let this train you will notice that while the pre-trained model reached an accuracy of 80% in less than 3 minutes the model without the pre-trained weights could only reach an accuracy of 24% and this is what makes

[2:03:39] transfer learning probably the single most powerful technique in computer vision so in general in the real world whenever you're working on a project you always always always want to use a pre-trained

[2:03:54] model now for this particular course project um you may not you you can try training a model from scratch too because that's a good way to learn but world project something that you want to deploy into the world you will you're

[2:04:09] going to get a good Head Start If you use a pre-train model so always use a pre-train model whenever you can and this training is just completed and you can see that it is about 20 3.9%

[2:04:27] the next steps are you if you had a test set then you can evaluate the model on the test set and Report the test set accuracy now at this point you should also look at examples you should pick examples from the test set or from the

[2:04:41] validation set and you should then make predictions on those examples now say our model is only about 80% accurate here so if it is 80% accurate that means 20% of the images from the validation set so the validation set is

[2:04:54] validation set so the validation set is of size about 700 So 20% of that is this point you should look at each of those 140 images that have been

[2:05:09] misclassified and check why they have been misclassified is it because maybe the image got cropped in a funny way is it because that the two classes are quite confusing using to begin with is it some other

[2:05:24] reason and then you can use that information to then improve your data set or to improve your model so you can maybe start try using a different model try using res net 50 try using dense net 101 try using efficient net there are a

[2:05:38] models that are available all you need to do is search for image net pre-trained models pytorch and you will end up with a whole bunch of them in fact if you just look inside models you will see a whole bunch of

[2:05:51] models you will see a whole bunch of bunch of them so if we just do dir models here and there are from they are from a certain set of families you have vgg squeez net Shuffle net rest net mobile net a denet and then there are a

[2:06:08] few more which you can simply copy over from elsewhere they are parts of different libraries so do try that out do experiment with it and see how far you can get and in fact it would be a good

[2:06:20] idea to try and get to about 95% accuracy on this and in fact you can try to get to 95% accuracy in less than 5 minutes so that's a challenge for you to try out on this transfer learning notebook and also use this notebook as

[2:06:34] an inspiration for your course project if you wish you can train a model from scratch or if you wish you can train a model using transfer learning that's totally up to you but the process is exactly the same so if we come back here

[2:06:47] exactly the same so if we come back here onto the course project a data set of your choice and you will apply the concepts that we've learned in

[2:06:59] this course to train deep learning models end to end with py toch hyperparameters and metrics so you can find data sets online and we'll talk about where to find data sets then you need to understand and describe the

[2:07:12] explain what type of data is it are you working with images or you if you want you can also work with tabular data you can also work with text and audio will have to do here but you have the foundation to figure out these things on

[2:07:26] with audio and then you need to figure out be a classification problem where we trying to categorize objects or in be a regression problem where you're trying to predict a single continuous

[2:07:43] modeling problem where you're trying to generate new images so you can use the Gans notebook as a starting point then you may need to clean the data if that all the files are in the right formats you may need to Define your

[2:07:57] custom data set as we did today for the transer learning uh tutorial you may want to plot some graphs you may want to ask some questions on how many how many elements are there in each class which classes

[2:08:09] are small which classes are large do you see any issues with the images images these are all issues that will come up with real world data then you need to perform your modeling so that means you need to First Define a model

[2:08:23] you can use a pre-trained model you can use a pre-trained you can use an without the pre-trained weights or you can define a network architecture on your own all three of them will give you different learnings and what I would

[2:08:36] recommend is on the same data set try all three ideas use a pre-train model use a model without the pre-train weights and Define your own custom model with your own regularization you can then pick some

[2:08:48] can use any training strategy you can you can use a a simple training strategy defined or you can use learning rate analing or scheduling something like the one cyle policy and you can even compare the two and see how how one is different

[2:09:04] predictions on samples and then you can evaluate it on a test data set if you have a test data set you also need to create a train test validation split wherever possible and

[2:09:17] then you can save the models weights because you've trained you've spent a record the metrics to Jian and then you can try different hyperparameters and regularization techniques to change your model so to get a pass grade in the

[2:09:30] model so to get a pass grade in the course project you should have trained a model and the model should be giving some good result now it doesn't have to be perfect but your model should be getting to let's say if it is 10 classes

[2:09:43] then you should be getting to at least 60% accuracy on 10 classes if you at 10% good as random or if you're doing a generative adversarial Network then you should be getting some something reasonable it doesn't have to be perfect

[2:09:58] once again if it is a regression problem again your mean squared error should be reasonable if you're predicting values in the range of uh let's say 100 to 200 then the error should not be so large that your prediction is so far away from

[2:10:13] the values that it doesn't make sense so try to pick a data set where you can get a good result and how do you pick data sets here are are some sources from go to kaggle.com sets and here you can get some public

[2:10:29] data set so you just search for image classification if that's what you image classification if that's what you want to classification data sets another good source is course.

[2:10:43] fast.ai so this is one place where you have a whole bunch of data sets now some problems so some of these are more advanced problems like image segmentation or object detection now that will require to learn something new

[2:10:58] if you have the time if you have the enthusiasm do learn about object detection do learn about image segmentation and try to create a model on one of these more advanced problems then there is also this list of

[2:11:13] awesome deep learning data sets that you can use some of these you know already some of these you some of these are new some of these are very large but try not to pick too large a data set because that may take a long time for you to

[2:11:26] complete uh it normally what you want is you should your training Loops your Epoch should not last more than a second or two so even if you're working with a few thousand images you can use transfer learning or if you working with 10,000

[2:11:38] images try to reduce the image sizes keep them small uh make sure that you are able to maybe at least train one model every day so that over a week or two you can get to a pretty good point where you have tried at least 10 15

[2:11:51] different ideas 10 15 different sets of hyper parameters so look through these these other data sets not all of them are image data set some of them are tabular data and you can apply the same techniques instead of convolutional

[2:12:03] layers you will use feed forward or linear layers uh so do do use these you can use any of the notebooks from the from this course as a reference so as a starter notebook you can click the new notebook

[2:12:19] button and create a blank notebook and then run that on collab and type the code yourself step by step but you can use any of these notebooks as a reference you can use any of the code from any of these

[2:12:31] notebooks directly you do not have to worry about plagiarism there because all you should not do is you should not take somebody else's project and submit it somebody else's project and submit it definitely pick pick a data set that you

[2:12:45] find interesting and then write your own code make your own modifications to this code to make it work with that data set do not copy paste from somebody so there's a fine distinction there but we think you can figure it out so please do

[2:12:59] that and then you can make a submission here by pasting The Notebook link and if you have the time and we know that not everybody might but if you have the time if you can put in another maybe four five 6 hours try to summarize your

[2:13:13] learnings in a blog post you can write a blog post about your course project about the data set about the model about the approaches you've tried about about the hyper parameters about the learning rate scheduling about uh transfer

[2:13:26] learning you can write a blog post about anything that has been covered in this course writing a blog post is a great way to consolidate your understanding knowledge with others and more importantly your notebook and your blog

[2:13:40] post will be really helpful for you when you look for jobs and internships because you will be able to share your work and it will not just be a line on your resume without any evidence it will be actual project hosted on Jovian or

[2:13:53] hosted on medium or wherever you write your blog and uh whoever is viewing your profile can then look at that project and understand that you not only uh learning you actually know it and you have done work on a real world project

[2:14:08] and that is going to go a long way in helping you move forward in your data science career so please do that and that is the course project you so please work on it and now a very quick recap of the

[2:14:22] course so we started out with the very basics of pyos we talked about tensors matrices vectors how to represent them we saw how to convert numpy arrays into pyos tensors and back and forth we saw how to compute we saw how to perform

[2:14:37] operations on pyo tensors and we saw how to use the autograd functionality which is to automatically compute derivatives of um results with respect to the input functionality to implement gradient descent so we used gradient we

[2:14:53] linear regression problem we tried to predict crop yields of apples and oranges in a bunch of different regions by looking at the temperature rainfall and humidity in that region first we did

[2:15:05] it from scratch using Matrix operations and then we saw how to use py to built-ins things like nn. linear things like the optimizer class loss functions and then we also we also defined our first training loop our

[2:15:19] first fit function to train a deep learning model and and you can go back and revise any of those those basic concepts whenever you need to then building on top of that we saw how to work with

[2:15:31] images so we saw how to go from working with tabular data like crop yields using temperature rainfall and humidity to working with image data and ultimately what we said was images are simply pixels and each pixel is a number so we

[2:15:44] can flatten it out into a vector of 784 pixels in this case from the amness data pixels in this case from the amness data set 28x 28 pixel images and then we trained we uh we used the same approach we had in in the previous lecture which

[2:15:59] was the linear regression uh approach but this time we used it for classification and that is when it it's now gets called logistic regression we multiplying with the weights Matrix adding the bias and then for loss we

[2:16:13] used the cross entropy loss instead of the mean square error loss because this time we wanted to interpret the outputs as probabilities and we wanted to maximize the probability of the correct class so we had 10 outputs for 10

[2:16:25] classes and then we used the cross entropy laws and once again we used also learned about the concept of training set and validation set so the and the validation set is used to evaluate the model because in the real

[2:16:39] world the valid the model is going to be used on data that it has not already been trained on so that's that's one thing that we did we also saw how to finally evaluate on the test set we saw how to make predictions on example

[2:16:53] images from the test set and why that is important then we moved on to feed forward neural networks we saw how you can add an activation function after a linear layer and then add another linear layer so that way we created our first

[2:17:08] activation function why that nonlinearity is important because it makes our model more powerful it gives our model the power to learn nonlinear relationships which was not possible in uh linear regression or logistic

[2:17:22] regression model another capability it gives us is to increase the number of layered learning which ultimately came networks but each layer can learn basic features and then the next layer can

[2:17:36] learn features based on top of the previous layer and so on and you can increase the size of each layer so the hidden size can be increased arbitrarily large so the number of parameters in the model can go from uh something that is

[2:17:50] is fixed and determined by the by the data to something that is completely flexible and you can in fact by the time we came to reset 34 the the number of parameters goes into millions so you can create models with millions of

[2:18:05] parameters even when you're working with small data sets and the way to do that is to create layer by layer and you need to have an nonlinear activation between simply collapses to a linear transformation so nonlinearity along

[2:18:19] ERS and increasing the size of each layer makes neural networks really powerful for learning any kind of um any kind of function any kind of relationship between inputs and targets and that was the universal approximation

[2:18:32] theorem that we learned about we also then understood why we need to use gpus because we are doing a lot of Matrix operations and gpus or Graphics processing units or gaming cards are optimized to do Matrix operations orders

[2:18:45] of magnitude faster than CPUs and we saw how to move our data to a GPU we saw how to detect a GPU and we saw how to move our model to a GPU and train on the GPU then we learned about the convolution operation so we saw some of

[2:19:00] the limitations of our feed forward neural networks where we teaching we're treating each pixel as an independent entity although that is not the case pixels come together in a patch to create patterns and then patterns come

[2:19:14] and that is how an image contains information which we can perceive so the convolution ution operation the kernel is something that can capture that it is a single patch that passes over the

[2:19:26] entire image and each kernel in a convolution starts to learn something about the image and as we layer convolutional layers we as we add more and more convolutional layers each layer uh builds a higher level understanding

[2:19:38] the lower level the lower layers learn edges and shapes and curves the higher layers learn patterns the even higher layer learns things like eyes and noses and objects and finally as you come to the final ler that learns to recognize

[2:19:52] specific objects from specific classes of the training data set then we looked at how to use some techniques to improve convolutional layers because one problem that we run into often is overfitting that the model

[2:20:07] gets really good on the training data set but is unable to give the same level of accuracy on the validation data set because it starts to memorize examples from the training data set and the way to counter that is regularization so we

[2:20:20] saw how to use techniques like data augmentation data normalization to not only counter overfitting but also train the model faster uh then we uh looked at regularization techniques like batch normalization and weight Decay and

[2:20:34] gradient clipping and Dropout and we also used residual networks so residual networks add the input of a convolution layer back into the output and what that does is it allows the layer to Simply learn the residual or the change between

[2:20:49] than an entire transformation which makes it more powerful and using techniques like batch normalization we can create really deep neural networks

[2:21:01] convolutional layers and then using the right data augmentation and regularization we can TR we can train these models really really quickly so we got to about a 90% accuracy on the C4 10 data set in less

[2:21:14] than 5 minutes which is pretty close to the stateof the-art and finally today we where we took all the things that we had learned over the course of the 6 weeks five weeks five and a so weeks and applied them to this problem of

[2:21:30] generating generative modeling and that tells you how versatile neural networks are that you just need to change a few things here and there and you can point things here and there and you can point it into towards any data set and solve

[2:21:42] many different kinds of problems we saw how to generate images of anime faces and they got pretty good in just about 10 to 15 Epoch and then we saw how the same approach can be used to

[2:21:54] generate images of handwritten digits all we need to do is change the data set learning a really powerful approach that makes deep learning so powerful where models that have been trained on a really large data set like image net

[2:22:10] with millions of images and thousands of classes over days and weeks by spending thousands of dollars the pre-trained weights of those models can be used in all we need to do is we need to customize the final layer to point uh to

[2:22:27] Simply give the kind of outputs that we want so we took a reset 34 um model and replaced it with a new fully connected or linear layer which could which had 37 outputs for the data set that we were working with the Oxford triple it pets

[2:22:43] you would have a different number of outputs um but you can change that

[2:22:55] and I hope you've been working through the assignments if not you can still do them definitely do the assignments it's so definitely do the assignments definitely work on a course project

[2:23:08] while you have all this information in the in your head it is the best time for you to consolidate and improve your understanding by doing a course project so definitely do it within the next few weeks

[2:23:20] because after that you may not really have the same level of understanding and then you may never find time to get back and review all the lectures or the um the videos you have the Jupiter notebooks you can use all the code that

[2:23:35] you need from any of these notebooks as a reference you have sources for data sets you have you can go to kaggle you can go to fast aai wherever you need to go so review the lecture videos run the jupyter notebooks on collab complete the

[2:23:47] course Project Share your work and exchange feedback back sharing is a very important part because we are learning this all around the world it's important interact with so please participate in the Forum discussions it's not only to

[2:24:02] ask questions but also to help other people and also to just feel motivated that there are so many people around the world who are taking this step which is a a very big step of trying to learn something as complex as deep learning on

[2:24:17] your own on the side while you are already holding a job or already holding already work uh studying something else so sometimes it it's natural to that is where the community can really help you so do try and participate in

[2:24:33] other help other people out the more you help people the more your understanding improves we have a great community and I just want to give a shout out to everybody who has been answering questions on the Forum um and some of

[2:24:47] runs of the course have also been answering so please do help each other out you have the free code Camp Forum you have the Jovian Forum you have um you have the YouTube comments use any format of discussion that you need you

[2:24:59] can always hit us up on Twitter you can reach us on email we are always available to help you out and what to do after this course the one single best thing that you can do is to create more projects on real world data sets and on

[2:25:13] different problems that is the best way to learn learning by doing is the right way so do not try to jump to a different topic immediately do not try to do get into the into the habit of doing more courses try to create projects that is

[2:25:27] the only way you learn so do create projects one other thing you can do is you can go to kaggle and try to participate in a kaggle competition in fact we have a kaggle competition that you can try out and

[2:25:39] we'll share the link in email it is a competition that we conducted 6 months submission to it you can still see how you're doing there do share your knowledge write a blog post write a tutorial or just

[2:25:53] answer questions on the Forum or we are also inviting people to create videos on put in a lot of work a lot of effort into your course project so we will be inviting people to create videos on the course project which we will then be

[2:26:06] sharing on social media and YouTube and on newsletters and so on so definitely if you're interested just let us know on the Forum or just write to us uh tweet at us and we will uh we will reach out to you and help you set it up

[2:26:20] and then once you have done enough work in this domain once you have also created some public repository of your projects and you can put them up on Jovian you can share on the free code Camp Forum you can share them on GitHub

[2:26:33] you can write blogs only then should you go and U do more courses U but if you Concepts that we've covered then few courses that I will

[2:26:45] deeplearning.ai which is a more theoretical course but it it definitely theoretical aspects and all the mathematics behind deep learning if you want to go there although it's not entirely necessary another great course

[2:26:59] entirely necessary another great course is fast.ai now fast.ai is a course built a much higher level interface where you do not have to write a lot of code with just about five six lines of code you can train a deep learning model very

[2:27:14] easily and uh it is a very versatile library and it's a great course as well so do check out fast. A2 so with that I will see you on the forums and zero.com is the course website where you can find all the

[2:27:28] lessons all the videos all the material all the assignments and you can also find the link to the Forum there you can find us on Twitter on @ freecode Camp Jovian ML and I am akashian is on

[2:27:42] Twitter and I have one final an announcement to make so our next course is on data structures and algorithms in Python this is a really useful course if you are looking to improve your coding

[2:27:55] skills if you're looking to understand more about computer science theory if you've picked up some python but you don't really know how maps and lists and different algorithms within python work it is also really useful from the

[2:28:09] perspective of interviews so no matter which role you're applying for you are where you will be asked to code something like binary search or uh b or

[2:28:22] traversal of a graph or sorting algorithms and things like that so this is a great course for to learn those things as well and we will have a lot of exercises which will ultimately be quite similar to the kind

[2:28:36] of questions that you will get asked in coding tests and interviews so definitely do go to py algorithms. comom and enroll for the course the course will be starting sometime in January so with that

[2:28:51] this is Akash signing off on behalf of free code camp and Jovian I hope to see you soon in the meantime continue learning continue on the Forum all the

[2:29:06] Forum all the best good luck and goodbye

More from freeCodeCamp.org

View all

⚡ Saved you 2h 29m reading this? Transcribe any YouTube video for free — no signup needed.