참고1
참고2
참고3

1. 동기(Motivation)

2015년 ILSVRC(ImageNet Large Scale Visual Recognition Challenge)에서 우승을 차지한 ResNet에 대해서 소개하려고 한다.
ResNet은 마이크로소프트에서 개발한 알고리즘이다. 그것도 북경연구소의 중국인 연구진이 개발한 알고리즘이다. ResNet의 original 논문명은 "Deep Residual Learning for Image Recognition"이고, 저자는 Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jiao Sun으로 전부 다 중국인이다. 층수에 있어서 ResNet은 급속도로 깊어진다. 2014년의 GoogLeNet이 22개 층으로 구성된 것에 비해, ResNet은 152개 층을 갖는다. 약 7배나 깊어졌다!

위 그림을 보면 네트워크가 깊어지면서 top-5 error가 낮아진 것을 확인할 수 있다. 한마디로 성능이 좋아진 것이다.
그렇다면 단순히 네트워크 깊이만 깊어지만 무조건 성능이 좋아질까? 이것을 확인하기 위해 ResNet 논문의 저자들은 컨볼루션 층들과 fully-connected 층들로 20 층의 네트워크와 56층의 네트워크를 각각 만든 다음에 성능을 테스트해보았다.

위 그래프들을 보면 오히려 더 깊은 구조를 갖는 56층의 네트워크가 20층의 네트워크보다 더 나쁜 성능을 보임을 알 수 있다. 기존의 방식으로는 망을 무조건 깊게 한다고 능사가 아니라는 것을 확인한 것이다. 뭔가 새로운 방법이 있어야 망을 깊게 만드는 효과를 볼 수 있다는 것을 ResNet의 저자들은 깨달았다.

2. Residual Block 제안

여기에서 참조
Network가 깊을 수록 더 좋은 성능을 낼 수 있도록 ResNet의 핵심은 Residual Block을 제안하였다. 아래 그림에서 오른쪽이 Residual Block을 나타낸다. 기존의 망과 차이가 있다면 입력값을 출력값에 더해줄 수 있도록 지름길(shortcut)을 하나 만들어준 것 뿐이다.

왼쪽은 "Plane" layer를 설명하는 그림이고, 오른쪽은 Residual Block을 설명하는 그림이다.
두 구조의 차이점은 한 가지이다. 동일한 연산을 하고 나서 Input인 xx를 더하는 것(Residual Block)과 더하지 않는 것(Plane layer)의 차이이다.
단순하게 Input xx를 더하는 것만으로 layer는 Direct로 학습하는 것 대신에, Skip Connection을 통해 각각의 layer(Block)들이 작은 정보만을 추가적으로 학습하도록 한다. (= 각각의 layer가 배워야 할 정보량을 축소) 즉 기존에 학습된 xx를 추가함으로써 xx만큼을 제외한 나머지 부분(F(X)F(X))만을 학습하면 되므로 학습량이 상대적으로 줄어드는 효과가 있다.
<plain layer의 경우>
레이어의 아웃풋인 Feature vector(Feature Map)을 yy라고 할 때 y=f(x)y=f(x)가 Direct로 학습하는 위의 왼쪽 그림을 설명하는 수식이라고 할 수 있다.
여기에서 아웃풋인 yyxx를 통해 새롭게 학습하는 정보이다. 즉, 기존에 학습한 정보를 보존하지 않고 변형시켜 새롭게 생성하는 정보이다.
이 경우에 Neural Network가 고차원적인 Feature vector로의 Mapping을 학습한다는 개념으로 생각했을 때, 층이 깊어질수록 한번에 학습해야 할 Mapping이 너무 많아져 학습이 어려워 진다.

<Residual Block의 경우>
반대로 오른쪽 그림을 설명하는 수식은 y=f(x)+xy=f(x)+x이다.
여기에서의 yyxx가 그대로 보존되므로 기존에 학습한 정보를 보존하고, 거기에 추가적으로 학습하는 정보를 의미하게 된다. 즉, Output에 이전 레이어에서 학습했던 정보를 연결함으로써 해당 층에서는 추가적으로 학습해야 할 정보만을 Mapping, 학습하게 된다.

