본문 바로가기

Deep Learning for Computer Vision

EECS 498-007 / 598-005 Lecture 8 : CNN Architectures

이전 시간에는 Convolution Network의 구성 요소들에 대해서 배웠다.

이번 시간에는 이 구성 요소들을 어떻게 조합할지에 대한 것인 CNN 아키텍처에 대해서 배워볼 것이다.

 

먼저 CNN의 큰 발전을 이끈 ImageNet Classification Challenge를 따라가며 살펴볼 것이다.

대회의 초창기였던 2010년과 2011년 모두 신경망 모델이 아니라 임의로 조합하고 임의로 선정한 feature로 구성된 'rule'기반 다층의 레이어를 쌓고 마지막으로 Linear Classifier를 쌓은 모델을 사용했지만, 2012년 CNN 아키텍처인

AlexNet이 엄청난 격차를 보여주면서 Convolution Network는 컴퓨터 비전의 전면에 서게 되었다.

AlexNet은 오늘날 딥러닝에서 쓰이는 모델만큼은 아니지만 그래도 충분히 'Deep'하다고 말할 수 있는 크기의 모델이다. 또한 Activation으로 Relu를 처음 사용한 모델 중 하나이기도 하다.

그리고 normalization 요소로 'Local response normalization'이란 것도 사용했는데, Batch norm의 등장 이전에나

사용되었던 기술로 오늘날엔 전혀 쓰지 않는 기술이다.

 

AlexNet의 인용 횟수가 다윈의 종의 기원의 인용 횟수에 맞먹는 것을 보면, AlexNet이 머신러닝 분야에 얼마나 큰 영향을

끼쳤는지, 알 수 있다. 

AlexNet에서 각 레이어의 크기나 Hyperparameter, 혹은 요구 메모리 등등을 계산하면 위 슬라이드처럼 된다.

계산은 이전 강의에서 배웠던 걸 응용해서 하는데, 정리하기엔 너무 길어서 그냥 생략했다. 강의 보면 차근차근

계산해가며 표를 채워 나가니 좀 더 자세히 알고 싶다면 보는 걸 추천한다. 그리고 슬라이드에서 Conv Layer와 Pooling Layer 사이에 Relu Layer가 있지만, 생략했다고 한다. Relu에서는 Flop이 없어서 생략했지 않나 싶다.

 

어쨌든 머신 러닝에서 Floating Point Operations, 속칭 FLOPS는 부동 소수점 연산의 횟수를 나타내는데

모델이 얼마나 Computing 자원을 필요로 하는지를 나타내는 역할을 하기에 이를 헤아리는 것은 매우 중요하다.

그래서 한 가지 유의할 점이 있는데, 부동 소수점 연산은 덧셈과 곱셈이 한 사이클에 한 번에 수행되므로 횟수를 헤아릴 때, 둘 다 합쳐서 하나의 연산으로 봐야 한다고 한다.

어떻게 그렇게 되는지 자세히는 안 알려주는데, 9강에서 GPU의 텐서 코어가 행렬 곱과 덧셈을 한 사이클에 수행한다고 했었는데 이것 때문일려나? 뭐 그냥 그렇다고만 알면 될 거 같다.

 

그리고 Pooling Layer에서의 Flops는 Convolution Layer와 비교했을 때 무시해도 문제없을 정도로 적어서 사실은 0이 아니지만 그냥 0으로 처리하는 경우가 많다고 한다.

 

AlexNet은 수많은 시행착오를 통해서 아키텍처가 완성되었다. 그래서 사람들은 많은 시행 착오 없이 아키텍처를 

개발해내고 싶었고, 결국 아키텍처 설계에 도움을 줄 만한 Convolution Network의 공통적인 특징들을 발견해냈다.

 

  1. 모델 초반부의 Convolution Layer 들에서 높은 spatial resolution과 상당히 많은 수의 필터들로 인한 대용량의 activation map을 저장해야하기에 모델 초반부에 메모리 소비가 집중된다.
  2. Convolution Neural Network의 대부분의 parameter는 Fully-Connected Layer에서 사용된다.
  3. 대부분의 부동 소수점 연산은 Convolution Layer에서 일어난다.

그래서 앞으로 알아볼 아키텍처에서는 이러한 특징들을 처리하는 요소들이 존재한다.

 

2013년의 ImageNet Challenge에서는 AlexNet과 동일한 레이어 수를 가진 ZFNet이 좋은 성과를 거두었는데, ZFNet은 AlexNet의 각 레이어를 튜닝한 모델로

Conv1에서 stride를 감소시키고, Conv3,4,5에서는 필터의 수를 증가시키는 등의 방법으로 더 높은 spatial resolution을 얻어 성능을 개선했다. 하지만 이때까지도 아키텍처를 설계할 때, 특별한 원리나 방법을 적용하지 않고

