-: Hello, and welcome to this Python tutorial.
So now the next step is to make that count neurons function
which will give us what we want,
that is, this number of neurons
and this huge vector after the convolutions are applied.
That's the only missing information we need right now,
and we are gonna get it with a function.
So let's make this function.
We are going to call it count_neurons very simply.
And what is this count neurons function going
to take as arguments?
Well, it is going to take the object self,
but then it's going to take something else,
because this number of output neurons
in the flattening layer actually only depends on one thing,
it depends on the dimensions of the original input image,
the one that goes at the very beginning
of the neural network.
And so the only argument we need right now,
is actually these dimensions,
the dimensions of the input images.
Therefore, let's give a name
to this argument representing the dimensions
of the input image.
And we are gonna call it image dim.
Alright.
And I can tell you right now that the actual dimensions
of the input images coming from doom are gonna be 80 by 80.
We're gonna reduce the size of the original images
to 80 by 80, and that's gonna be the format
of the images going into the neural network.
So image dim is actually going to be one, 80, 80,
and the one corresponds to the fact
that we're working with black and white images.
That is with only one channel.
So image dim is going to be equalated
to the tuple one, 80 and 80.
Alright. So that's the only argument we need.
And now let's count the neurons.
So how are we going to do that?
Well, first of all,
we actually don't have any input image right now.
We don't have any doom image that we can import.
We're gonna do that later.
So the first thing we have to do is create a fake image,
but that has dimensions 80 by 80.
We're gonna create that fake image with fake pixels,
and that will still give us
eventually the number that we want,
because that number only depends on the dimensions,
and not on the pixels that are inside the images.
So let's just create a fake image to start,
and then we will compute the number of neurons that we want.
So the trick to create a fake image is, well,
we are gonna call it X, first of all,
and then we are gonna use the torch.rand
because you know we're going to put some random pixels
in this images.
So we're using this random functions from torch,
which is the rand function.
Then inside we're gonna input, as you can see,
the dimensions of the images, that is one, 80, 80.
But since we are going to input this image
into the neural network, and as you remember,
the neural network can only accept batches of input states,
that is here, batches of input images,
we are going to create that fake dimension
which we can directly do in this rand function.
We actually just need to start with a one,
that will correspond to the batch,
and then we can just put the tuple, one, 80, 80,
corresponding to the dimensions of the input image.
And as you understood, these dimensions are contained
in this image dim argument,
which represents that tuple one, 80, 80.
So now we just need to add image dim,
but in order to pass the elements of a tuple,
because you know right now image dim is a tuple,
as a list of arguments of a function,
we need to add here before image dim,
that is before the tuple, a star.
The star will allow to pass the elements
of the image dim tuple
as a list of arguments for a function.
And as you can see, that's exactly what is specified here
with the star and the dimensions.
Alright. So that will create an image of fake pixels.
So that will have nothing to do with the doom images,
but again, we will still be able to get
the final number of neurons.
And now the last thing that we need to do, remember,
is to convert this input batch vector into a torch variable,
because this is going to go into the neural network.
Alright, so this now represents an input image,
of random pixels,
that was just converted into a torch variable,
and that will now go into the neural network,
and more specifically,
the convolutional layers of the neural network.
Because since we only need the number of neurons
after the convolutions are applied,
we will just go up to the convolution three,
so right after the third convolutional layer,
and we will not go into the two full connections here.
And that's because the number of neurons
that we want is between convolution three and FC1.
Alright, so now that we have one input image
with the right dimensions,
well, it's time to propagate this image
into the neural network to reach the flattening layer.
Then we're gonna get the neurons in the flattening layer,
and we will just get the information that we want,
that is, the number of neurons in this flattening layer.
So now what we have to do
is exactly what we do in a forward function,
we need to propagate the signals into the neural network,
but only in the convolutional layers,
until we reach the flattening layer.
So let's do this.
We're going to update X.
Now X is the input image, and with the second X here,
X will become, well, the first convolutional layer.
And now what we have to do is a three steps process.
First step, we apply the convolution to the input images.
Then second step, we apply max pooling
to the obtained convoluted images.
And then third step,
we activate the neurons in this pooled convoluted images.
And so X will become this first convolutional layer
composed of all these pooled convoluted images.
So let's do this.
First step, apply the first convolution,
convolution one to the input images.
So what we do is take our convolution one,
self.convolutionone, there we go.
We apply it to our input images,
which so far are represented by X.
So that's the first step.
First step done.
Now, second step, we are going to apply max pooling
to our convoluted images returned by convolution 1X.
And to apply max pooling, well,
we're gonna take a function from the functional module.
So we take F the shortcut then dot
and then we're gonna use the function max pool 2D.
That's the one, we put self convolution 1X
in the parenthesis of the max pool 2D function,
because we apply max pooling to the convoluted images.
But this max pooling function takes additional arguments
which are first, the kernel size.
So again, that's the size of the window sliding
through your images,
and that will take the maximum of the pixels in each slide.
So that will still detect the features,
because the features are associated
to a high value of the pixel in the arrays,
as you saw in the intuition lectures.
So this first argument here we need to input
is this kernel size.
And we're gonna take three,
that's a common choice for the kernel size.
And then we need to input the strides, you know,
by how many pixels it's going to slide in the images,
and we are gonna take a stride of two.
Again, that's a common choice.
So there we go.
Now the second step is done.
And now let's move on to the third step,
which is to activate all the neurons in this pooled
and convoluted images in this first convolutional layer.
And to do this, again,
we are going to apply a function to all this
and so here I'm taking F again,
because we're gonna take another function,
which as you might have guessed is going
to be an activation function.
But which one as usual it's going
to be a rectifier activation function,
and maybe you remember the name for that is ReLu.
There we go.
That's the one.
And so we apply ReLU to our pooled convoluted images,
that is all this.
Alright, and that's it.
Three steps done.
That was very quick.
So remember, the way we have to look at this,
is first, we apply the convolution to our input images,
then we apply max pooling to our convoluted images,
obtained with the convolution,
and then we activate the neurons
in all this pooled convolutional layer
with the rectifier activation function.
So perfect, we get our first convolutional layer,
on which was applied max pooling,
and in which the neurons are now activated.
And so basically what it does
is that it propagates the signals
from the first convolutional layer to the next one.
And speaking of the next one,
that's exactly what we're gonna take care of right now.
We are going to do the same thing,
as we just did on the first convolutional layer,
to the second convolutional layer,
to, again, propagate the signals further
into the neural network,
by activating the neurons of the second convolutional layer.
But before doing this,
we need to get this convolutional layer,
and so we are going to apply convolution two to X
that is now the first convolutional layer,
while we are going to apply convolution two to X,
to obtain the second convolutional layer,
after which we will be max pooling it,
and then finally activating its neurons.
So let's do this.
It's actually very easy,
we just need to copy that and paste in that below.
Now, of course, we need to replace convolution one
by convolution two, and there we go.
That's actually ready.
See, very easy.
And so now with this line,
we propagate the signals from the second convolutional layer
to the next one,
which is going to be the third convolutional layer.
And to get the third convolutional layer, well,
we need to apply that again.
So I'm copying this, pasting that below,
and replacing convolution two by convolution three.
And that's done, isn't it so practical?
We propagate the signals in the three convolutional layers
in a flashlight, thanks to this awesome structure.
Alright, so perfect.
Now we have our signals propagated
up to the third convolutional layer, and after,
and speaking of after that leads us
to what we're looking for, what we're interested in,
that is the flattening layer.
Alright, so now that we have our third convolutional layer,
that's the last X here,
it's time to get our flattening layer.
And so that's exactly what we're gonna do now,
we're going to flatten all the pixels
of this third convolutional layer, that is,
we're gonna take all the pixels of all the channels
of the third convolutional layer.
We're gonna put them one after the other in a huge vector,
and, of course, this huge vector is gonna be nothing else
than the flattening layer.
And at the same time, we will use a trick
to get the number of neurons in this flattening layer.
That's exactly what we're looking for,
that's the number of neurons we're missing.
And therefore, let's directly return what we want.
And in this return,
we are going to flatten this third convolutional layer,
and get at the same time the number of neurons
in this flattening layer.
So we're gonna take X,
which is our third convolutional layer,
we're gonna take all the channels
of the third convolutional layer,
and we're gonna use a function,
which is the size function to flatten all the pixels
of all these channels in one same huge vector.
And so the trick, you can find it in the PyTorch tutorial,
while first we take the data of X
because X is a special structure,
you know, it's a torch variable,
so it has a pretty complex structure,
but first we need to access it with data here.
Then we need to view what's inside of it.
So we use this view function
and now we need to access what we're looking for
and that is given with the arguments one and minus one.
You don't have to understand what's inside the structure,
but you can just understand
that this is how we're gonna get this number of neurons.
And then to finish, we need to add size,
then parenthesis and inside we input one.
So basically what we do here,
what we do is, we take all the pixels of all the channels,
and we put them one after the other in this huge vector
which will be the input of the fully connected network.
That's basically what this size one does,
and with this, can get this number of neurons
that we're looking for.
Alright. So now we get what we want.
And so finally, we can replace number neurons here
by what is returned by this function,
when it is applied to the format of the doom images,
that is one by 80 by 80.
So what we have to do now is replace number neurons
by we take the count neurons function,
which we apply to the format of the doom images,
which will be the tuple one, 80 and 80.
And there we go.
And, of course, we don't forget self,
because counts neuron is actually a method of the CNN class.
So we need to add the self,
and now the warning should disappear.
And there we go.
Now everything is good.
We get the architecture of the neural network,
with nothing missing,
and we have this count neurons function,
in case, you know, you want to try some other architectures,
and you don't want to count this number of neurons manually.
You just use this function,
you apply it to the format of your images,
and this will get you directly what you want,
that is the number of neurons in the flattening layer,
without having to do anything
and whatever the architecture is.
So that's pretty cool.
And now we are done with the first big important step
of this brain that we're making,
and we have one last step that is one last function to make,
which is going to be the main forward function.
So we are gonna propagate the signals
from the beginning of the brain, that is,
from the eyes of the AI up to the output layer,
that is after the second pool connection.
So we'll do that in the next tutorial.
And until then, enjoy AI.