좀 더 이해를 돕기 위해 예를 들면 다음의 두 가지 경우에 대해서,
(1) open book이 불가능한 시험
(2) open book이 가능한 시험
(1)의 경우에는 시험의 범위가 많아질수록(= 층이 깊어지고 한번에 학습할 Mapping이 많은 경우) 공부하기가 어려울수가 있으나,
반면에 (2)의 경우에는 이미 배웠던 내용(x)가 제공되기 때문에 추가적으로 학습해야 할 정보만을 공부할 것이다.

그리고 학습이 진행되어 layer의 depth가 깊어질 수록, 즉 학습이 많이 될수록 xx는 점점 출력값 H(x)H(x)에 근접하게 되어 추가 학습량 F(x)F(x)는 점점 작아져서 최종적으로 0에 근접하는 최소값으로 수렴되어야 할 것이다.
다시 말해, H(x)=F(x)+xH(x) = F(x) + x에서 추가 학습량에 해당하는 F(x)=H(x)xF(x) = H(x) - x가 최소값(0)이 되도록 학습이 진행이 된다.
그리고,
H(x)=F(x)+xH(x) = F(x) + x 이므로 네트워크 구조 또한 크게 변경할 필요가 없는데, 단순히 입력에서 출력으로 바로 연결되는 shortcut만 추가하면 되기 때문이다. 또한, 입력과 같은 x가 그대로 출력에 연결되기에 파라미터 수에 영향이 없으며, 덧셈이 늘어나는 것을 제외하면 shortcut 연결을 통한 연산량 증가는 없다.
여기서 H(x) - x를 잔차(residual) 라고 한다. 즉, 잔차를 최소로 해주는 것이므로 ResNet이란 이름이 붙게 된다.
이 외에도 ResNet에는 Skip-Connection(또는 Shortcut-Connection), identity mapping, Pre-Activation등의 특징들이 있는데 바로 이어서 다루도록 한다.

3. ResNet의 구조

ResNet은 기본적으로 VGG-19의 구조를 뼈대로 한다. 거기에 컨볼루션 층들을 추가해서 깊게 만든 후에, shortcut들을 추가하는 것이 사실상 전부다. 34층의 ResNet과 거기에서 shortcut들을 제외한 버전인 plain 네트워크의 구조는 다음과 같다.

위 그림을 보면 알 수 있듯이 34층의 ResNet은 처음을 제외하고는 균일하게 3 x 3 사이즈의 컨볼루션 필터를 사용했다. 그리고 특성맵의 사이즈가 반으로 줄어들 때, 특성맵의 뎁스를 2배로 높였다.

4. ResNet의 성능 비교

논문의 저자들은 과연 shortcut, 즉 Residual block들이 효과가 있는지를 알기 위해 이미지넷에서 18층 및 34층의 plain 네트워크와 ResNet의 성능을 비교했다.

왼쪽 그래프를 보면 plain 네트워크는 망이 깊어지면서 오히려 에러가 커졌음을 알 수 있다. 34층의 plain 네트워크가 18층의 plain 네트워크보다 성능이 나쁘다. 반면, 오른쪽 그래프의 ResNet은 망이 깊어지면서 에러도 역시 작아졌다! shortcut을 연결해서 잔차(residual)를 최소가 되게 학습한 효과가 있다는 것이다.
아래 표는 18층, 34층, 50층, 101층, 152층의 ResNet이 어떻게 구성되어 있는가를 잘 나타내준다.

18-Layer의 경우는 conv2_x에서 2X2, conv3_x에서 2X2, conv4_x에서 2X2, conv5_x에서 2X2, 입력1, 출력1해서 1+2×2+2×2+2×2+2×2+1=181 + 2\times 2+2\times 2+2\times 2+2\times 2+1=18이 된다.

다음 표는 ResNet에서 Layer가 깊을 수록 더 좋은 성능을 보여준다는 것을 나타낸다.

