역전파(BackPropagation)는 한마디로 신경망 모델에서 오차를 이용하여 가중치를 업데이트하는 방법이다.
1. 인공 신경망의 이해
예제로 사용할 인공 신경망은 다음과 같이 입력층, 은닉층, 출력층 3개의 층을 갖고 각 layer는 2개의 뉴런으로 구성된다. 은닉층과 출력층의 모든 뉴런은 활성화 함수로 시그모이드 함수를 사용한다.
은닉층과 출력층의 변수 z는 이전 층의 모든 입력이 각각 가중치와 곱해진 값들을 모두 더한 가중합을 의미한다. 이 값은 아직 시그모이드 함수를 거치지 않은 상태이다. z의 우측 | 를 지나서 존재하는 변수 h 또는 o는 z가 활성화 함수인 시그모이드 함수를 지난 후의 값으로 각 뉴런의 출력값을 의미한다.
* 시그모이드 함수는 활성화 함수 중 하나로 아래와 같이 0에서 1 사이의 값을 반환하는 함수이다.
현재 역전파 예제에서는 인공 신경망에 존재하는 모든 가중치 W에 대해서 역전파를 통해 업데이트하는 것을 목표로 하므로 편향 b는 고려하지 않는다.
2. 순전파(Forward Propagation)
먼저, 위 그림에서 순전파를 살펴볼 것이다. 파란색 숫자는 입력 값을 의미하며, 빨간색 숫자는 각 가중치 값을 의미한다.
각 입력은 입력층에서 은닉층 방향으로 향하면서 각 입력에 해당하는 가중치와 곱해 가중합을 계산한다. 이 값은 곧 은닉층 뉴런의 시그모이드 함수의 입력값이 된다.
$ z_{1} , z_{2} $는 각각 은닉층 뉴런에서 활성화 함수인 시그모이드 함수를 지나게 된다. 이 시그모이드 함수가 리턴하는 결과 값은 은닉층 뉴런의 최종 출력값에 해당한다.
이제 $ h_{1} $ 과 $ h_{2} $는 각각의 값에 해당하는 가중치와 곱해 가중합을 계산하여 출력층의 뉴런의 시그모이드 함수의 입력값이 된다.
$ z_{3} , z_{4} $는 각각 출력층 뉴런에서 활성화 함수인 시그모이드 함수를 지나 최종적으로 인공 신경망의 출력값이 된다. 이 출력값은 실제값을 예측하기 위한 값으로서 예측값이라고도 부른다.
이제 예측값과 실제값 사이의 오차를 계산하기 위해 손실 함수(Loss Function)를 선택한다. 손실 함수로는 평균 제곱 오차(MSE, Mean Squared Error)를 많이 사용한다. MSE는 이름에서 알 수 있듯이 오차(error)를 제곱한 값을 모두 더해 평균을 구한 것이다. 즉, MSE의 값이 작을수록 모델의 성능이 좋다고 할 수 있다.
실제값을 target, 위 순전파 과정을 통해 계산한 예측값을 output이라고 하자. 손실 함수 MSE를 적용한 전체 오차 제곱의 합의 평균을 구하면 다음과 같다.
3. 역전파 1단계
이제 역전파에 대해 알아볼 것이다. 순전파가 입력층에서 출력층으로 향한다면, 역전파는 반대로 출력층에서 입력층 방향으로 계산하며 가중치를 업데이트해나간다.
출력층 바로 이전의 은닉층을 N층이라고 할 때, 출력층과 N층 사이의 가중치를 업데이트 하는 단계를 역전파 1단계, N층과 N층의 이전층 사이의 가중치를 업데이트 하는 단계를 역전파 2단계라고 하자.
역전파 1단계에서 업데이트해야할 가중치는 $ W_{5}, W_{6}, W_{7}, W_{8} $ 총 4개이다. 원리 자체는 동일하므로 먼저 W5에 대해 업데이트를 진행해볼 것이다.
경사 하강법을 수행하려면 가중치 $ {W_{5}} $를 업데이트 하기 위해 $ \frac{\partial E_{total}}{\partial W_{5}} $ 를 계산해야 한다.
$ \frac{\partial E_{total}}{\partial W_{5}} $ 를 계산하기 위해 미분의 연쇄 법칙(Chain rule)을 이용하여 편미분 값을 계산할 수 있다.
$ {E_{total}} $ 을 $ {o_{1}} $에 대해 편미분하면 다음과 같다.
$ {o_{1}} $ 은 시그모이드 함수의 출력값이다.
시그모이드 함수 $ f(x) = \textit{sigmoid}(x) = \frac{1}{1 + e^{-x}} $를 미분하면 $ f'(x) = \frac{1}{1 + e^{-x}} * \frac{e^{-x}}{1 + e^{-x}} $이므로 $ f(x) * (1 - f(x)) $이다.
이에 따라서 $ \frac{\partial o_{1} }{\partial z_{3}} = f(z_{3}) * (1 - f(z_{3})) = o_{1} * (1 - o_{1}) $ 이므로 결과는 다음과 같다.
마지막으로 $ z_{3} = W_{5}h_{1} + W_{6}h_{2} $이므로 $ \frac{\partial z_{3}}{\partial W_{5}} $는 $ h_{1} $의 값과 동일하다.
따라서 모두 곱해주면 $ \frac{\partial E_{total}}{\partial W_{5}} $의 값은 다음과 같다.
이제 경사 하강법을 통해 가중치를 업데이트한다. 하이퍼파라미터에 해당하는 학습률(learning rate) $ \alpha $를 0.5라고 가정하고 가중치 $ W_{5} $를 업데이트한다.
이와 같은 원리로 $ W_{6}^{+}, W_{7}^{+}, W_{8}^{+} $을 계산할 수 있다.
4. 역전파 2단계
이제 입력층 방향으로 이동하며 다시 계산을 이어간다. 현재 인공 신경망 예제는 은닉층이 1개 밖에 없으므로 이번 단계가 마지막 단계가 된다. 실제로 은닉층이 더 많은 경우라면 입력층 방향으로 한단계씩 계속해서 계산해나가야한다.
이번 단계에서 계산할 가중치는 $ W_{1}, W_{2}, W_{3}, W_{4} $ 이다. 마찬가지로 원리 자체는 동일하므로 $ W_{1} $에 대해 먼저 업데이트를 진행해볼 것이다.
경사 하강법을 수행하려면 가중치 $ W_{1} $를 업데이트하기 위해 $ \frac{\partial E_{total}}{\partial W_{1}} $ 를 계산해야 한다.
$ \frac{\partial E_{total}}{\partial W_{1}} $ 를 계산하기 위해 미분의 연쇄 법칙(Chain rule)을 이용하여 편미분 값을 계산할 수 있다.
그리고 우변의 첫째항인 $ \frac{\partial E_{total}}{\partial h_{1}} $은 다음과 같이 다시 식을 풀어쓸 수 있다.
위 식의 우변의 두 항을 각각 구해보자. 우선 첫번째 항 $ \frac{\partial E_{o1}}{\partial h_{1}} $에 대해서 항을 분해 및 계산해볼 것이다.
$ E_{o1} = \frac{1}{2}(target_{o1} - o_{1})^{2} $ 이므로 $ \frac{\partial E_{o1}}{\partial o1} = -(target_{o1} - o_{1}) $이고,
위에서 살펴본 시그모이드 함수의 미분 $ f'(x) = f(x) * (1 - f(x)) $에 의해서 $ \frac{\partial o_{1}}{\partial z_{1}} = o_{1} * (1 - o_{1}) $이다.
그리고 $ z_{3} = W_{5}h_{1} + W_{6}h_{2} $이므로 $ \frac{\partial z_{3}}{\partial h_{1}} = W_{5} $이다.
이와 같은 원리로 $ \frac{\partial E_{o2}}{\partial h_{1}} $도 구한다.
이제 $ \frac{\partial E_{total}}{\partial W_{1}} $를 구하기 위한 첫번째 항을 구했으므로 나머지 두번째 항, 세번째 항을 구하면 다음과 같다.
따라서 $ \frac{\partial E_{total}}{\partial W_{1}} $는 다음과 같다.
이제 경사 하강법을 통해 가중치 $ W_{1}^{+} $을 업데이트할 수 있다.
이와 같은 원리로 $ W_{2}^{+}, W_{3}^{+}, W_{4}^{+} $도 업데이트할 수 있다.
5. 결과 확인
업데이트된 가중치에 대해서 다시 한번 순전파를 진행하여 오차가 감소하였는지 확인해보면 다음과 같이 오차 $ E_{total} $가 0.02397190에서 0.02323634로 줄어들었음을 알 수 있다.
이렇게 인공신경망의 학습은 오차를 최소화하는 가중치를 찾는 목적으로 순전파와 역전파를 반복하는 것을 말한다.
다음 게시글: Pytorch로 경사하강법 역전파 자동미분 구현하기
https://daeunnniii.tistory.com/190
참고:
- 위키독스 Pytorch로 시작하는 딥러닝 입문
- 위키독스 딥 러닝을 이용한 자연어 처리 입문
'AI > 딥러닝' 카테고리의 다른 글
RNN(Recurrent Neural Network) 정리 (0) | 2024.03.17 |
---|---|
MLP(Multi-Layer Perceptron)과 CNN(Convolutional Neural Network) 정리 (0) | 2024.03.17 |
[Pytorch] 데이터 로드하기 - Dataset, DataLoader 정리 (0) | 2023.03.28 |
[Pytorch] Autograd 자동 미분 및 역전파 적용하기 (0) | 2023.03.26 |
[Pytorch] 텐서(Tensor) 다루기 (0) | 2023.03.26 |