시행착오를 통해서 아키텍처를 설계해 나갔다.

 

2014년엔 드디어 principal design을 가진 아키텍처인 VGG가 등장했다.

 

이전까지의 AlexNet과 ZFNet은 특별한 원리 없이 시행착오를 통해서 완성되었고, 그래서 모델의 규모를 조절하기란

쉽지 않은 일이었다. 하지만 VGG에서는 모든 Conv Layer는 3 x 3의 크기에 1 stride, 1 pad를 가지며, 모든 Pooling Layer는 2 x 2 크기와 2 stride를 가진 Max Pooling이며, Pooling Layer를 통과하면 채널의 수를 두 배로 증가시켰다.

그리고 모델을 구성할 때, 몇 개의 Conv Layer와 Pooling Layer로 묶어 stage를 만들어 stage를 가지고 모델을 구성했다.

 

이러한 principal design을 적용해 여러 가지 뛰어난 성능의 VGG 모델들이 만들어졌는데

대표적으로 VGG16과 VGG19가 있다.

 

 

지금부터는 VGG의 principal design이 어째서 뛰어난 성능을 발휘하는지 알아볼 것이다.

먼저 왜 모든 Conv Layer가 3 x 3일까? 

5 x 5 크기와 7 x 7 크기의 Conv Layer와 동일한 receptive field를 가지려면 3 x 3 크기의 Conv Layer는 각각 2개, 3개만 있으면 충분하며, 더 적은 Flops를 요구한다. 그리고 Conv Layer 사이에는 Activation으로 Relu가 들어가는데, 그래서

Conv Layer 1개보다 여러 개를 사용하면 더 많은 Nonlinearity를 가진다.

즉, 3 x 3 Conv Layer를 사용하면 더 뛰어난 성능을 더 적은 비용으로 얻을 수 있게 된다.

그렇다면 왜 모든 Pooling Layer는 2 x 2 크기의 커널에 2 stride, 0 pad인 Max Pooling일까?

그리고 왜 Pooling Layer를 지나면 채널의 수를 두 배로 할까?

 

슬라이드의 좌측 하단에 Pooling Layer 전 후의 Convolution Layer의 정보가 나와있는데,

좌측은 이전 stage의 Conv Layer, 우측은 이후 stage의 Conv Layer이다.

좌측과 우측을 비교해보았을 때, 우측이 좌측보다 Parameter의 수는 4배 더 많은데 메모리 소비는 절반에 불과하고

Flops는 동일한 것을 알 수 있다.

3 x 3 Conv Layer를 사용하는 것과 마찬가지로 더 뛰어난 성능을 더 적은 비용으로 얻을 수 있는 것을 알 수 있다.

 

그리고 이러한 VGG의 principal design은 VGG 이후의 많은 Conv Net에서 이어진다.

 

위 슬라이드는 AlexNet과 VGG-16을 비교한 것으로 수많은 시행착오를 통해 완성된 AlexNet과 달리 VGG는 

principal design을 통해 더 'Deep'하고 뛰어난 성능의 모델을 효율적으로 만들어낼 수 있음을 보여준다.

2014년엔 principal design을 적용한 모델로 VGG 말고도 GoogLeNet도 개발되었는데, 

GoogLeNet은 딥러닝 모델의 높은 비용으로 인한 문제를 처리하기 위해 효율성에 중점을 두고 개발되었다.

 

 

 

GoogLeNet이 가져온 몇 가지 혁신이 있는데

  1. Aggressive Stem. 모델의 초반부의 거대한 feature map을 처리하기 위해 모델의 시작 부분에 Stem Network를      사용해서 급격한 Down Sampling을 통해서 Input의 spatial resolution을 감소시킨다.

  2. Inception Module. 모델이 더 'Deep' 하게 된다고 해서 'Inception'이라는 이름이 붙었으며, Inception 모듈은

     'parellel branches of computation' 아이디어를 적용한 것으로 Convolution Layer의 커널 사이즈를 임의로

     선정하기보다는 여러 개의 커널 사이즈를 적용한 Conv Layer를 병렬적으로 사용했다. 또한 이전의 레이어에서

     데이터를 받으면 1 x 1 Conv Layer로 채널의 수를 줄였는데, 이에 대해서는 바로 다음에 다룰 ResNet에서 좀 더

     자세히 다룬다. 그리고 GoogLeNet을 구성할 때, 이 Inception 모듈을 VGG에서 stage를 사용한 것처럼 모델 전체에

     걸쳐 여러 번 사용했다. 

  3 Global Average Pooling. 이전의 VGG와 AlexNet에서는 모델 후반부의 Fully-Connected Layer에서 매우 많은            parameter가 사용되었다. 그래서 GoogLeNet에서는 Flatten Layer를 통하여 데이터를 벡터로 만드는 것이 아니라, 

  각  feature vector의 평균만 남기는 global average pooling을 통하여 벡터로 만들어 내었다. 즉, 이전에는 

  Fully-Connected Layer에서 7 x 7 spatial resolution을 처리했다면 global average poolng을 통하여 1 x 1 크기로

  감소시켜 Fully-Connected Layer의 크기를 크게 줄일 수 있었다.