CIFAR-10, CIFAR-100은 머신러닝 용 이미지 분류 데이터셋을 말하며 CIFAR-10 dataset이 10개의 클래스로 분류가 되고 CIFAR-100 dataset이 100개의 클래스로 분류가 된다.
위의 표를 보면 CIFAR-10, CIFAR-100둘다 ResNet의 layer가 깊을 수록 error율(%)이 더 작은 것을 볼 수 있다. baseline과 pre-activation은 바로 다음에 다룰 것이다.

5. ResNet 심화 과정

다음은 ResNet의 주요 구성 요소들을 좀 더 자세하게 살펴보았다.

5.1 Residual Block

ResNet에서는 2개 이상의 Convolutional Layer와 skip-connection을 활용해 하나의 블록을 만들고 그 블록을 쌓아서 네트워크를 만든다. (여기서 BottleNeck 구조는 다루지 않습니다.)
하나의 블록을 블록의 구조와 수식은 아래 그림과 같다.

위 그림의 Residual Block은 ll번 째 블록으로 xlx_l을 입력으로 받고 skip-connection인 h(xl)h(x_l)과 Connvolutional layer F(xl,Wl)F(x_l, W_l)를 통과한 결과의 합으로 yly_l을 출력한다.마지막으로 출력 yly_l을 활성함수를 통과시키면 다음 블록의 입력 xl+1x_{l+1}이 된다.

<Residual Block이 vanishing gradient(기울기 소실)를 피하는 원리>
ll : 현재 layer의 index
LL : 전체 layer의 갯수
WW : 가중치 행렬
FF : Residual Function
ff : Activation Function(ReLU)
hh : Identity Mapping을 위한 Dimension 세팅용 함수
라고 하면,
앞절의 수식에서 활성함수 f(yl)f(y_l)을 identity mapping이라고 가정하면,
xl+1=f(yl)=yl=xl+F(xl,Wl)x_{l+1}=f(y_l)=y_l=x_l+F(x_l, W_l)
xl+1=xl+F(xl,Wl)x_{l+1}=x_l+F(x_l, W_l)
(참고로 identify mapping은 입력으로 들어간 xx가 어떠한 함수를 통과해도 다시 xx가 나오는 것으로 항등함수 F(x)=xF(x)=x가 대표적인 identity mapping에 해당한다.)
(hh도 identity mapping으로 가정했으므로 xx가 그대로 사용된다.)
이 식으로부터 일반화식을 표현하면 다음과 같이 나타낼 수 있다.
xL=xl+i=lL1F(xi,Wi)x_L=x_l+\sum\limits_{i=l}^{L-1}F(x_i, W_i)
Loss function의 gradient의 계산식은 backward propagation chain rule로 부터 아래 식으로 나타낼 수 있다.
εxl=εxLxLxl=εxL(1+xli=1L1F(xi,Wi))\cfrac{\partial\varepsilon}{\partial x_l}=\cfrac{\partial\varepsilon}{\partial x_L}\cfrac{\partial x_L}{\partial x_l}=\cfrac{\partial\varepsilon}{\partial x_L}\left (1+\cfrac{\partial}{\partial x_l}\sum\limits_{i=1}^{L-1}F(x_i,W_i) \right )
위 식에서 우리는 εxl\cfrac{\partial\varepsilon}{\partial x_l}가 두 개 값의 합으로 분해할 수 있다는것을 알 수 있다.
먼저 (1) 앞 부분의 εxL\cfrac{\partial\varepsilon}{\partial x_L}은 weight layer와 무관하게 다이렉트로 전파되는 정보이다. 따라서 정보는 어떤 layer든 같은 정보가 전파된다.
(2) 뒷 부분의 εxLxli=1L1F(xi,Wi)\cfrac{\partial\varepsilon}{\partial x_L}\cfrac{\partial}{\partial x_l}\sum\limits_{i=1}^{L-1}F(x_i,W_i) 은 weight layer를 거쳐 전파되는 정보이다.
backward propagation을 할 때 εxl\cfrac{\partial\varepsilon}{\partial x_l} 이 0이 되기 위해서는 weight layer를 거쳐 역전파되는 값이 -1이 되어야 한다.
실제 학습을 할 때 전체 데이터를 한번에 학습하는것이 아닌 데이터의 일부분씩 학습하는 mini-batch방식이 사용되는데, 모든 mini-batch에서 역전파값이 -1이 되는것은 불가능에 가깝다. 때문에 εxl\cfrac{\partial\varepsilon}{\partial x_l} 은 항상 0이 아닌 어떠한 값을 갖게 되고, 역전파된 값이 0에 가깝게 되는 vanishing gradient가 발생하지 않게 된다.

