1. 심층 신경망(Deep Neural Network)

 이번 포스팅에서야 제대로 Deep한 개념이 나오게 된다. Deep하다는 것은 입력층과 출력층 사이에 은닉층(Hidden Layers)이 많이 껴있어 입력층과 출력층 사이가 Deep하다는 의미이다. 그렇다면 왜 딥러닝일까? 직관적으로 이해하기 위하여 아래 그림을 보면, 여러 비선형 변환기법의 조합을 통해 높은 수준의 추상화가 가능하다는 것을 알 수 있다. 일반적으로 깊은 층을 가질 수록 더욱 복잡한 표현이 가능하다고 알려져있다. 


출처: 장교수의 딥러닝


 심층 신경망은 Perceptron을 여러개 쌓은것 처럼 보인다 하여 다층 퍼셉트론(Multi-layer Perceptron)이라고도 한다. 그러면 단층 퍼셉트론에서 진행한 순서대로 심층 신경망을 설계해보자.


Step 1. 모델 설계


 아래 그림은 심층신경망의 예이다. 입력층 $x$가 있고, $L-1$개의 은닉층(Hidden Layers) $h$가 있고, 마지막에 출력층 $\hat{y}$이 있다. 일반적으로 Layer의 개수를 셀 때는 입력층을 제외하고 센다. 엄밀히 말하면 출력층 $\hat{y}$은 $h_{L}$이라 할 수 있다. 윗 첨자($^{[n]}$)는 각 Layer에서의 원소 인덱싱이 될 것이고, 입력층에서는 feature가 된다. $n_{i}$는 $i$번째 Layer의 원소 개수를 뜻한다. 심층신경망 모델을 프로그래밍 할 때, 파라미터 행렬들($W, B$)의 크기가 많이 헷갈리므로 잘 기억해두길 바란다.



 출력층 $h_{L}$을 제외한 모든 층에서는 Relu함수를 활성화 함수로 사용하겠다. 또한, 이해하기 쉽게 각 층을 Linear Function과 Activation Function 두개로 나누어 생각하겠다. 오류 역전파(Step 3)에서 설명할테지만 $\frac { \partial J }{ \partial W } =\frac { \partial J }{ \partial z } \frac { \partial z }{ \partial W }$으로 $dW$를 구하기 위함이다. 하여, 은닉층에서의 Forward propagation의 일반식은 $h_{i+1}=relu(W_{i+1}h_{i}+B_{i+1})$이 된다.



 이번 실습도 Cat vs Dog 데이터셋에서 수행할 것이므로 출력층에서 Label의 개수 $n_{L}$은 1개이다. 따라서 출력층의 활성화 함수는 이진분류에 적합한 $sigmoid$ 함수를 사용하겠다. 출력층의 일반식은 $\hat{y}=h_{L}=sigmoid(W_{L}h_{L-1}+B_{L})$이 되겠다.


Step 2. 손실함수 정의


 전체 학습데이터에 대한 손실함수($J$)는 하나의 데이터에 대한 손실함수 ($L$)의 평균으로 정의할 수 있다. 전체 시스템은 데이터의 수 만큼(문제의 수) 총 $m$번의 학습이 진행될 것이다. 


$$J=\frac{1}{m}\sum _{ i=0 }^{ m-1 }{ \mathcal{L}(y^{i}, \hat{y}^{i}) } $$

$$\mathcal{L}= −ylog(\hat{y})−(1−y)log(1−\hat{y}))  $$