Batch norm 이전의 모델들은 공통적으로 10개의 레이어 이상의 깊이에서는 모델을 제대로 학습시키기란 매우 어려운 일이었다. 그래서 종종 이를 위해 특별한 방식을 도입하곤 했는데, vGG의 경우 11 레이어 크기의 모델을 학습한 후에, 

학습된 레이어 사이사이에 새로운 레이어를 집어넣는 식으로 모델의 크기를 키워 나갔으며 GoogLeNet의 경우

'Auxiliary Classifier' 란 것을 사용했다. GoogLeNet에서는 모델의 마지막 부분에만 Classifier가 있는 것이 아니라

모델 중간중간에 avg pooling Layer와 Fully-Connected Layer로 구성된 Classifier를 집어넣었다. 그리고 여기서 나온 Loss와 gradient를 back propagation 과정에서 활용하는 식으로 학습을 진행해나갔다.

2015년은 머신 러닝 분야에서 큰 발전이 있었던 해인데, 먼저 Batch Normalization이 도입되어 딥러닝 모델에서

Auxiliary Classifier와 같은 특이한 테크닉을 사용하지 않게 되었으며, Neural Network에서 혁신을 가져다준 Residual Network, 줄여서 ResNet이 만들어졌다. ResNet 이전의 딥러닝 모델이라고 해봤자 레이어 100개는커녕, 50개도 넘지

않았으나,, ResNet은 무려 152개의 레이어를 사용했다.

Batch  Normalization을 통해서 사람들은 이제 10개가 넘는 레이어의 모델을 쉽게 학습시킬 수 있었다. 그런데 레이어를

일정 수준 이상 쌓으면, 더 'Deep'한 모델이 성능이 안 좋은 것을 발견했고, 처음에는 overfitting으로 인식했다. 하지만

train error와 test error 모두 안 좋은 것을 통해 학습을 방해하는 무언가 때문에 underfitting 문제가 있는 것을

알게 되었다.

레이어가 56개인 모델과 20개의 레이어를 가진 모델이 있다고 할 때, 56개의 레이어를 가진 모델의

첫 20개의 레이어는 20개의 레이어를 가진 모델을 통째로 복사하고 나머지 레이어는 identity function 역할만 하면

되기에 이론적으로 56개의 레이어의 모델은 최소한 20개 레이어의 모델만큼의 성능은 보장된다. 그런데 그러지 

못했다는 것은 optimization에서 문제가 발생했다는 소리이다.

그래서 ResNet에서는 필요한 것보다 레이어가 더 많은 경우에 남는 레이어를 identity function의 역할을 하기

더 쉽도록 아키텍처를 설계했다.

좌측이 VGG에서 적용되던 block이고 우측이 ResNet에서 적용된 'Residual Block'이다. residual bock에서는

두 번째 relu가 적용되기 전에 add gate를 통해 두 번째 Conv Layer의 결과와 block의 입력값을 더해준 후에, relu를

적용했다. 이렇게 하면, 두번째 Conv Layer의 결과가 0이면 identity function과 동일한 block이 되므로

blcok이 identity function의 역할을 쉽게 수행할 수 있게 되었다.

ResNet은 이러한 residual block과 함께 VGG의 principal design과 GoogLeNet이 가져온 혁신으로 구성되었다.

ResNet에서는 모델을 VGG에서와 같이 여러 stage로 나누고 각 stage에서의 spatial resolution과 channel의 변화를

주었으며, 3 x 3 Conv로 각 stage를 구성했다.

또한 GoogLeNet에서처럼 aggressive stem과 avg pooling을 사용했다.

이러한 기법들을 통해서 ResNet에서는 input size와 각 stage에서의 block 수만 조절하면 상대적으로 매우 적은 Flops와 error를 가진 모델을 만들 수 있다.

ResNet에서는 ResNet-18이나 ResNet34와 같이 상대적으로 얕은 모델에서는 'Basic Residual block'을 사용하는데,

더 깊은 모델을 만들 때는 'Bottleneck Residual block'을 사용한다. Bottleneck residual block에서는 3 x 3 Conv 2개를 

사용하는 대신, 총 3개의 1 x 1, 3 x 3, 1x 1 Conv를 사용하는데, 처음의 1 x 1 Conv에서는 채널의 수를 1/4로 줄이고,