5.2 Skip-Connection

Skip-Connection을 identity mapping으로 사용하지 않는 경우
이 수식에서 skip-connection인 h(xl)h(x_l)과 활성함수인 f(yl)f(y_l)를 identity-mapping이라고 가정했다. 그렇다면 h(xl)h(x_l)f(yl)f(y_l)이 identity-mapping이 아닌경우는 어떻게 될까?
skip-connection h(xl)h(x_l)h(xl)=λlxlh(x_l)=\lambda_lx_l이라고 가정해 보자.(λ\lambda는 modulating scalar이다. 활성함수 ff는 여전히 identity-mapping이라고 가정한다.)
xl+1=λlxl+F(xl,Wl)x_{l+1}=\lambda_lx_l+F(x_l, W_l)
이 때 앞에서 정리한 수식과 같이 정리하면 다음과 같다.

XL=(i=1L1λi)xl+i=lL1(j=i+1L1λj)F(xi,Wi)X_L=\left (\prod\limits_{i=1}^{L-1}\lambda_i \right )x_l+\sum\limits_{i=l}^{L-1}\left ( \prod\limits_{j=i+1}^{L-1} \lambda_j\right )F(x_i,W_i)

앞장의 식과는 다르게 weight layer와 무관하게 전파되는 정보가 λi\lambda_i의 곱 형태인 i=1L1λi\prod\limits_{i=1}^{L-1}\lambda_i로 나타난다. 따라서 λ\lambda값이 1이 아닌 경우에 layer가 깊어질수록 i=1L1λi\prod\limits_{i=1}^{L-1}\lambda_i의 값은 매우 작거나 매우 커지게 되고, 따라서 weight layer와 무관하게 전파되는 정보가 소실되거나 매우 크게 증폭될 수 있다.
예를 들어 λi\lambda_i가 단순히 0.9인 경우 한없이 곱하다보면 나중엔 0에 가까운 값이 되고, 결과적으로 weight layer와 무관하게 전파되는 정보의 gradient가 소실(vanishing)되어 버린다. 반대로 λi\lambda_i가 1.1인 경우 한없이 곱하다 보면 나중엔 무한대에 가까운 값이 되어 gradient가 매우 커지는 문제가 발생한다.
정리한바와 같이 skip-conection시 입력에 어떠한 값을 곱하는 경우 정보 전달에 악영향을 미치고, 최적화(학습)을 어렵게 만든다.
그래서 skip-connection의 입력과 residual block의 출력에는 모두 identity mapping이 적용되어야 한다.(출력의 경우 다음 residual block의 skip-connection 입력으로 들어가기 때문이다.)

참고로 논문에서는 skip-connection의 형태를 6가지로 다양하게 설정하고(이 중에는 identity mapping이 아닌 것도 있다.) 학습하여 성능을 평가해 본 결과 입력 그대로 전달하는 원래 구조가 가장 성능이 좋은 것을 볼 수 있었다. 따라서 결과로부터 shortcut에 어떠한 조작을 가하는 것은 정보 전달에 악영향을 주고, 최적화를 어렵게 만든다고 결론 내릴 수 있다.

5.3 Pre-Activation

앞 장의 실험은 활성함수 ff가 identity-mapping이라는 가정했었다. 하지만 Resnet에서 사용하는 residual block에서 활성함수 ff는 ReLU함수이며, shortcut된 신호와 합쳐지는 곳 뒤에 위치한다. 논문의 저자들은 ff를 identity-mapping으로 만들기 위해 새로운 residual block을 제안하였다.
아래 그림은 논문 저자들이 제안한 여러 구조들이며 밑에는 제안된 구조를 사용하여 CIFAR-10을 학습 후 test set에서의 error를 나타낸다. 실험할 때 weight layer는 2개의 Convolutional layer가 아닌 Bottleneck구조를 사용하였다.

