"
]
},
"metadata": {
"tags": []
},
"output_type": "display_data"
}
],
"source": [
"show_at(dsrc.train, 3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can see that it's a `PILImage` of a zero, along with a label of `0`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next we need to give ourselves some transforms on the data! These will need to:\n",
"1. Ensure our images are all the same size\n",
"2. Make sure our output are the `tensor` our models are wanting\n",
"3. Give some image augmentation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"tfms = [ToTensor(), CropPad(size=34, pad_mode=PadMode.Zeros), RandomCrop(size=28)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* `ToTensor`: Converts to tensor\n",
"* `CropPad` and `RandomCrop`: Resizing transforms\n",
"* Applied on the `CPU` via `after_item`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gpu_tfms = [IntToFloatTensor(), Normalize()]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"* ``: Enables GPU usage\n",
"* `IntToFloatTensor`: Converts to a float\n",
"* `Normalize`: Normalizes data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"dls = dsrc.dataloaders(bs=128, after_item=tfms, after_batch=gpu_tfms)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And show a batch"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\nC4zTAAAAAElFTkSuQmCC\n",
"text/plain": [
"
"
]
},
"metadata": {
"tags": []
},
"output_type": "display_data"
}
],
"source": [
"dls.show_batch()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From here we need to see what our model will expect"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"xb, yb = dls.one_batch()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And now the shapes:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(torch.Size([128, 1, 28, 28]), torch.Size([128]))"
]
},
"execution_count": null,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"xb.shape, yb.shape"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"10"
]
},
"execution_count": null,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"dls.c"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So our input shape will be a [128 x 1 x 28 x 28] and our output shape will be a [128] tensor that we need to condense into 10 classes"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The Model\n",
"\n",
"Our models are made up of **layers**, and each layer represents a matrix multiplication to end up with our final `y`. For this image problem, we will use a **Convolutional layer**, a **Batch Normalization layer**, an **Activation Function**, and a **Flattening layer**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Convolutional Layer\n",
"\n",
"These are always the first layer in our network. I will be borrowing an analogy from [here](https://adeshpande3.github.io/A-Beginner%27s-Guide-To-Understanding-Convolutional-Neural-Networks/) by Adit Deshpande.\n",
"\n",
"Our example Convolutional layer will be 5x5x1\n",
"\n",
"Imagine a flashlight that is shining over the top left of an image, which covers a 5x5 section of pixels at one given moment. This flashlight then slides crosses our pixels at all areas in the picture. This flashlight is called a **filter**, which can also be called a **neuron** or **kernel**. The region it is currently looking over is called a **receptive field**. This filter is also an array of numbers called **weights** (or **parameters**). The depth of this filter **must** be the same as the depth of our input. In our case it is 1 (in a color image this is 3). Now once this filter begins moving (or **convolving**) around the image, it is multiplying the values inside this filter with the original pixel value of our image (also called **element wise multiplications**). These are then summed up (in our case this is just one multiplication of 28x28) to an individual value, which is a representation of **just** the top left of our image. Now repeat this until every unique location has a number and we will get what is called an **activation** or **feature map**. This feature map will be 784 different locations, which turns into a 28x28 array\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def conv(ni, nf): return nn.Conv2d(ni, nf, kernel_size=3, stride=2, padding=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we can see our `ni` is equivalent to the depth of the filter, and `nf` is equivalent to how many filters we will be using. (Fun fact this always has to be divisible by the size of our image)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Batch Normalization\n",
"\n",
"As we send our tensors through our model, it is important to normalize our data throughout the network. Doing so can allow for a much larger improvement in training speed, along with allowing each layer to learn independantly (as each layer is then re-normalized according to it's outputs)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def bn(nf): return nn.BatchNorm2d(nf)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`nf` will be the same as the filter output from our previous convolutional layer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Activation functions\n",
"\n",
"They give our models non-linearity and work with the `weights` we mentioned earlier along with a `bias` through a process called **back-propagation**. These allow our models to learn and perform more complex tasks because they can choose to fire or activate one of those neurons mentioned earlier. On a simple sense, let's look at the `ReLU` activation function. It operates by turning any negative values to zero, as visualized below:\n",
"\n",
"![](https://miro.medium.com/max/2052/1*DfMRHwxY1gyyDmrIAd-gjQ.png)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From \"A Practical Guide to ReLU by Danqing Liu [URL](https://medium.com/@danqing/a-practical-guide-to-relu-b83ca804f1f7)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def ReLU(): return nn.ReLU(inplace=False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Flattening\n",
"\n",
"The last bit we need to do is take all these activations and this outcoming matrix and flatten it into a single dimention of predictions. We do this with a `Flatten()` module"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Flatten??"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Making a Model\n",
"\n",
"* Five convolutional layers\n",
"* `nn.Sequential`\n",
"* 1 -> 32 -> 10"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"model = nn.Sequential(\n",
" conv(1, 8),\n",
" bn(8),\n",
" ReLU(),\n",
" conv(8, 16),\n",
" bn(16),\n",
" ReLU(),\n",
" conv(16,32),\n",
" bn(32),\n",
" ReLU(),\n",
" conv(32, 16),\n",
" bn(16),\n",
" ReLU(),\n",
" conv(16, 10),\n",
" bn(10),\n",
" Flatten()\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now let's make our `Learner`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"learn = Learner(dls, model, loss_func=CrossEntropyLossFlat(), metrics=accuracy)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can then also call `learn.summary` to take a look at all the sizes with thier **exact** output shapes"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Sequential (Input shape: 128 x 1 x 28 x 28)\n",
"================================================================\n",
"Layer (type) Output Shape Param # Trainable \n",
"================================================================\n",
"Conv2d 128 x 8 x 14 x 14 80 True \n",
"________________________________________________________________\n",
"BatchNorm2d 128 x 8 x 14 x 14 16 True \n",
"________________________________________________________________\n",
"ReLU 128 x 8 x 14 x 14 0 False \n",
"________________________________________________________________\n",
"Conv2d 128 x 16 x 7 x 7 1,168 True \n",
"________________________________________________________________\n",
"BatchNorm2d 128 x 16 x 7 x 7 32 True \n",
"________________________________________________________________\n",
"ReLU 128 x 16 x 7 x 7 0 False \n",
"________________________________________________________________\n",
"Conv2d 128 x 32 x 4 x 4 4,640 True \n",
"________________________________________________________________\n",
"BatchNorm2d 128 x 32 x 4 x 4 64 True \n",
"________________________________________________________________\n",
"ReLU 128 x 32 x 4 x 4 0 False \n",
"________________________________________________________________\n",
"Conv2d 128 x 16 x 2 x 2 4,624 True \n",
"________________________________________________________________\n",
"BatchNorm2d 128 x 16 x 2 x 2 32 True \n",
"________________________________________________________________\n",
"ReLU 128 x 16 x 2 x 2 0 False \n",
"________________________________________________________________\n",
"Conv2d 128 x 10 x 1 x 1 1,450 True \n",
"________________________________________________________________\n",
"BatchNorm2d 128 x 10 x 1 x 1 20 True \n",
"________________________________________________________________\n",
"Flatten 128 x 10 0 False \n",
"________________________________________________________________\n",
"\n",
"Total params: 12,126\n",
"Total trainable params: 12,126\n",
"Total non-trainable params: 0\n",
"\n",
"Optimizer used: \n",
"Loss function: FlattenedLoss of CrossEntropyLoss()\n",
"\n",
"Callbacks:\n",
" - TrainEvalCallback\n",
" - Recorder\n",
" - ProgressCallback"
]
},
"execution_count": null,
"metadata": {
"tags": []
},
"output_type": "execute_result"
}
],
"source": [
"learn.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`learn.summary` also tells us:\n",
"* Total parameters\n",
"* Trainable parameters\n",
"* Optimizer\n",
"* Loss function\n",
"* Applied `Callbacks`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [],
"text/plain": [
""
]
},
"metadata": {
"tags": []
},
"output_type": "display_data"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"