1+ import os
2+ import urllib .request
3+ from types import SimpleNamespace
4+ from urllib .error import HTTPError
5+
6+ import lightning as L
7+ import matplotlib
8+ import matplotlib .pyplot as plt
9+ import matplotlib_inline .backend_inline
10+ import numpy as np
11+ import seaborn as sns
12+ import tabulate
13+ import torch
14+ import torch .nn as nn
15+ import torch .optim as optim
16+ import torch .utils .data as data
17+ import torchvision
18+
19+ % matplotlib inline
20+ from IPython .display import HTML , display
21+ from lightning .pytorch .callbacks import LearningRateMonitor , ModelCheckpoint
22+ from PIL import Image
23+ from torchvision import transforms
24+ from torchvision .datasets import CIFAR10
25+
26+ matplotlib_inline .backend_inline .set_matplotlib_formats ("svg" , "pdf" ) # For export
27+ matplotlib .rcParams ["lines.linewidth" ] = 2.0
28+ sns .reset_orig ()
29+
30+
31+ class GoogleNet (nn .Module ):
32+ def __init__ (self , num_classes = 10 , act_fn_name = "relu" , ** kwargs ):
33+ super ().__init__ ()
34+ self .hparams = SimpleNamespace (
35+ num_classes = num_classes , act_fn_name = act_fn_name , act_fn = act_fn_by_name [act_fn_name ]
36+ )
37+ self ._create_network ()
38+ self ._init_params ()
39+
40+ def _create_network (self ):
41+ # A first convolution on the original image to scale up the channel size
42+ self .input_net = nn .Sequential (
43+ nn .Conv2d (3 , 64 , kernel_size = 3 , padding = 1 ), nn .BatchNorm2d (64 ), self .hparams .act_fn ()
44+ )
45+ # Stacking inception blocks
46+ self .inception_blocks = nn .Sequential (
47+ InceptionBlock (
48+ 64 ,
49+ c_red = {"3x3" : 32 , "5x5" : 16 },
50+ c_out = {"1x1" : 16 , "3x3" : 32 , "5x5" : 8 , "max" : 8 },
51+ act_fn = self .hparams .act_fn ,
52+ ),
53+ InceptionBlock (
54+ 64 ,
55+ c_red = {"3x3" : 32 , "5x5" : 16 },
56+ c_out = {"1x1" : 24 , "3x3" : 48 , "5x5" : 12 , "max" : 12 },
57+ act_fn = self .hparams .act_fn ,
58+ ),
59+ nn .MaxPool2d (3 , stride = 2 , padding = 1 ), # 32x32 => 16x16
60+ InceptionBlock (
61+ 96 ,
62+ c_red = {"3x3" : 32 , "5x5" : 16 },
63+ c_out = {"1x1" : 24 , "3x3" : 48 , "5x5" : 12 , "max" : 12 },
64+ act_fn = self .hparams .act_fn ,
65+ ),
66+ InceptionBlock (
67+ 96 ,
68+ c_red = {"3x3" : 32 , "5x5" : 16 },
69+ c_out = {"1x1" : 16 , "3x3" : 48 , "5x5" : 16 , "max" : 16 },
70+ act_fn = self .hparams .act_fn ,
71+ ),
72+ InceptionBlock (
73+ 96 ,
74+ c_red = {"3x3" : 32 , "5x5" : 16 },
75+ c_out = {"1x1" : 16 , "3x3" : 48 , "5x5" : 16 , "max" : 16 },
76+ act_fn = self .hparams .act_fn ,
77+ ),
78+ InceptionBlock (
79+ 96 ,
80+ c_red = {"3x3" : 32 , "5x5" : 16 },
81+ c_out = {"1x1" : 32 , "3x3" : 48 , "5x5" : 24 , "max" : 24 },
82+ act_fn = self .hparams .act_fn ,
83+ ),
84+ nn .MaxPool2d (3 , stride = 2 , padding = 1 ), # 16x16 => 8x8
85+ InceptionBlock (
86+ 128 ,
87+ c_red = {"3x3" : 48 , "5x5" : 16 },
88+ c_out = {"1x1" : 32 , "3x3" : 64 , "5x5" : 16 , "max" : 16 },
89+ act_fn = self .hparams .act_fn ,
90+ ),
91+ InceptionBlock (
92+ 128 ,
93+ c_red = {"3x3" : 48 , "5x5" : 16 },
94+ c_out = {"1x1" : 32 , "3x3" : 64 , "5x5" : 16 , "max" : 16 },
95+ act_fn = self .hparams .act_fn ,
96+ ),
97+ )
98+ # Mapping to classification output
99+ self .output_net = nn .Sequential (
100+ nn .AdaptiveAvgPool2d ((1 , 1 )), nn .Flatten (), nn .Linear (128 , self .hparams .num_classes )
101+ )
102+
103+ def _init_params (self ):
104+ # Based on our discussion in Tutorial 4, we should initialize the
105+ # convolutions according to the activation function
106+ for m in self .modules ():
107+ if isinstance (m , nn .Conv2d ):
108+ nn .init .kaiming_normal_ (m .weight , nonlinearity = self .hparams .act_fn_name )
109+ elif isinstance (m , nn .BatchNorm2d ):
110+ nn .init .constant_ (m .weight , 1 )
111+ nn .init .constant_ (m .bias , 0 )
112+
113+ def forward (self , x ):
114+ x = self .input_net (x )
115+ x = self .inception_blocks (x )
116+ x = self .output_net (x )
117+ return x
0 commit comments