(a) 구조는 resnet논문에서 제안된 가장 기본적인 구조이다. shortcut된 신호와 합쳐지는 addtion연산 뒤 ReLU함수를 통과한다.
(b) 구조에서는 마지막 Batch Normalization을 addtion연산 뒤로 옮겼습니다. 학습한 결과는 원래 형태인 post-activation 보다 나빠진 error 8.17%가 되는것을 볼 수 있다.
(c) 구조는 활성함수 ReLU를 weight layer안으로 옮겨, ReLU를 통과한 신호를 shortcut한 신호와 합치는 구조이다. 이 아이디어는 좋아보이지만, 잔차를 학습할 때 신호 값의 범위가 양수가 되어 forward propagation시에 신호가 양수로 편향된다. 따라서 네트워크의 표현력이 낮아져 성능이 나빠진다.

여기서 논문 저자들은 resnet에서 신호 범위가 양수가 아닌 전체 실수영역 (-∞ ~ ∞)을 가져야 한다고 예상하였다. 따라서 뒤에 나오는 새로운 구조는 신호범위가 (-∞ ~ ∞) 이도록 설계한다.

(d) 구조는 ReLU만 weight 앞에 위치시킨 구조이다. 기본구조인 (a)보다 미미하게 성능이 좋지 않은 것을 볼 수 있다.
(e) 구조는 Batch Normalization과 ReLU 모두 weight앞에 위치한 full pre-activation 구조로 기본구조보다 좋은 성능을 보여준다. 그리고 지금까지의 구조 중 가장 좋은 성능을 보여준다.

(d), (e) 구조는 에서 비대칭(asymmetric)적인 구조로 신호가 weight layer를 먼저 통과하는 구조가 아닌 Activation(ReLU, Batch Normalization) 앞에 위치시키는 구조이다.
아래 그림에서 왼쪽에 위치한 기본구조에서 활성함수가 weight layer를 거쳐가는 신호에만 영향을 주도록 가운데 그림의 구조로 변경한다. 그 다음 동일한 구조에서 residual unit의 영역을 수정하여 pre-activation 구조를 설계한다.


논문에서 가져온 위 Table 2를 보면 full pre-activation 일 때(위에서 (e)케이스) ResNet-110/164 모두 가장 좋은 성능을 보여주는 것을 볼 수 있다.
Table 3에서 Depth를 110부터 1001까지 바꿔가며 Cifar-10/100 에서 테스트해본 결과 모든 경우에 pre-activation 구조가 성능이 좋은 것을 볼 수 있다.
따라서 pre-activation 이 post-activation보다 더 성능이 뛰어나다고 볼 수 있다.

5.4 Bottleneck


residual block은 1x1, 3x3, 1x1으로 위 그림처럼 구성이 된다. Bottleneck 구조라고 이름을 붙인 이유는 차원을 줄였다가 뒤에서 차원을 늘리는 모습이 병목처럼 보이기 때문이다.
이렇게 구성한 이유는 연산 시간을 줄이기 위함이다. 먼저 맨 처음 1x1 convolution은 NIN(Network-in-Network)이나 GoogLeNet의 Inception 구조에서 살펴본 것처럼 dimension을 줄이기 위한 목적이며, 이렇게 dimension을 줄인 뒤 3x3 convolution을 수행 한 후, 마지막 1x1 convolution은 다시 dimension을 확대시키는 역할을 한다. 결과적으로 3x3 convolution 2개를 곧바로 연결시킨 구조에 비해 연산량을 절감시킬 수 있게 된다.
왼쪽의 Bottlenck를 사용하지 않은 경우 고려해야할 파라미터의 갯수는 3×3×64×2=11523\times3\times64\times2=1152인데 반해 Bottleneck을 사용한 경우 고려해야할 파라미터의 갯수는 (1×1×64)+(3×3×64)+(1×1×256)=896(1\times1\times64)+(3\times3\times64)+(1\times1\times256)=896으로 파라미터의 갯수가 왼쪽의 구조 대비 22%가 줄어든다.
Bottleneck에 대한 자세한 내용은 여기를 참고하면 된다.

