Pytorch_About_VGG_Advance_CNN

VGG 모델의 생성과정 살펴보기

모두를 위한 딥러닝 - 파이토치 강의 참고

  • torchvision.models를 통해 VGG11~VGG19까지 이용할 수 있다.

  • 3x224x224 input을 기준으로 만들어져 있으며, input size가 다른경우 모델을 약간 수정해서 사용할 수 있다.

  • 이번에는 VGG에서 layer가 생성되는 과정을 살펴보려고 한다.

  • VGG의 Source Code이며 일부만 가져와서 살펴보자.

  • VGG 모델의 Class선언의 __init__ 부분을 살펴보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class VGG(nn.Module):

def __init__(self, features, num_classes=1000, init_weights=True):
super(VGG, self).__init__()
self.features = features
self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
self.classifier = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, num_classes),
)
if init_weights:
self._initialize_weights()
.
.
.
  • features라는 레이어를 통과하고 pooling and linear layer를 통과하는 모습을 확인할 수 있다.

  • 즉 처음 layer는 features부분에서 생성되는데 이는 make_layers라는 함수를 통해 이루어진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def make_layers(cfg, batch_norm=False):
layers = []
in_channels = 3
for v in cfg:
if v == 'M':
layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
else:
conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
if batch_norm:
layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)]
else:
layers += [conv2d, nn.ReLU(inplace=True)]
in_channels = v
return nn.Sequential(*layers)

cfgs = {
'A': [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'B': [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'],
'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'E': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'],
}
  • make_layers함수를 살펴보면 cfg값에 따라서 알맞는 layer를 return하고 있다.

  • cfgs에서 ‘A’값을 받았을때 어떻게 Convolution layer가 만들어지는지 따라가보자.

1
2
3
4
5
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
순차적으로 'A'의 값이 for문을 통해 들어가면 layers에 어떻게 layer가 쌓이는지 누적시키며 따라가보자.
(batch_norm=False)인 상황이다.
1. 처음에 64 값을 받으면,
layers = [
conv2d= nn.Conv2d(3, 64, kernel_size=3, padding=1)
nn.ReLU(inplace=True)
]
가 되며 in_channels가 입력받은 64로 바뀌게된다!

2. 'M' 을 입력받으면, MaxPool2d가 들어가며 in_channels값은 바뀌지 않는다.
layers = [
conv2d= nn.Conv2d(3, 64, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)
]

3. 다시 128 값을 받으면, 처음 64를 입력받았을때와 마찬가지로 ```Conv2d```와 ```ReLU```가 추가되며 in_channels는 128로 바뀌게된다.
layers = [
conv2d= nn.Conv2d(3, 64, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(64, 128, kernel_size=3, padding=1)
nn.ReLU(inplace=True)
]

4. 다음으로 'M'을 입력받으면, 두번째 단계와 마찬가지로 MaxPool2d가 들어가고 in_channels는 유지된다.
layers = [
conv2d= nn.Conv2d(3, 64, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(64, 128, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)
]

5. 다음으로 256 값을 두번 연속해서 받으면, 첫번째 단계가 두번 실행되는것과 같다.
layers = [
conv2d= nn.Conv2d(3, 64, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(64, 128, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(128, 256, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

conv2d= nn.Conv2d(256, 256, kernel_size=3, padding=1)
nn.ReLU(inplace=True)
]

6. 세번째 'M'을 입력받아서 다음과 같다.
layers = [
conv2d= nn.Conv2d(3, 64, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(64, 128, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(128, 256, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

conv2d= nn.Conv2d(256, 256, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)
]

7. 위의 과정을 통해 익숙해졌으므로 [512, 512, 'M'] 입력을 한번에 살펴보자. 세 개의 입력이 들어오면 다음과 같이 layers가 쌓이게된다.
layers = [
conv2d= nn.Conv2d(3, 64, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(64, 128, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(128, 256, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

conv2d= nn.Conv2d(256, 256, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(256, 512, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

conv2d= nn.Conv2d(512, 512, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)
]

8. 마지막으로 다시 한번 [512, 512, 'M'] 입력을 받는다. 따라서 최종적으로는 다음과 같은 layers가 생성된다.
layers = [
conv2d= nn.Conv2d(3, 64, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(64, 128, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(128, 256, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

conv2d= nn.Conv2d(256, 256, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(256, 512, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

conv2d= nn.Conv2d(512, 512, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)

conv2d= nn.Conv2d(512, 512, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

conv2d= nn.Conv2d(512, 512, kernel_size=3, padding=1)
nn.ReLU(inplace=True)

nn.MaxPool2d(kernel_size=2, stride=2)
]
  • 위의 과정을 따라서 만들어진 모델은 VGG11을 의미하게 되는데, 다음과 같이 계산해 볼 수 있다.

  • make_layers를 통해 만들어진 Convolution layer의 갯수는 8개였다. 그리고 Source Code를 살펴보면 이후에 fully connected layer가 3개있다.

  • 따라서, 위의 과정으로 만들어진 모델은 8 + 3 = 11 로 VGG11 을 의미한다.

  • 이와 마찬가지로, 나머지 모델은 다음과 같다.

1
2
3
'B' --> 10 + 3 = 13 --> VGG13
'C' --> 13 + 3 = 16 --> VGG16
'D' --> 16 + 3 = 19 --> VGG19
  • Source Code를 따라가면서 VGG모델이 생성되는 과정을 살펴볼 수 있었고 다음에는 input size가 다를경우 VGG를 수정해서 사용하는 방법을 살펴볼 것이다.

Full Code

Full Code

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×