마지막 1 x 1 Conv에서 다시 채널의 수를 원래 크기로 늘린다. ResNet에서는 이 방법을 통해 더 많은 Non-Linearity와 sequential computation을 더 적은 Flops를 통해 얻을 수 있게 되었다. 

여러 버전의 ResNet을 비교한 표인데, ResNet-50은 ResNet-34에서의 basic block을 bottleneck block으로 변경한

것인데 그것만으로 소폭의 Flops를 희생하는 것만으로 error가 상대적으로 적어진 것을 볼 수 있다. 또한 ResNet-101과

ResNet-152 모두 각 stage에서의 block을 증가시킨 것으로 ResNet 이전과 달리 더 깊은 모델이 더 잘 작동하는 것을

볼 수 있다. 

그리고 ResNet은 ImageNet Challenge 말고도 여러 대회에서 우수한 성능을 뽐내며 컴퓨터 비전의

여러 분야에서 baseline 모델이 되었다.


ResNet에서 batch norm과 relu의 순서를 변경하면 성능이 소폭 개선되지만 그다지 많이 쓰이지는 않는다고 한다.

위 슬라이드는 여러 모델을 비교한 그래프인데 VGG의 경우 많은 메모리와 연산이 드는 것에 비해 성능이 우월하지는

않은 것을 볼 수 있으며, GoogLeNet의 경우 효율적이지만 성능이 안 좋은 것을 볼 수 있다. 또한 AlexNet은 적은 수의

연산이 필요한 만큼 성능도 낮은 것을 볼 수 있으며, ResNet은 적절한 효율성에 적절한 성능을 가진 것을 볼 수 있다.

2016년에는 이전처럼 혁신적인 시도보다는 이전까지의 모델을 이용한 앙상블 방식의 모델이 많이 쓰였었다.

그리고 ResNet을 개선하려는 시도가 몇몇 있었는데, bottleneck block을 G만큼 병렬적으로 사용하는 ResNext 모델이 

탄생되었다. ResNext에서는 단순히 병렬적으로 사용하는 것이 아니라 1 x 1 Conv에서 채널의 1/4로 축소하는 것이

아니라 'c' 만큼 축소했는데 9Gc^2 + 8GCc - 17C^2 = 0이라는 Flops 수를 구하는 방정식으로 통해서 임의로 정한 C와 G를 이용했을 때, 기존의 bottleneck residual block과 동일한 연산이 수행되는 c를 구해 그 값으로 c를 정한다고 한다.

다음 슬라이드로 나온 Group Convolution은 시간 관계상 설명 없이 넘어갔는데

다행히 한국어 강의에서 교수님이 설명을 해주셨다.

Grouped Convolution은 Group의 수만큼 GPU를 병렬적으로 사용하는데, 이때 채널을 GPU의 수만큼 분리해서 

각 GPU별로 학습을 진행한다고 한다.

그리고 ResNext에서 이 방식을 사용한다고 한다.

위 슬라이드에서 그룹을 이용한 ResNext가 동일한 비용으로 더 나은 성능을 얻었다고 되어 있는데,

시간 관계상 자세한 설명 없이 그냥 넘어갔다. 아마 non-linearity 때문이지 않을까 싶다.

2017년에는 Squeeze-and-Excitation Network 개념을 적용한 모델이 좋은 성과를 얻었다고 했는데,

이 역시 아쉽게도 자세한 설명은 생략되었다.

그리고 ImageNet Challenge는 2017년을 마지막으로 대회를 종료하고, 지금은 Kaggle에서 찾아볼 수 있다고 한다.

ImageNet Challenge는 사라졌지만, 대회를 통해 수많은 유익한 아이디어가 나와 지금도 활발히 사용되고 있으며,

대회가 종료되었지만 여전히 사람들은 아키텍처를 개선하려고 하고 있으며,

그중 하나가 Densely Connected Neural Network이다.

이 아키텍처에서는 ResNet과 달리 이전의 feature를 더 하는 게 아니라 concatenate를 해서 block을 구성하여

stage를 구성했다고 한다.

그리고 휴대폰이나 임베디드 환경에서도 조금 더 원활한 작동을 위해 이전과 달리 무조건 높은 성능보다는 성능과

연산량을 타협한 모델인 MobileNet 등의 모델이 만들어졌다.

이 모델은 Depthwise Convolution, Pointwise Convoultion 두 종류의 Conv Layer를 사용한다고 한다.

그리고 모델의 출력으로 아키텍처를 출력하는 모델도 만들어졌는데,

우수한 성능의 모델이 만들어지지만, 매우 엄청난 비용이 소모된다고 한다.

마지막으로 아키텍처를 선택할 때는 새로 설계하기보다는 가져다 쓰는 걸 추천하며 보통은 ResNet-50이나 ResNet-101이

무난하며, 가벼운 사양의 환경에서는 MobileNet이나 ShuffleNet도 괜찮다고 한다.

요약

728x90