6. 성능 분석

6.1 post-activation vs pre-activation 비교


Pre-activation이 주는 긍정적인 영향 중 첫 번째는 활성함수 ff가 identity-mapping이 되어 최적화하기 쉬워진 것이다.
ResNet의 post-activation 구조 에서는 ReLU로 인해 음수 신호가 모두 사라진다. 깊은 망일수록 이러한 음의 영역 신호손실이 많이 발생하여 제일 처음 가정했던 아래 식이 만족하지 않게 된다.
xl+1=λlxl+F(xl,Wl)x_{l+1}=\lambda_lx_l+F(x_l,W_l)\rightarrow 실제로는 ReLU로 인해 오차 발생
이러한 현상은 ResNet-1001을 학습 할 때 확인할 수 있다. post-activation 구조에서 학습할 경우 초반에 학습이 잘 이루어지지 않는 경향이 있지만 pre-activation 구조에서는 처음부터 학습이 잘 이루어진다.

6.2 Batch-Normalization 적용 여부에 따른 비교


Pre-activation이 주는 긍정적인 영향 중 두 번째는 Batch Normalization 의 영향으로 regularization(정규화)되어 일반화가 잘되는 것이다.
위 그림은 ResNet-164를 학습한 결과이다. 특이한 점은 테스트 성능은 제안된 구조가 더 좋지만, 학습 결과는 제안한 구조가 더 나쁘게 나오고 있다. 이러한 현상이 발생하는 원인은 제안하는 full pre-activation 구조는 Batch-Normalization을 통과해 정규화된 신호가 weight layer를 통과하기 때문에 일반화 성능이 올라가기 때문이다.(일반화 성능이 올라간다는 말의 의미는 overfitting이 상대적으로 덜 일어나서 학습할 때에는 overfitting이 더 잘 일어나는 기존 구조에 비해 성능이 다소 떨어지지만 테스트 시에는 기존 구조에 비해 일반화가 더 잘되어 성능이 더 좋아지는 것을 말한다.)

6.3 다른 네트워크와 성능 비교


위 표는 Pre-Activation 구조의 성능을 비교분석하기 위해 Cifar-10/100 데이터셋에서 다른 최신(state-of-the-art) 모델들을 비교한 결과이며 가장 좋은 성능을 보여준다.

다음으로 ImageNet에서 ResNet-152/200, Inception-v3를 비교한 결과이다.
실험결과에서 기본구조의 Residual block을 사용한 ResNet-152와 ResNet-200을 비교해보면, ResNet-152가 성능이 더 좋은것을 볼 수 있다. 특이한점은 학습할 때 training error는 ResNet-200이 더 낮았기 때문에 논문 저자들은 overfitting이 발생한 것으로 보았다.
하지만 일반화 성능이 좋은 pre-activation 구조의 ResNet은 200이 152보다 성능이 더 좋은 것을 볼 수 있다.
post-activation 구조에서는 ReLU에 의해 신호손실이 생기지만 pre-activation 구조에서는 신호손실이 없다. 네트워크가 깊어질수록 더 많은 활성함수를 통과하기 때문에 post구조에서 손실은 커지지만 pre-activation은 그러한 경향이 없다. 실제로 실험에서 pre-activation을 사용하면 ResNet-152/200 모두 성능은 개선되지만, ResNet-152에서는 성능개선이 미미한것을 볼 수 있습니다.(0.2%) 하지만 ResNet-200 구조 에서는 상대적으로 성능이 많이 올라간것을 볼 수 있다.(1.1%) 즉 층이 깊을수록 pre-activation 구조가 성능이 더 좋다.
최종적으로 pre-activation 구조를 적용하고, single crop등의 agumentation 기법을 적용한 ResNet-200이 가장 좋은 성능을 보여준다.

profile
바쁘게 부지런하게 논리적으로 살자!!!

0개의 댓글