Step 3. 오류 역전파(Backpropagation)로 미분식 풀기 


 아마 오류 역전파(Back propagation)이라는 것을 많이 들어봤을 것이다. Step1에서 입력->출력 방향으로 전파되는 것을 Forward propagation라고 했었다. 반대로 미분식을 풀기 위해서는 출력->입력 방향으로 수식이 전개 되는데 이것을 Back propagation 라고 한다. 단일퍼셉트론과 마찬가지로 손실함수 $J$를 최소화 하는 미분식부터 구하게 된다. 사실 단일퍼셉트론을 이해했다면 심층 신경망 유도는 쉬울것이다. 

 먼저 하나의 데이터에 대한 손실함수 $\mathcal{L}$를 최소화 하는 $L-1$층의 파라미터의 편미분값을 구해보자. 아래 그림에서 Back propagation방향은 빨간색으로 그렸다.  단일퍼셉트론에서 했던 최적화 과정과 동일하게 $\frac{\partial \mathcal{L}}{\partial z_{L-1}} $을 구할 수 있으며 연쇄법칙으로 $\frac{\partial \mathcal{L}}{\partial B_{L}} $과 $\frac{\partial \mathcal{L}}{\partial W_{L}} $을 구할 수 있다. Back propagation을 위해 다음 Layer에 넘길 $\frac{\partial \mathcal{L}}{\partial h_{L-1}} $ 또한 요구된다. 



 아래는 은닉층에서의 Back propagation에 대한 설명이다. 출력층->$i_{th}$Layer까지 전파(propagation)가 이루어졌다면 $\frac{\partial \mathcal{L}}{\partial h_{i+1}} $의 값을 넘겨받았을 것이다. $Relu(x)$함수의 미분은 $1(x>0)$ 또는 $0(x\leq 0)$이 된다. 나머지 파라미터 ($W, B$)는 위와 동일하게 진행된다. 개념은 그리 어렵지 않을 것이다. 여기서 눈치가 좋은 사람이라면 $Relu(x)$의 미분이 0을 반환하는 것에 주목할 것이다. 이것이 저번 포스팅에서 설명한 "Dying Relu Problem"이다.



Step 4. 행렬식으로 풀기


 이제 모든 $m$개의 데이터를 한번에 트레이닝 하기 위하여 벡터화(Vectorization) 하면 아래와 같이 모든 Layer가 행렬을 이루게 된다. 역시 우리가 할 실습에 따라서 그림은 $n_{L}=1$로 그렸다. 아래 그림에서 대괄호아래첨자($[]_{i}$)는 데이터 순번 인덱싱이다. 



위의 모델을 Back propagation 하게되면 아래와 같이 되는데 자세한 설명은 동영상 강의를 참고하길 바란다. 




동영상 강의: 준비중...

1. 활성화 함수

 활성화 함수(Activation Function)는 신경학적으로 볼때 뉴런발사(Firing of a Neuron)의 과정에 해당한다고 볼 수 있다. 최종출력 신호를 다음 뉴런으로 보내줄지 말지 결정하는 역할을 하게 된다.


Firing of a neuron 출처: Andrii Vodolazhskyi via Shutterstock


 뉴런이 다음 뉴런으로 신호를 보낼 때 입력신호가 일정 기준 이상이면 보내고 기준에 달하지 못하면 보내지 않을 수도 있다. 그 신호를 결정 해주는 것이 활성화 함수(Activation Function)라 이해하면 된다. 많은 종류의 활성화 함수가 있고, Activation function의 결정이 결과에 크게 영향을 준다. 하나하나 알아보도록 하자.


- 선형함수 (Linear Function)

 선형함수는 말 그대로 직선적인 함수($y=x$)이다. 결론부터 말하면 Linear Function를 활성화 함수로 하게되면 "Deep"한 네트워크의 이점이 전혀 없다는 것이다. 아래의 2-Layer 모델을 예로 들어보자.



 2개의 Layer를 쌓아봤지만 $X$에 곱해지는 항들은 $W$로 치환가능하고, 입력과 무관한 상수들은 전체를 $B$로 치환 가능하기 때문에 $WX+B$라는 Single layer perceptron과 동일한 결과를 낸다. 다시말해 Deep 하게 쌓는 의미가 없어진다.


linear Function


- 계단함수 (Step Function)

 입력이 양수일때는 1(보낸다)을 음수일때는 0(보내지 않는다)의 신호를 보내주는 이진적인(Binary) 함수이다. 직관적으로는 상당히 좋다. 0이상이면 출력하고 0이하면 뉴런을 죽이고 하지만 우리가 모델 Optimization과정에서 미분을 해야하므로 미분이 되지않는 이녀석은 쓸 수가 없다.


Step Function


- Sigmoid Function 

 지난 포스트04 단일퍼셉트론에서 사용했던 활성화 함수이다. 입력을 ($0, 1$) 사이의 값으로 normalize해준다.  과거에 상당히 인기가 있었던 활성화 함수이다. sigmoid의 수식과 그 미분은 아래와 같다.


