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
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