Skip to content

googlenet

GoogleNet

Bases: Module

GoogleNet architecture

Parameters:

Name Type Description Default
num_classes int

Number of classes for the classification task. Defaults to 10.

10
act_fn_name str

Name of the activation function. Defaults to “relu”.

'relu'
**kwargs Any

Additional keyword arguments.

{}

Attributes:

Name Type Description
hparams SimpleNamespace

Namespace containing the hyperparameters.

input_net Sequential

Input network.

inception_blocks Sequential

Inception blocks.

output_net Sequential

Output network.

Returns:

Type Description
Tensor

Output tensor of the GoogleNet architecture

Examples:

>>> from spotpython.light.cnn.googlenet import GoogleNet
    import torch
    import torch.nn as nn
    model = GoogleNet()
    x = torch.randn(1, 3, 32, 32)
    y = model(x)
    y.shape
    torch.Size([1, 10])
Source code in spotpython/light/cnn/googlenet.py
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
class GoogleNet(nn.Module):
    """GoogleNet architecture

    Args:
        num_classes (int):
            Number of classes for the classification task. Defaults to 10.
        act_fn_name (str):
            Name of the activation function. Defaults to "relu".
        **kwargs (Any):
            Additional keyword arguments.

    Attributes:
        hparams (SimpleNamespace):
            Namespace containing the hyperparameters.
        input_net (nn.Sequential):
            Input network.
        inception_blocks (nn.Sequential):
            Inception blocks.
        output_net (nn.Sequential):
            Output network.

    Returns:
        (torch.Tensor):
            Output tensor of the GoogleNet architecture

    Examples:
        >>> from spotpython.light.cnn.googlenet import GoogleNet
            import torch
            import torch.nn as nn
            model = GoogleNet()
            x = torch.randn(1, 3, 32, 32)
            y = model(x)
            y.shape
            torch.Size([1, 10])
    """

    def __init__(self, num_classes: int = 10, act_fn_name: str = "relu", **kwargs):
        super().__init__()
        # TODO: Replace this by act_fn handlers specified in the config file:
        act_fn_by_name = {"tanh": nn.Tanh, "relu": nn.ReLU, "leakyrelu": nn.LeakyReLU, "gelu": nn.GELU}
        self.hparams = SimpleNamespace(
            num_classes=num_classes, act_fn_name=act_fn_name, act_fn=act_fn_by_name[act_fn_name]
        )
        self._create_network()
        self._init_params()

    def _create_network(self):
        # A first convolution on the original image to scale up the channel size
        self.input_net = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=3, padding=1), nn.BatchNorm2d(64), self.hparams.act_fn()
        )
        # Stacking inception blocks
        self.inception_blocks = nn.Sequential(
            InceptionBlock(
                64,
                c_red={"3x3": 32, "5x5": 16},
                c_out={"1x1": 16, "3x3": 32, "5x5": 8, "max": 8},
                act_fn=self.hparams.act_fn,
            ),
            InceptionBlock(
                64,
                c_red={"3x3": 32, "5x5": 16},
                c_out={"1x1": 24, "3x3": 48, "5x5": 12, "max": 12},
                act_fn=self.hparams.act_fn,
            ),
            nn.MaxPool2d(3, stride=2, padding=1),  # 32x32 => 16x16
            InceptionBlock(
                96,
                c_red={"3x3": 32, "5x5": 16},
                c_out={"1x1": 24, "3x3": 48, "5x5": 12, "max": 12},
                act_fn=self.hparams.act_fn,
            ),
            InceptionBlock(
                96,
                c_red={"3x3": 32, "5x5": 16},
                c_out={"1x1": 16, "3x3": 48, "5x5": 16, "max": 16},
                act_fn=self.hparams.act_fn,
            ),
            InceptionBlock(
                96,
                c_red={"3x3": 32, "5x5": 16},
                c_out={"1x1": 16, "3x3": 48, "5x5": 16, "max": 16},
                act_fn=self.hparams.act_fn,
            ),
            InceptionBlock(
                96,
                c_red={"3x3": 32, "5x5": 16},
                c_out={"1x1": 32, "3x3": 48, "5x5": 24, "max": 24},
                act_fn=self.hparams.act_fn,
            ),
            nn.MaxPool2d(3, stride=2, padding=1),  # 16x16 => 8x8
            InceptionBlock(
                128,
                c_red={"3x3": 48, "5x5": 16},
                c_out={"1x1": 32, "3x3": 64, "5x5": 16, "max": 16},
                act_fn=self.hparams.act_fn,
            ),
            InceptionBlock(
                128,
                c_red={"3x3": 48, "5x5": 16},
                c_out={"1x1": 32, "3x3": 64, "5x5": 16, "max": 16},
                act_fn=self.hparams.act_fn,
            ),
        )
        # Mapping to classification output
        self.output_net = nn.Sequential(
            nn.AdaptiveAvgPool2d((1, 1)), nn.Flatten(), nn.Linear(128, self.hparams.num_classes)
        )

    def _init_params(self):
        # We should initialize the
        # convolutions according to the activation function
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, nonlinearity=self.hparams.act_fn_name)
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        x = self.input_net(x)
        x = self.inception_blocks(x)
        x = self.output_net(x)
        return x