52. Implementing InceptionNet From Thesis

■ InceptionNet

I’ve been using this model to run inference on jetson for a while, but I didn’t know what was actually going on inside, so for this time I’ve decided to create the network from scratch using Pytorch.

■ Why Inception ?

The word inception means the beginning of something, so I originally thought that it was named that way because of its unique structure. But it turns out it came from the movie Inception, “we need to go deeper”.

■ Implementation

I’ll be building the model from the actual thesis (Here is the Link). The InceptionNet has many repetitive tasks, so before we jump into initializing the layers, I’m going to first build some blocks which can be generalized.
First, Import torch

import torch
import torch.nn as nn

Block for Convolutional Layer

class conv_block(nn.Module):
    def __init__(self, in_channels, out_channels, **kwargs):
        super(conv_block, self).__init__()
        self.relu = nn.ReLU() #Activation
        self.conv = nn.Conv2d(in_channels, out_channels, **kwargs)
        self.batchnorm = nn.BatchNorm2d(out_channels)


    def forward(self, x):
        return self.relu(self.batchnorm(self.conv(x)))

**kwargs:
I’ll explain later, but inceptionNet has multiple kernel sizes, so I’m setting the parameters for that as **kwargs.

BatchNorm:
This gives 2 additional learnable parameters, which then gives the model the option to normalize the hidden variables or not. This is not implemented in the thesis, but I’m adding this because it will definitely improve the performance.

Forward:
The order is usually conv batchnorm relu. (I don’t see a lot of people bringing the activation before the batch normalization.)

Block for Inception

One of the most unique features of the model is that it uses several kernel sizes. You never know which kernel size works best, so this model uses 3 different sizes to get the best performance.
By using the 1×1 convolutions you can adjust the number of channels, and this helps when dividing/concatenating the 4 different routes.
Since we’ve made our Block for a single Convolution in the previous step, we’ll be using that to create this network.

class Inception_block(nn.Module):
    # There are 4 routes, so I'm naming each of those routes as a 'branch'
    # Set the number of channels for input and output for each 'branch'

    # red_ : channel reduction = 1x1 conv
    def __init__(self, in_channels, out_1x1, red_3x3, out_3x3, red_5x5, out_5x5, out_1x1pool):
        super(Inception_block, self).__init__()
        self.branch1 = conv_block(in_channels, out_1x1, kernel_size=1)
        self.branch2 = nn.Sequential(
            conv_block(in_channels, red_3x3, kernel_size=1),
            conv_block(red_3x3, out_3x3, kernel_size=3, stride=1, padding=1)
        )
        self.branch3 = nn.Sequential(
            conv_block(in_channels, red_5x5, kernel_size=1),
            conv_block(red_5x5, out_5x5, kernel_size=5, stride=1, padding=2)
        )
        self.branch4 = nn.Sequential(
            nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
            conv_block(in_channels, out_1x1pool, kernel_size=1, stride=1)
        )

    def forward(self, x):
        # Output dimensions are..(Batch_size, channel, width,height)
        # All routes will be concatenated with the 'channel' axis.
        #  Index number for 'channel' is 1 so let's assign that when concat 
        return torch.cat([self.branch1(x), self.branch2(x), self.branch3(x), self.branch4(x)], 1)

Initializing the Layers

I’ll be initializing all the layers following the table from the thesis.

class InceptionNet(nn.Module):
    def __init__(self, in_channels=3, num_classes=1000):
        super(InceptionNet, self).__init__()

        self.conv1 = conv_block(in_channels=in_channels, out_channels=64, kernel_size=(
            7, 7), stride=(2, 2), padding=(3, 3))
        self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
        self.conv2 = conv_block(
            64, 192, kernel_size=(3, 3), stride=1, padding=1)
        self.maxpool2 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)

        #Inception_block(in_channels, out_1x1, red_3x3, out_3x3, red_5x5, out_5x5, out_1x1pool)
        self.inception3a = Inception_block(192, 64, 96, 128, 16, 32, 32)
        self.inception3b = Inception_block(256, 128, 128, 192, 32, 96, 64)

        self.maxpool3 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)

        self.inception4a = Inception_block(480, 192, 96, 208, 16, 48, 64)
        self.inception4b = Inception_block(512, 160, 112, 224, 24, 64, 64)
        self.inception4c = Inception_block(512, 128, 128, 256, 24, 64, 64)
        self.inception4d = Inception_block(512, 112, 144, 288, 32, 64, 64)
        self.inception4e = Inception_block(528, 256, 160, 320, 32, 128, 128)

        self.maxpool4 = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)

        self.inception5a = Inception_block(832, 256, 160, 320, 32, 128, 128)
        self.inception5b = Inception_block(832, 384, 192, 384, 48, 128, 128)

        self.avgpool = nn.AvgPool2d(kernel_size=7, stride=1)
        self.dropout = nn.Dropout(p=0.4)
        self.fc1 = nn.Linear(1024, 1000)

Forward Function

Set the layers in order inside the InceptionNet class

def forward(self, x):
        x = self.conv1(x)
        x = self.maxpool1(x)
        x = self.conv2(x)
        x = self.maxpool2(x)

        x = self.inception3a(x)
        x = self.inception3b(x)

        x = self.maxpool3(x)

        x = self.inception4a(x)
        x = self.inception4b(x)
        x = self.inception4c(x)
        x = self.inception4d(x)
        x = self.inception4e(x)

        x = self.maxpool4(x)

        x = self.inception5a(x)
        x = self.inception5b(x)
        x = self.avgpool(x)
        x = x.reshape(x.shape[0], -1)
        x = self.dropout(x)
        x = self.fc1(x)
        return x

Check Implementation

If you’ve done all the processes correctly you’ll get the dimension of the tensor when you run the code below

x = torch.randn(3, 3, 224, 224)
    model = InceptionNet()
    print(model(x).shape)  


# OUTPUT:torch.Size([3, 1000])