이 포스트는 Do it 딥러닝 교과서 (윤성진 저)를 참고하여 만들어졌음!
신경망의 학습 목표
신경망의 학습 목표는 loss function의 값을 최소화 하는 것이다. loss는 신경망이 내놓은 예측값과 target 값의 차이로 주어지기 때문에 신경망의 weights를 변경해가면서 해당 모델이 target을 잘 맞출 수 있도록 해야한다.
위 그림의 x축을 weights, y축을 loss라고 생각하면 우리는 모델의 weights를 잘 변경해가면서 최대한 global minimum에 가까운 loss값을 가지도록 하는 것이 최종 목표가 되는 것이다.
weight vector의 차원이 낮다면 단순 미분으로 global minimum을 찾는것이 가능하다. 하지만 deep learning의 파라미터 개수는 어마무시하므로 이를 closed form으로 해를 구하는 것은 연산량 이슈로 불가능하다. 따라서 최적화 알고리즘을 통해 적절한 local minimum을 찾는 것이 최종 목표가 된다.
경사 하강법 (Gradient descent)
미분을 통해 한 번에 최적해를 구하는 것이 불가능하므로, 우리는 loss를 조금씩 줄여나가는 방법을 택한다. 그것이 바로 경사하강법인데 현재 weight의 위치에서 loss를 미분하여 $\frac{\partial J(\vec{\theta})}{\partial \theta_i}$를 구한 후, 이를 현재 weight에서 빼주면 된다.
위 그림에서처럼 현재 weight가 loss function (y축) 기준으로 오른쪽으로 내려가는 방향에 존재한다면 그때 기울기 $\frac{\partial J(\vec{\theta})}{\partial \theta_i}$는 음수가 된다. 이 기울기를 현재 weight에서 빼주면 다음 식을 수행하게 된다.
$$\vec{\theta}^+ = \vec{\theta} - \gamma \frac{\partial J}{\partial \vec{\theta}}$$
여기서 $\vec{\theta}^+$는 update 이후의 가중치를 의미한다. 위 식에서 gradient가 음수였으므로 $\vec{\theta}^+$는 $\vec{\theta}$보다 오른쪽으로 $\gamma \cdot \text{gradient}$만큼 이동한 값이 된다.
쉽게 말하면 현재 weight 위치에서 경사가 존재한다면 그 경사를 0에 가깝게 줄이는 방향으로 이동하는 것이다.
위 식에서 $\gamma$는 learning rate로 한 번의 update에서 얼마나 이동할지를 나타낸다.
위와 같은 회귀모델 순방향 신경망이 있다고 가정해본다. 이때 각 문자와 첨자의 의미는 다음과 같다.
예를들어 $w_{1m}^1$은 첫 계층의 1번째 뉴런에서 다음 계층의 m번째 뉴런으로 향하는 가중치이다.
이때 맨 첫 번째 계층에 존재하는 가중치 $w_{nm}^1$을 update하기 위해서는 다음 식을 수행해야 한다.
$${w_{nm}^1}^+ = w_{nm}^1 - \gamma \frac{\partial J}{\partial w_{nm}^1}$$
중요한 점은 loss function $J(y)=\frac{1}{N}\sum^{N}||t-y||_2^2$에는 $w_{nm}^1$이 포함되지 않기 때문에 $\frac{\partial J}{\partial w_{nm}^1}$을 바로 구할 수 없다는 것이다.
$\frac{\partial J}{\partial w_{nm}^1}$을 구하기 위해서는 맨 끝단 $J$에서부터 맨 처음 계층 $w_{nm}^1$까지 거슬러 올라가는 chain rule을 적용해야 하며, 이는 다음과 같이 표현할 수 있다
$$\frac{\partial J}{\partial w_{nm}^1} = \frac{\partial J}{\partial y} \cdot \frac{\partial y}{\partial z^2} \cdot \frac{\partial z^2}{\partial a_m^1} \cdot \frac{\partial a_m^1}{\partial z_m^1} \cdot \frac{\partial z_m^1}{\partial w_{nm}^1} $$
Chain rule에 사용될 인자들은 다음과 같이 구할 수 있다.
$$\frac{\partial J}{\partial w_{nm}^1} = \frac{\partial J}{\partial y} \cdot \frac{\partial y}{\partial z^2} \cdot \frac{\partial z^2}{\partial a_m^1} \cdot \frac{\partial a_m^1}{\partial z_m^1} \cdot \frac{\partial z_m^1}{\partial w_{nm}^1} \\ =-\frac{1}{N} \sum_{(x,t) \in D}^{N}2(t-y) \cdot 1 \cdot w_m^2 \cdot \text{ReLU}'(z_m^1)\cdot x_n $$
이렇게 구해진 기울기로 경사하강법을 이용해 한 step update가 가능해진다.
$${w_{nm}^1}^+ = w_{nm}^1 - \gamma \frac{\partial J}{\partial w_{nm}^1} \\ = w_{nm}^1 - \gamma(-\frac{1}{N} \sum_{(x,t) \in D}^{N}2(t-y) \cdot 1 \cdot w_m^2 \cdot \text{ReLU}'(z_m^1)\cdot x_n) $$
역전파 알고리즘
위에서 다룬 경사 하강법을 수행하기 위해 신경망에 존재하는 모든 파라미터에 대해 미분을 수행하면 중복 미분을 여러 번 수행하는 비효율성 문제가 발생. (같은 경로에 있는 파라미터임에도 불구하고 동일한 경로에 대해 미분을 여러 번 수행하게 된다.)
역전파 알고리즘은 경사 하강법을 여러 파라미터들에 대하여 효율적으로 적용하기 위해 모든 경로에 대해 한 번만 미분을 수행하는 방식이다.
바로 예시를 보도록 한다.
$I_n \rightarrow h_m$ 경로상의 weights를 첫 번째 계층 파라미터
$h_m \rightarrow O$ 경로상의 weights를 두 번째 계층 파라미터로 둔다.
Output $\rightarrow$ Input 방향으로 가면서 가장 먼저 마주치는 학습 가능한 파라미터는 $h_1, h_2, \cdots h_m$에서 $O$로 향하는 경로에 있는 $w_1^2, w_2^2, \cdots, w_m^2$이다.
Step 1
먼저 $w_1^2$를 update하기 위해서는 다음을 구해야 한다.
$$\frac{\partial J}{\partial w_1^2} = \frac{\partial J}{\partial y} \cdot \frac{\partial y}{\partial z^2} \cdot \frac{\partial z^2}{\partial w_1^2} $$
그 다음 파라미터인 $w_2^2$를 update하기 위해서는 다음을 구해야 한다.
$$\frac{\partial J}{\partial w_2^2} = \frac{\partial J}{\partial y} \cdot \frac{\partial y}{\partial z^2} \cdot \frac{\partial z^2}{\partial w_2^2} $$
마지막으로 $w_m^2$를 update를 하기 위해서는 다음을 구해야 한다.
$$\frac{\partial J}{\partial w_m^2} = \frac{\partial J}{\partial y} \cdot \frac{\partial y}{\partial z^2} \cdot \frac{\partial z^2}{\partial w_m^2} $$
즉 두 번째 계층 파라미터를 구하는 과정에서 $\frac{\partial J}{\partial y} \cdot \frac{\partial y}{\partial z^2}$는 공통되는 부분이다. 공통부분은 딱 한 번만 계산하면 된다.
Step 2
공통부분을 계산해놓았다면 이제 가중치별로 지역미분 $\frac{\partial z^2}{\partial w_1^2}, \frac{\partial z^2}{\partial w_2^2}, \cdots, \frac{\partial z^2}{\partial w_m^2}$을 구한다.
위에서 구한 공통부분 $\frac{\partial J}{\partial z^2}$에 $\frac{\partial z^2}{\partial w_1^2}, \frac{\partial z^2}{\partial w_2^2}, \cdots, \frac{\partial z^2}{\partial w_m^2}$를 곱하면 $\frac{\partial J^2}{\partial w_1^2}, \frac{\partial J^2}{\partial w_2^2}, \cdots, \frac{\partial J^2}{\partial w_m^2}$를 얻는다.
최종적으로 구한 $\frac{\partial J^2}{\partial w_1^2}, \frac{\partial J^2}{\partial w_2^2}, \cdots, \frac{\partial J^2}{\partial w_m^2}$을 이용해서 $w_1^2, w_2^2, w_m^2$들을 update.
Step 3
이 그림을 다시 보면 첫 번째 계층의 출력이 activation을 거친 후 두 번째 계층 뉴런 $h_1, h_2, \cdots, h_m$에 $a_1^1, a_2^1, \cdots, a_m^1$으로 입력된다.
그렇게 첫 번째 계층의 출력은 두 번째 뉴런에 입력되고, 이것들이 다시 두 번째 계층의 weights들과 결합되어
$z^2 = w_1^2\cdot a_1^1 + w_2^2 \cdot a_2^1 + \cdots + w_m^2 \cdot a_m^1$을 만들어낸다.
두 번째 계층 뉴런들 $w_1^2, w_2^2, \cdots, w_m^2$에 대해서는 전역미분을 전부 다 구했다. 이제 첫 번째 계층 뉴런들 $w_1^1, w_2^1, \cdots, w_m^1$에 대하여 전역미분을 구할 차례이다. 첫 번째 계층 뉴런들을 함축한 두 번째 계층의 요소는 바로 $a_1^1, a_2^1, \cdots, a_m^1$이다. 예를 들어 $a_m^1 = \text{ReLU}(w_{1m}^1 \cdot x_1+ w_{2m}^1 \cdot x_2+ \cdots + w_{nm}^1 \cdot x_n)$ 이다. 따라서 $z^2=w_1^2\cdot a_1^1+w_2^2\cdot a_2^1+ \cdots + w_m^2\cdot a_m^1$에 대하여 다음을 계산해야 한다.
$$\frac{\partial z^2}{\partial a_1^1}, \frac{\partial z^2}{\partial a_2^1}, \cdots, \frac{\partial z^2}{\partial a_m^1} $$
위에서 구한 공통부분 $\frac{\partial J}{\partial z^2}$에 $\frac{\partial z^2}{\partial a_1^1}, \frac{\partial z^2}{\partial a_2^1}, \cdots, \frac{\partial z^2}{\partial a_m^1}$을 곱하면 $\frac{\partial J}{\partial a_1^1}, \frac{\partial J}{\partial a_2^1}, \cdots, \frac{\partial J}{\partial a_m^1}$을 얻는다.
여기까지하면 두 번째 계층에서 할 수 있는 일을 다 했다.
첫 번째 계층 파라미터들에 대한 공통부분은 $\frac{\partial J}{\partial z_m^1}=\frac{\partial J}{\partial a_m^1} \cdot \frac{\partial a_m^1}{\partial z_m^1}$으로 구할 수 있다. 나머지 부분은 생략~
역전파 알고리즘에서 중요한 점은 한 뉴런은 앞선 단에서 전달받은 전역미분(공통부분) 값에 자신의 지역미분 값만을 곱하면 자신이 가진 가중치로 loss function을 구할 수 있다는 것이다.
'딥러닝' 카테고리의 다른 글
7. 손실함수 Loss function (0) | 2023.09.15 |
---|---|
6. 배치, 미니배치, SGD (0) | 2023.09.15 |
4. 시그모이드와 크로스엔트로피, 양수출력문제, 죽은 ReLU (0) | 2023.09.14 |
Optuna document 읽어보기 (0) | 2023.09.14 |
3. 활성화 함수 (Activation function) (0) | 2023.09.13 |