$$sigmoid(x)=\frac { 1 }{ 1+{ e }^{ -x } } $$

$$\frac { d }{ \partial x } sigmoid(x)=\frac { 1 }{ 1+{ e }^{ -x } } \left( 1-\frac { 1 }{ 1+{ e }^{ -x } }  \right)$$


 아주 아름답게$(A'=A(1-A))$로 미분이 되어 코드로 구현하기가 쉽다. 이런 완벽해보이는 매력적인 함수지만 문제점이 있다. 바로 Gradient Vanishing인데 아래의 tanh함수부터 소개하고 설명하겠다. $x$가 0일때 기울기가 최대가 되는데, 그 미분값이 $\frac{1}{4}$이다. 딥러닝을 하기 위해서는 Layer를 많이 쌓아야 하는데 이렇게 작은 미분 값은 에너지함수 최적화 과정에서 Layer을거쳐갈 때마다 곱하기 연산을 거쳐 deep할 수록 기울기가 사라져 버리는 Gradient Vanishing을 야기 시킬 수 있다. 1~2개의 Layer에서는 사용할 수 있겠지만 Deep한 학습법에서 사용하는 것은 추천하지 않는다. 


Sigmoid Function


- tanh Function

 sigmoid fuction을 보완하고자 나온 함수이다. 입력신호를 ($-1, 1$) 사이의 값으로 normalization 해준다. 거의 모든 방면에서 sigmoid보다 성능이 좋다. 수식은 아래와 같다.


$$tanh(x)=\frac { { e }^{ x }-{ e }^{ -x } }{ { e }^{ x }+{ e }^{ -x } } $$

$$\frac{d}{dx}tanh(x)=1-tanh(x)^{2}$$


 기울기가 최대인 $x$가 0인 지점의 미분값은 1이 된다. 그럼에도 불구하고 Gradient Vanishing문제가 발생하게 된다. sigmoid 함수보다는 덜함


Tanh Function



Gradient Vanishing

 sigmoid와 tanh함수 모두 $x$가 0일때 기울기가 최대가 되는데, 그 미분값이 $sigmoid'(0)=\frac{1}{4}, tanh'(0)=1$이다. 학습을 더 잘 하기 위해서는 Layer를 많이 쌓아야 하는데 이렇게 작은 미분 값은 에너지함수 최적화 과정에서 Layer을 거쳐갈 때마다 곱하기 연산을 거쳐 deep할 수록 기울기가 사라져 버리는 것이 Gradient Vanishing이다. 아래의 deep 모델이 있다고 하자.



 backpropagation에 따라 $\frac{dY}{dw_{1}}$을 구하면,


$$\frac { dY }{ d{ w }_{ 1 } } =\frac { dY }{ dh_{ n } } \frac { dh_{ n } }{ d{ h }_{ n-1 } } ...\frac { dh_{ 2 } }{ dh_{ 1 } } \frac { dh_{ 1 } }{ d{ w }_{ 1 } } $$


 Hidden Layer와 Hidden Layer사이에 미분을 하게 되면 활성화 함수의 미분이 반드시 들어가게 되는데 1이하의 실수가 n번 곱해지면 결국에는 0으로 수렴하게 될 것이다. 비슷한 문제로 미분값이 1 이상이면 Gradient Exploding문제가 발생하는데 이것 또한 1이상의 실수가 $n$번 곱해져 발산해버리는 것이다.


- ReLU Function (Rectified Linear Unit)

 현재 가장 인기있는 활성화 함수인 ReLu는 양수에서 Linear Function과 같으며 음수는 0으로 버려버리는 함수($Relu(x)=max(0, x)$)이다. 우선, 기울기(미분값)가 0 또는 1의 값을 가지기 때문에 Sigmoid Function에서 나타나는 Gradient Vanishing 문제가 발생하지 않는다. 언뜻 보기에는 Linear Function과 같은 문제가 없을까 생각이 들 수 있지만 엄연히 Non-Linear함수 이므로 Layer를 deep하게 쌓을 수 있다. 또한 exp() 함수를 실행하지 않아 sigmoid함수나 tanh함수보다 6배 정도 빠르게 학습이 된다고 한다. 

Relu Function

+ Recent posts