Back Propagation 설명 | 오차역전파 (Backprogation)의 개념을 쉽게 이해해 봅시다 상위 208개 베스트 답변

당신은 주제를 찾고 있습니까 “back propagation 설명 – 오차역전파 (Backprogation)의 개념을 쉽게 이해해 봅시다“? 다음 카테고리의 웹사이트 th.taphoamini.com 에서 귀하의 모든 질문에 답변해 드립니다: th.taphoamini.com/wiki. 바로 아래에서 답을 찾을 수 있습니다. 작성자 테디노트 TeddyNote 이(가) 작성한 기사에는 조회수 15,852회 및 좋아요 363개 개의 좋아요가 있습니다.

Back Propagation 연산에서 핵심은 ‘Chain Rule’ 즉 연쇄법칙(함성함수의 도함수)입니다. 다시 말하지만 Back Propagation은 Cost를 최소화하기 위해 w를 갱신해야하며 이를 위해선 Cost의 미분값이 필요합니다.

Table of Contents

back propagation 설명 주제에 대한 동영상 보기

여기에서 이 주제에 대한 비디오를 시청하십시오. 주의 깊게 살펴보고 읽고 있는 내용에 대한 피드백을 제공하세요!

d여기에서 오차역전파 (Backprogation)의 개념을 쉽게 이해해 봅시다 – back propagation 설명 주제에 대한 세부정보를 참조하세요

오차역전파 (Backpropagation)에 대한 수학적 이해를 도와드리는 영상입니다.
편미분, Chain Rule에 대한 개념이 부족하신 분들은 이전 영상을 먼저 보시고 오세요.
#오차역전파 #딥러닝 #설명

텐서플로우 자격증 취득 강의: https://bit.ly/tfcert-vod
테디노트(깃헙 블로그) : https://teddylee777.github.io
머신러닝 혼자서 스터디 : https://github.com/teddylee777/machine-learning

back propagation 설명 주제에 대한 자세한 내용은 여기를 참조하세요.

[Deep Learning 시리즈] Backpropagation, 역전파 알아보기

Backpropagation이란? Backpropagation 은 오늘 날 Artificial Neural Network 를 학습시키기 위한 일반적인 알고리즘 중 하나이다. 한국말로 직역하면 …

+ 여기를 클릭

Source: evan-moon.github.io

Date Published: 9/13/2021

View: 9369

딥러닝 역전파 backpropagation이란? – 프라이데이

역전파 알고리즘은 출력값에 대한 입력값의 기울기(미분값)을 출력층 layer에서부터 계산하여 거꾸로 전파시키는 것이다. 이렇게 거꾸로 전파시켜서 …

+ 여기를 클릭

Source: ganghee-lee.tistory.com

Date Published: 3/17/2022

View: 2383

04-3) 역전파(BackPropagation) 이해하기 – 딥 러닝을 이용한 …

04-3) 역전파(BackPropagation) 이해하기. 인공 신경망이 순전파 과정을 진행하여 예측값과 실제값의 오차를 계산하였을 때 어떻게 역전파 과정에서 경사 하강법을 …

+ 자세한 내용은 여기를 클릭하십시오

Source: wikidocs.net

Date Published: 9/12/2022

View: 2890

3.14.1. 순전파(forward propagation) – Dive into Deep Learning

일반적으로는 역전파(back propagation)은 뉴럴 네트워크의 각 층과 관련된 목적 함수(objective function)의 중간 변수들과 파라미터들의 그래디언트(gradient)를 출력층 …

+ 여기에 더 보기

Source: ko.d2l.ai

Date Published: 9/7/2022

View: 9376

Backpropagation 설명 예제와 함께 완전히 이해하기 – Jaejun Yoo

쉽게 설명하는 기계학습(machine learning) 개념, 역전파(backpropagation) 예제와 함께 완전히 이해하기.

+ 여기에 자세히 보기

Source: jaejunyoo.blogspot.com

Date Published: 7/9/2022

View: 3777

역전파(Backpropagation) 설명 – Deep Learning with Writing

역전파(Backpropagation)에 대해서 쉽게 설명한다면? Gradient Descent를 이용해 가중치 갱신을 해야하고, GD를 하기 위해선 loss function의 …

+ 자세한 내용은 여기를 클릭하십시오

Source: mole-starseeker.tistory.com

Date Published: 5/1/2022

View: 4742

[딥러닝] 뉴럴 네트워크 Part. 4 – 역전파 (backpropagation)

쉬운 설명을 위해 예제 신경망을 구성해보았습니다. Input 값은 1개이고 Output 값은 2개, Hden Layer 수는 2개인 작은 신경망입니다.

+ 여기에 보기

Source: gomguard.tistory.com

Date Published: 1/16/2022

View: 6312

[딥러닝기초] 역전파 알고리즘(Back Propagation)1_ Delta Rule

– 출력층(ouput layer)에서 입력층(input layer) 방향으로 오차(error)를 역으로 전파하면서 가중치를 업데이트 하기 때문에 역전파(Back Propagation) …

+ 자세한 내용은 여기를 클릭하십시오

Source: hyen4110.tistory.com

Date Published: 6/26/2021

View: 6399

Backpropagation 설명 (역전파) – questionet

1. computational graph로 backpropagation을 계산했을 때 발견되는 pattern의 의미와 그 쓰임. 2. input과 output이 scalar가 아닌 vector 또는 …

+ 여기에 자세히 보기

Source: questionet.tistory.com

Date Published: 2/8/2022

View: 6487

주제와 관련된 이미지 back propagation 설명

주제와 관련된 더 많은 사진을 참조하십시오 오차역전파 (Backprogation)의 개념을 쉽게 이해해 봅시다. 댓글에서 더 많은 관련 이미지를 보거나 필요한 경우 더 많은 관련 기사를 볼 수 있습니다.

오차역전파 (Backprogation)의 개념을 쉽게 이해해 봅시다
오차역전파 (Backprogation)의 개념을 쉽게 이해해 봅시다

주제에 대한 기사 평가 back propagation 설명

  • Author: 테디노트 TeddyNote
  • Views: 조회수 15,852회
  • Likes: 좋아요 363개
  • Date Published: 2020. 11. 29.
  • Video Url link: https://www.youtube.com/watch?v=1Q_etC_GHHk

[머신러닝] Back Propagation(역전파) 정복하기

반응형

시작하며

오늘은 머신러닝에서 가장 큰 고비 중 하나인 ‘ Back Propagation(역전파) 알고리즘’ 에 대해 공부해보겠습니다.

알고리즘을 이해하기 어려울 수도 있고, 복잡한 수식이 나와 거부감이 드실 수도 있습니다.

하지만 정말 중요한 개념이니 조급해하지 마시고 최소 3번은 정독하며 완전히 이해하시고 다음 개념들을 공부하시길 바랍니다.

이번 포스팅은 아래 포스팅을 먼저 공부하시고 보시면 훨씬 효과적입니다.

https://box-world.tistory.com/17?category=397062

Neural Network의 목적

우리는 두개 혹은 그 이상의 결과값을 분류(Classification)하기 위해 Logistic Regression을 사용하였습니다.

그런데 만약 위와 같이 ‘non-linear’한 Decision Boundary가 필요한 경우 가설함수가 복잡해져 기존의 Logistic Regression으로는 연산이 어려웠지만 Neural Network로 이를 해결할 수 있었습니다.

우리가 Neural Network도 정규화된 Logistic Regression을 기반으로 그 목표는 최대한 실제값에 가깝게 잘 예측하는 것입니다.

이를 위해선 Neural Network를 학습시켜야 하고, 결국 학습시킨다는 말은 실제값과 예측값의 오차인 Cost(비용)을 최소화 한다는 것입니다.

우리가 익히 아는 Gradient Descent Algorithm을 Neural Network에 이용하여 Cost를 최소화해보겠습니다.

Neural Network 속 하나의 Unit은, Input과 가중치 W 가 곱해져 Z가 만들어집니다. 이를 sigmoid 함수 g에 넣어 도출된 결과값 g(Z)를 다음 Layer로 보냅니다.

최종적인 목표는 Cost를 최소화시키는 Neural Network 내의 모든 Unit의 가중치 W 를 찾는 것입니다.

이를 Neural Network를 최적화한다고 표현합니다.

Forward Propagation

본격적으로 Back Propagation을 알아보기 전, 위 Neural Network에서 Layer 2의 첫번째 Unit을 최적화하며, Forward Propagation의 문제점을 알아보겠습니다.

우선 Cost를 구하기 위해서는 Neural Network의 예측값을 구해야합니다.

따라서 Output Layer에서의 최종적인 예측값을 구하기 위해서는, Layer 3의 4개의 Unit이 각각의 g(z)값을 Output Layer에 보내줘야 합니다.

근데 이 layer 3의 g(z)을 각각 구하기 위해서는, Layer 2의 unit들은 ‘Input Layer’에서 받은 Input으로 g(z)값 을 계산해서 Layer 3에 보내줘야합니다.

이렇게 구한 예측값을 실제값에서 빼면 Cost를 구할 수 있게 됩니다.

그러면 현재 우리는 Gradient Descent Algorithm을 이용하고 있으므로, 계산한 Cost의 미분값에 learning rate를 곱하여 가중치 W에서 뺌으로써 한번의 갱신이 이뤄집니다.

근데 여기서 끝이 아닙니다! 우리는 한번의 갱신을 한것이지 Cost를 최소화하기 위해 이 짓을 적게는 몇 백번, 많게는 몇 천번을 연산해줘야 합니다.

백보 양보해서 하나의 Unit에서 최적화 하는데 성공했습니다. 그러나 우리는 이 짓을 Neural Network에 있는 나머지 Unit들에 대해서 똑같이 다 해줘야 합니다.

만약 우리가 사용하려는 Neural Network의 Layer가 100개였다면 이러한 방식은 연산량이 무한대에 가까울 것이며 불가능합니다.

이처럼 Forward Propagation은 Neural Network가 커질수록 최적화를 위한 연산량이 기하급수적으로 늘어나게 됩니다.

한동안 전문가들은 이러한 문제에 봉착하여 한동안 연구가 진전되지 못하다가 나오게 된것이 바로 Back Propagation입니다.

Back Propagation이란

‘Back Propagation’ 는 Output Layer 직전의 Layer부터 최적화합니다.

미리 말하고 싶은 것은 ‘Back Propagation’도 Gradient Descent를 이용합니다. 즉 앞서 배웠던 Forward Propagation처럼 Cost를 구하여 W를 여러번 갱신하여 최적화합니다.

다만 그 차이는 ‘Forward Propagation’은 한번의 갱신을 위한 Cost를 구하는데 비효율적으로 많은 연산을 필요로 합니다.

그러나 ‘Back Propagation’에서는 최적화의 순서를 달리하여 몇번의 연산만으로 Cost를 구할 수 있습니다.

Back Propagation 계산

Back Propagation 연산에서 핵심은 ‘Chain Rule’ 즉 연쇄법칙(함성함수의 도함수)입니다.

다시 말하지만 Back Propagation은 Cost를 최소화하기 위해 w를 갱신해야하며 이를 위해선 Cost의 미분값이 필요합니다. 이것이 위 이미지 좌측 상단의 ‘∂f / ∂w’ 이고 이것을 구하는데 이용되는 것이 연쇄법칙인 것입니다.

‘∂f / ∂w’을 [∂f//∂g와 ∂g/∂w의 곱] 으로 구할 수 있다는 부분에서 연쇄법칙이 이용됐음을 확인할 수 있습니다.

핵심은 우리가 하나의 Unit을 최적화하기 위해 Forward Propagation에선 엄청난 연산량이 필요했는데, Back Propagation에선 편미분값을 구해서 ‘한번의 곱셈’으로 아주 간단하게 구할 수 있다는 점입니다.

저런 방식으로 나머지 모든 Unit의 Cost 미분값을 간단하게 구하여 Neural Network를 최적화할 수 있습니다.

결론적으로 Back Propagation은 Output Layer에서 시작하여 직전 레이어로 이동하면서 Cost를 구하는 최적화 알고리즘으로, Chain Rule을 이용하여 Forward Propagatin에 비해 연산량을 현저히 줄이게 되었습니다.

아래 링크는 Back Propagation을 애니메이션화하여 알고리즘의 작동원리를 보다 쉽게 이해하는데 도움 될거라 생각합니다. (한글 자막도 있습니다!)

What is backpropagation really doing?

요약

제가 Back Propagation에서 이해가 안됐던 부분들을 하나씩 짚어가며, 맥락적으로 설명하고자 이번 포스팅을 굉장히 오랫동안 준비하였습니다.

따라서 여러분들도 제 포스팅을 통해서 Back Propagation을 공부하려 하신다면, 요약보다는 맥락에 집중하여 오늘 글의 흐름을 읽으려고 하시는게 좋을 거 같습니다.

반응형

[Deep Learning 시리즈] Backpropagation, 역전파 알아보기

이번 포스팅에서는 저번 포스팅에 이어 Backpropagation 에 대해서 알아보려고 한다. 앞서 설명했듯, 이 알고리즘으로 인해 Multi Layer Network 에서의 학습이 가능하다는 것이 알려져, 암흑기에 있던 Neural Network 학계가 다시 관심을 받게 되었다.

Backpropagation 은 오늘 날 Artificial Neural Network 를 학습시키기 위한 일반적인 알고리즘 중 하나이다. 한국말로 직역하면 역전파 라는 뜻인데, 내가 뽑고자 하는 target 값과 실제 모델이 계산한 output 이 얼마나 차이가 나는지 구한 후 그 오차값을 다시 뒤로 전파해가면서 각 노드가 가지고 있는 변수들을 갱신하는 알고리즘인 것이다.

다행히 여기까지는 직관적으로 이해가 되지만 필자는 다음 2가지의 원리가 궁금했다.

각 노드가 가지고 있는 weight 이나 bias 같은 변수들을 어떻게 업데이트할 것인가? Multi Layer Network 에서 각 노드나 레이어가 가지고 있는 변수들은 다 제 각각인데 그 값들을 얼만큼 변경하는 지 어떻게 알 수 있는가?

다행히 이 문제들은 Chain Rule 이라는 법칙을 사용해 해결할 수 있다고 한다. 한번 차근차근 살펴보자.

Chain Rule이란?

Chain Rule , 미분의 연쇄법칙이라고도 불리는 법칙이다. 이건 고딩때는 안배우고 대학수학에서 배우기 때문에, 대학 때 이산수학만 배웠던 필자는 이해가 잘되지않아서 고생했다. 먼저 정의부터 보자.

함수 f , g f, g f,g가 있을 때

f f f와 g g g가 모두 미분 가능하고

F = f ( g ( x ) ) = f ∘ g F = f(g(x)) = f \circ g F=f(g(x))=f∘g로 정의된 합성 함수이면 F F F는 미분 가능하다.

이때 F ′ ( x ) = f ′ ( g ( x ) ) ⋅ g ′ ( x ) F'(x) = f'(g(x)) \centerdot g'(x) F′(x)=f′(g(x))⋅g′(x)이다.

t = g ( x ) t = g(x) t=g(x)라고 한다면,

d y d x = d t d x d y d t \frac{dy}{dx} = \frac{dt}{dx} \frac{dy}{dt} dxdy​=dxdt​dtdy​가 성립한다.

정의를 보면 뭔 말인가 싶을 수 있는데, 먼저 합성함수 는 그냥 어떤 함수의 인자로 다른 함수가 주어진 함수이다. 대충 이런 식이랄까?

function f ( g ) { return g * 3 ; } function g ( x ) { return x + 1 ; } const x = 3 ; let F = f ( g ( x ) ) ;

그럼 미분 가능하다 라는 말이 의미하는 것은 뭘까? 보통 미분 = x와 x’간의 기울기를 구한다 정도로 이해하고 있다면 합성함수 어쩌고에서 기울기를 왜 구하지? 라고 생각할 수 있다.

하지만 기울기를 구한다 라는 말은 변화량을 구한다 라고도 할 수 있다. 위의 코드를 보면 변수 F 를 선언할 때 g 에 주는 값을 변경한다면 최종적으로 F 값이 바뀐다는 것을 알 수 있을 것이다.

F = f ( g ( 4 ) ) ; F = f ( g ( 2 ) ) ;

즉 Chain Rule 이란 쉽게 얘기하자면 1. x가 변화했을 때 함수 g가 얼마나 변하는 지 와 그로인해 2. 함수 g의 변화로 인해 함수 f가 얼마나 변하는 지 를 알 수 있고 3. 함수 f의 인자가 함수 g이면 최종 값 F 의 변화량에 기여하는 각 함수 f 와 g 의 기여도를 알 수 있다는 것이다.

방금 전 위에서 예시로 든 합성함수 F 의 식에 들어가는 변수는 x 하나였다. 그럼 변수가 여러 개면 어떻게 되는 걸까?

이변수함수 z = f ( x , y ) z = f(x, y) z=f(x,y)에서 x = h ( s , t ) , y = g ( s , t ) x = h(s,t), y = g(s,t) x=h(s,t),y=g(s,t)일 때

f ( x , y ) , g ( s , t ) , h ( s , t ) f(x,y), g(s,t), h(s,t) f(x,y),g(s,t),h(s,t)가 모두 미분 가능하면

∂ z ∂ s = ∂ z ∂ x ∂ x ∂ s + ∂ z ∂ y ∂ y ∂ s ∂ z ∂ t = ∂ z ∂ x ∂ x ∂ t + ∂ z ∂ y ∂ y ∂ t \begin{aligned} \frac{\partial z}{\partial s} = \frac{\partial z}{\partial x}\frac{\partial x}{\partial s} + \frac{\partial z}{\partial y}\frac{\partial y}{\partial s} \\ \\ \frac{\partial z}{\partial t} = \frac{\partial z}{\partial x}\frac{\partial x}{\partial t} + \frac{\partial z}{\partial y}\frac{\partial y}{\partial t} \\ \end{aligned} ∂ s ∂ z ​ = ∂ x ∂ z ​ ∂ s ∂ x ​ + ∂ y ∂ z ​ ∂ s ∂ y ​ ∂ t ∂ z ​ = ∂ x ∂ z ​ ∂ t ∂ x ​ + ∂ y ∂ z ​ ∂ t ∂ y ​ ​

로 나타내어질 수 있다.

이 말인 즉슨 s s s나 t t t가 얼만큼인지는 모르지만 어쨌든 변했을 때, 함수 z z z의 변화량을 저런 식으로 구할 수 있다는 것이다.

그리고 ∂ \partial ∂는 편미분 을 뜻하는 기호인데, 메인이 되는 변수 하나를 남겨두고 나머지 변수는 그냥 개무시하는 미분법이다. 그래서 s s s와 z z z의 관계를 구하는 식에서는 아예 t t t가 없는 것을 알 수 있다.

여기까지 이해가 되었다면 이제 본격적으로 Backpropagation 이 어떻게 진행되는 지 살펴보도록 하자.

이제 직접 Backpropagation 이 어떻게 이루어지는 지 한번 계산해보자.

그 전에 먼저 Forward Propagation 을 진행해야한다. 초기화한 w w w값과 input인 x x x을 가지고 계산을 진행한 뒤 우리가 원하는 값이 나오는 지, 나오지 않았다면 얼마나 차이가 나는지를 먼저 구해야한다.

필자가 이번 계산에 사용할 모델은 아래와 같다.

이 모델은 2개의 input, 2개의 output을 가지고 2개의 Hidden Layer를 가진 2-Layer NN 모델이다. 이제 각 변수에 값을 할당해보자.

먼저 필자가 output으로 원하는 y 1 y_1 y1​의 값은 0.2 , y 2 y_2 y2​의 값은 0.7 이다. 그리고 input으로는 x 1 x_1 x1​에 0.2 , x 2 x_2 x2​에 0.5 를 넣어주었고, 각각의 w w w값은 그냥 느낌 가는대로 넣어놓았다.

필자는 이 계산에서 Activation Function 으로 Sigmoid 함수를 사용하고, Error Function 은 Mean Squared Error 함수를 사용하려고 한다.

먼저 Layer0에서 받을 값부터 계산해보자. 보통 행렬로 계산한다.

z 10 = [ x 1 x 2 ] × [ w 10 0 w 20 0 ] z 11 = [ x 1 x 2 ] × [ w 11 0 w 21 0 ] \begin{aligned} z_{10} = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} \times \begin{bmatrix} w^0_{10} & w^0_{20} \end{bmatrix} \\ \\ z_{11} = \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} \times \begin{bmatrix} w^0_{11} & w^0_{21} \end{bmatrix} \\ \end{aligned} z 1 0 ​ = [ x 1 ​ x 2 ​ ​ ] × [ w 1 0 0 ​ ​ w 2 0 0 ​ ​ ] z 1 1 ​ = [ x 1 ​ x 2 ​ ​ ] × [ w 1 1 0 ​ ​ w 2 1 0 ​ ​ ] ​

저 행렬 곱을 풀어보면 다음과 같이 되고 결국 w x wx wx들의 합의 형태로 나타난다.

z 10 = x 1 w 10 0 + x 2 w 20 0 = ( 0.2 × 0.1 ) + ( 0.5 × 0.3 ) = 0.02 + 0.15 = 0.17 z 11 = x 1 w 11 0 + x 2 w 21 0 = ( 0.2 × 0.2 ) + ( 0.5 × 0.1 ) = 0.04 + 0.05 = 0.09 \begin{aligned} z_{10} = x_1w^0_{10} + x_2w^0_{20} = (0.2\times0.1) + (0.5\times0.3) = 0.02 + 0.15 = 0.17 \\ \\ z_{11} = x_1w^0_{11} + x_2w^0_{21} = (0.2\times0.2) + (0.5\times0.1) = 0.04 + 0.05 = 0.09 \\ \end{aligned} z 1 0 ​ = x 1 ​ w 1 0 0 ​ + x 2 ​ w 2 0 0 ​ = ( 0 . 2 × 0 . 1 ) + ( 0 . 5 × 0 . 3 ) = 0 . 0 2 + 0 . 1 5 = 0 . 1 7 z 1 1 ​ = x 1 ​ w 1 1 0 ​ + x 2 ​ w 2 1 0 ​ = ( 0 . 2 × 0 . 2 ) + ( 0 . 5 × 0 . 1 ) = 0 . 0 4 + 0 . 0 5 = 0 . 0 9 ​

z 10 z_{10} z10​와 z 11 z_{11} z11​의 값을 구했으면 이제 Activation Function 을 사용하여 a 10 a_{10} a10​와 a 11 a_{11} a11​값을 구해보자. 필자가 사용할 Activation Function 인 Sigmoid 의 수식은 다음과 같다.

σ = 1 1 + e − x \sigma = \frac{1}{1 + e^{-x}} σ = 1 + e − x 1 ​

이걸 매번 손으로 계산하면 너무 번거롭기 때문에 JavaScript를 사용해 다음과 같이 함수를 하나 만들어 놓고 사용했다.

function sigmoid ( x ) { return 1 / ( 1 + Math . exp ( – x ) ) ; }

a 10 = σ ( z 10 ) = 0.54 a 11 = σ ( z 11 ) = 0.52 \begin{aligned} a_{10} = \sigma(z_{10}) = 0.54 \\ \\ a_{11} = \sigma(z_{11}) = 0.52 \\ \end{aligned} a 1 0 ​ = σ ( z 1 0 ​ ) = 0 . 5 4 a 1 1 ​ = σ ( z 1 1 ​ ) = 0 . 5 2 ​

다음 레이어도 같은 방식으로 값을 계속 구해보면 다음과 같은 값들을 구할 수 있다.

z 10 = 0.17 a 10 = 0.54 z 11 = 0.09 a 11 = 0.52 z 20 = 0.27 a 20 = 0.57 z 21 = 0.43 a 21 = 0.61 \begin{aligned} z_{10} = 0.17 \\ a_{10} = 0.54 \\ \\ z_{11} = 0.09 \\ a_{11} = 0.52 \\ \\ z_{20} = 0.27 \\ a_{20} = 0.57 \\ \\ z_{21} = 0.43 \\ a_{21} = 0.61 \\ \end{aligned} z 1 0 ​ = 0 . 1 7 a 1 0 ​ = 0 . 5 4 z 1 1 ​ = 0 . 0 9 a 1 1 ​ = 0 . 5 2 z 2 0 ​ = 0 . 2 7 a 2 0 ​ = 0 . 5 7 z 2 1 ​ = 0 . 4 3 a 2 1 ​ = 0 . 6 1 ​

결국 y 1 y_1 y1​와 y 2 y_2 y2​는 각각 a 20 a_{20} a20​과 a 21 a_{21} a21​과 같으므로, 우리는 최종 output값을 구하게 되었다. 근데 우리가 처음에 원했던 y 1 y_1 y1​과 y 2 y_2 y2​는 0.2 와 0.7 이었는데, 우리가 구한 output은 0.57 과 0.61 으로 거리가 있다.

이제 Mean Squared Error 함수를 사용하여 에러 E E E를 구할 차례이다. 결과값으로 얻기를 바라는 값을 t t t로, 실제 나온 값을 y y y라고 할 때 에러 E E E는 다음과 같다.

E = 1 2 ∑ ( t i − y i ) 2 E = \frac{1}{2}\sum(t_i – y_i)^2 E = 2 1 ​ ∑ ( t i ​ − y i ​ ) 2

필자같은 수포자를 위해 쉽게 설명하자면, 그냥 마지막 Output Layer에서 뱉어낸 y y y들과 하나하나 레이블링했던 y ^ \hat{y} y^​가 얼마나 차이나는 지 구한 다음에 그 값들의 평균을 내는 것이다.

결국 ANN 을 학습시킨다는 것은 이렇게 구한 에러 E E E의 값을 0에 근사시킨다고 볼 수 있다. 여기서 나온 E E E값을 이제 Backpropagation 하면 되는 것이다.

이것도 매번 손으로 계산하기 귀찮으니까 그냥 함수를 하나 만들자.

function MSE ( targets , values ) { if ( values instanceof Array === false ) { return false ; } let result = 0 ; targets . forEach ( ( target , i ) => { result += 0.5 * ( target – values [ i ] ) ** 2 ; } ) ; return result ; } MSE ( [ 0.2 , 0.7 ] , [ 0.57 , 0.61 ] ) ;

이제 여기서 구한 에러 E E E값을 사용하여 Backpropagation 을 진행해보자.

Backpropagation

Frontend Propagation 을 통해서 구해진 값을 다시 그림으로 살펴보면 다음과 같다.

필자는 이 중 현재 0.4 로 할당되어 있는 w 10 1 w^1_{10} w101​값을 업데이트 하려고 한다. 그러려면 w 10 1 w^1_{10} w101​이 전체 에러인 E E E에 얼마나 영향을 미쳤는지, 즉 기여도를 구해야한다. 이때 위에서 설명한 Chain Rule 이 사용된다.

E E E에 대한 w 10 1 w^1_{10} w101​의 기여도를 식으로 풀어보면 다음과 같다.

∂ E ∂ w 10 1 = ∂ E ∂ a 20 ∂ a 20 ∂ z 20 ∂ z 20 ∂ w 10 1 \begin{aligned} \frac{\partial E}{\partial w^1_{10}} = \frac{\partial E}{\partial a_{20}} \frac{\partial a_{20}}{\partial z_{20}} \frac{\partial z_{20}}{\partial w^1_{10}} \\ \end{aligned} ∂ w 1 0 1 ​ ∂ E ​ = ∂ a 2 0 ​ ∂ E ​ ∂ z 2 0 ​ ∂ a 2 0 ​ ​ ∂ w 1 0 1 ​ ∂ z 2 0 ​ ​ ​

먼저 ∂ E ∂ a 20 \frac{\partial E}{\partial a_{20}} ∂a20​∂E​부터 차례대로 풀어보자. 원래 우리가 구한 E E E는 아래와 같은 식이였다.

E = 1 2 ( ( t 1 − a 20 ) 2 + ( t 2 − a 21 ) 2 ) E = \frac{1}{2}((t_1 – a_{20})^2 + (t_2 -a_{21})^2) E = 2 1 ​ ( ( t 1 ​ − a 2 0 ​ ) 2 + ( t 2 ​ − a 2 1 ​ ) 2 )

여기서 a 20 = y 1 , a 21 = y 2 a_{20} = y_1, a_{21} = y_2 a20​=y1​,a21​=y2​이기 때문에 치환해주었다. 하지만 ∂ E ∂ a 20 \frac{\partial E}{\partial a_{20}} ∂a20​∂E​는 편미분식이기 때문에 지금 구하려는 값과 상관없는 a 21 a_{21} a21​는 그냥 0 으로 생각하고 풀면된다.

∂ E ∂ a 20 = ( t 1 − a 20 ) ∗ − 1 + 0 = ( 0.2 − 0.57 ) × − 1 = 0.37 \begin{aligned} \frac{\partial E}{\partial a_{20}} = (t_1 – a_{20}) * -1 + 0 = (0.2 – 0.57) \times -1 = 0.37 \\ \end{aligned} ∂ a 2 0 ​ ∂ E ​ = ( t 1 ​ − a 2 0 ​ ) ∗ − 1 + 0 = ( 0 . 2 − 0 . 5 7 ) × − 1 = 0 . 3 7 ​

이 계산 결과가 의미하는 것은 전체 에러 E E E에 대하여 a 20 a_{20} a20​, 즉 y 1 y_1 y1​가 0.37 만큼 기여했다는 것을 의미한다. 이런 식으로 계속 계산해보자.

∂ a 20 ∂ z 20 = a 20 × ( 1 − a 20 ) = 0.57 × ( 1 − 0.57 ) = 0.25 \begin{aligned} \frac{\partial a_{20}}{\partial z_{20}} = a_{20} \times (1 – a_{20}) = 0.57 \times (1 – 0.57) = 0.25 \\ \end{aligned} ∂ z 2 0 ​ ∂ a 2 0 ​ ​ = a 2 0 ​ × ( 1 − a 2 0 ​ ) = 0 . 5 7 × ( 1 − 0 . 5 7 ) = 0 . 2 5 ​

∂ z 20 ∂ w 10 1 = a 10 + 0 = 0.54 \begin{aligned} \frac{\partial z_{20}}{\partial w^1_{10}} = a_{10} + 0 = 0.54 \\ \end{aligned} ∂ w 1 0 1 ​ ∂ z 2 0 ​ ​ = a 1 0 ​ + 0 = 0 . 5 4 ​

∂ E ∂ w 10 1 = 0.37 × 0.25 × 0.54 = 0.049 \begin{aligned} \frac{\partial E}{\partial w^1_{10}} = 0.37 \times 0.25 \times 0.54 = 0.049 \\ \end{aligned} ∂ w 1 0 1 ​ ∂ E ​ = 0 . 3 7 × 0 . 2 5 × 0 . 5 4 = 0 . 0 4 9 ​

최종적으로 E E E에 w 10 1 w^1_{10} w101​가 기여한 값은 0.049 이라는 값을 계산했다. 이제 이 값을 학습식에 넣으면 w 10 1 w^1_{10} w101​값을 업데이트 할 수 있다.

이때 값을 얼마나 건너뛸 것이냐 또는 얼마나 빨리 학습시킬 것이냐 등을 정하는 Learning Rate 라는 값이 필요한데, 이건 그냥 사람이 정하는 상수이고 보통 0.1 보다 낮은 값으로 설정하나 필자는 0.3 으로 잡았다.

w 10 1 + = w 10 1 − ( L ∗ ∂ E ∂ w 10 1 ) = 0.4 − ( 0.3 × 0.049 ) = 0.3853 \begin{aligned} w^{1+}_{10} = w^1_{10} – (L * \frac{\partial E}{\partial w^1_{10}}) = 0.4 – (0.3 \times 0.049) = 0.3853 \end{aligned} w 1 0 1 + ​ = w 1 0 1 ​ − ( L ∗ ∂ w 1 0 1 ​ ∂ E ​ ) = 0 . 4 − ( 0 . 3 × 0 . 0 4 9 ) = 0 . 3 8 5 3 ​

이렇게 해서 필자는 새로운 w 10 1 w^1_{10} w101​값인 0.3853 을 얻었다. 이런 식으로 다른 w w w값을 계속 업데이트 해보자. 이번에는 Layer1보다 한 층 더 깊숙히 있는 Layer0의 w 0 10 w^0{10} w010값을 업데이트 할 것이다.

보다시피 w 10 0 w^0_{10} w100​은 w 10 1 w^1_{10} w101​보다 많은 값에 영향을 미치고 있다. 전체 에러 E t E_t Et​에 w 10 0 w^0_{10} w100​가 기여한 정도는 다음과 같이 나타낼 수 있다.

∂ E t ∂ w 10 0 = ( ∂ E 1 ∂ a 10 + ∂ E 2 ∂ a 10 ) ∂ a 10 ∂ z 10 ∂ z 10 ∂ w 10 0 \begin{aligned} \frac{\partial E_t}{\partial w^0_{10}} = (\frac{\partial E_1}{\partial a_{10}} + \frac{\partial E_2}{\partial a_{10}}) \frac{\partial a_{10}}{\partial z_{10}} \frac{\partial z_{10}}{\partial w^0_{10}} \end{aligned} ∂ w 1 0 0 ​ ∂ E t ​ ​ = ( ∂ a 1 0 ​ ∂ E 1 ​ ​ + ∂ a 1 0 ​ ∂ E 2 ​ ​ ) ∂ z 1 0 ​ ∂ a 1 0 ​ ​ ∂ w 1 0 0 ​ ∂ z 1 0 ​ ​ ​

그럼 먼저 ∂ E 1 ∂ a 10 \frac{\partial E_1}{\partial a_{10}} ∂a10​∂E1​​부터 구해보자.

∂ E 1 ∂ a 10 = ∂ E 1 ∂ a 20 ∂ a 20 ∂ z 20 ∂ z 20 ∂ a 10 = − ( t 1 − a 20 ) × a 20 × ( 1 − a 20 ) × w 10 1 = − ( 0.2 − 0.57 ) × 0.57 × ( 1 − 0.57 ) × 0.4 = 0.03627 \begin{aligned} \frac{\partial E_1}{\partial a_{10}} = \frac{\partial E_1}{\partial a_{20}} \frac{\partial a_{20}}{\partial z_{20}} \frac{\partial z_{20}}{\partial a_{10}}\\ \\ = -(t_1 – a_{20}) \times a_{20} \times (1 – a_{20}) \times w^1_{10} \\ \\ = -(0.2 – 0.57) \times 0.57 \times (1 – 0.57) \times 0.4 \\ \\ = 0.03627 \end{aligned} ∂ a 1 0 ​ ∂ E 1 ​ ​ = ∂ a 2 0 ​ ∂ E 1 ​ ​ ∂ z 2 0 ​ ∂ a 2 0 ​ ​ ∂ a 1 0 ​ ∂ z 2 0 ​ ​ = − ( t 1 ​ − a 2 0 ​ ) × a 2 0 ​ × ( 1 − a 2 0 ​ ) × w 1 0 1 ​ = − ( 0 . 2 − 0 . 5 7 ) × 0 . 5 7 × ( 1 − 0 . 5 7 ) × 0 . 4 = 0 . 0 3 6 2 7 ​

마찬가지로 ∂ E 2 ∂ a 10 \frac{\partial E_2}{\partial a_{10}} ∂a10​∂E2​​도 구해본다.

∂ E 2 ∂ a 10 = ∂ E 2 ∂ a 21 ∂ a 21 ∂ z 21 ∂ z 21 ∂ a 10 = − ( t 2 − a 21 ) × a 21 × ( 1 − a 21 ) × w 11 1 = − ( 0.7 − 0.61 ) × 0.61 × ( 1 − 0.61 ) × 0.5 = − 0.0107 \begin{aligned} \frac{\partial E_2}{\partial a_{10}} = \frac{\partial E_2}{\partial a_{21}} \frac{\partial a_{21}}{\partial z_{21}} \frac{\partial z_{21}}{\partial a_{10}}\\ \\ = -(t_2 – a_{21}) \times a_{21} \times (1 – a_{21}) \times w^1_{11} \\ \\ = -(0.7 – 0.61) \times 0.61 \times (1 – 0.61) \times 0.5 \\ \\ = -0.0107 \end{aligned} ∂ a 1 0 ​ ∂ E 2 ​ ​ = ∂ a 2 1 ​ ∂ E 2 ​ ​ ∂ z 2 1 ​ ∂ a 2 1 ​ ​ ∂ a 1 0 ​ ∂ z 2 1 ​ ​ = − ( t 2 ​ − a 2 1 ​ ) × a 2 1 ​ × ( 1 − a 2 1 ​ ) × w 1 1 1 ​ = − ( 0 . 7 − 0 . 6 1 ) × 0 . 6 1 × ( 1 − 0 . 6 1 ) × 0 . 5 = − 0 . 0 1 0 7 ​

이제 ∂ E 1 ∂ a 10 \frac{\partial E_1}{\partial a_{10}} ∂a10​∂E1​​와 ∂ E 2 ∂ a 10 \frac{\partial E_2}{\partial a_{10}} ∂a10​∂E2​​를 전부 구했으니 ∂ E t ∂ w 10 0 \frac{\partial E_t}{\partial w^0_{10}} ∂w100​∂Et​​를 구할 차례이다.

∂ E t ∂ w 10 0 = ( ∂ E 1 ∂ a 10 + ∂ E 2 ∂ a 10 ) ∂ a 10 ∂ z 10 ∂ z 10 ∂ w 10 0 = ( 0.03627 + ( − 0.0107 ) ) × 0.2484 × 0.54 = 0.0034 \begin{aligned} \frac{\partial E_t}{\partial w^0_{10}} = (\frac{\partial E_1}{\partial a_{10}} + \frac{\partial E_2}{\partial a_{10}}) \frac{\partial a_{10}}{\partial z_{10}} \frac{\partial z_{10}}{\partial w^0_{10}} \\ \\ = (0.03627 + (-0.0107)) \times 0.2484 \times 0.54 \\ \\ = 0.0034 \end{aligned} ∂ w 1 0 0 ​ ∂ E t ​ ​ = ( ∂ a 1 0 ​ ∂ E 1 ​ ​ + ∂ a 1 0 ​ ∂ E 2 ​ ​ ) ∂ z 1 0 ​ ∂ a 1 0 ​ ​ ∂ w 1 0 0 ​ ∂ z 1 0 ​ ​ = ( 0 . 0 3 6 2 7 + ( − 0 . 0 1 0 7 ) ) × 0 . 2 4 8 4 × 0 . 5 4 = 0 . 0 0 3 4 ​

이로써 w 10 0 w^0_{10} w100​이 전체 에러 E t E_t Et​에 0.0034 만큼 기여한다는 걸 알아냈다. 이제 이 값을 사용하여 w 10 0 w^0_{10} w100​값을 업데이트하자. Learning Rate 는 아까와 동일한 0.3 이다.

w 10 0 + = w 10 0 − ( L ∗ ∂ E t ∂ w 10 0 ) = 0.1 − ( 0.3 × 0.0034 ) = 0.09897 \begin{aligned} w^{0+}_{10} = w^0_{10} – (L * \frac{\partial E_t}{\partial w^0_{10}}) = 0.1 – (0.3 \times 0.0034) = 0.09897 \end{aligned} w 1 0 0 + ​ = w 1 0 0 ​ − ( L ∗ ∂ w 1 0 0 ​ ∂ E t ​ ​ ) = 0 . 1 − ( 0 . 3 × 0 . 0 0 3 4 ) = 0 . 0 9 8 9 7 ​

코딩하기

필자는 도저히 이걸 8번이나 손으로 풀 수 있는 사람이 아니기 때문에 JavaScript를 사용하여 위에 설명했던 공식을 간단하게 코드로 작성해보았다.

function sigmoid ( x ) { return 1 / ( 1 + Math . exp ( – x ) ) ; } function MSE ( targets , values ) { if ( values instanceof Array === false ) { return false ; } let result = 0 ; targets . forEach ( ( target , i ) => { result += 0.5 * ( target – values [ i ] ) ** 2 ; } ) ; return result ; } const x1 = 0.2 ; const x2 = 0.5 ; const t1 = 0.2 ; const t2 = 0.7 ; const w0 = [ [ 0.1 , 0.2 ] , [ 0.3 , 0.1 ] , ] ; const w1 = [ [ 0.4 , 0.5 ] , [ 0.1 , 0.3 ] , ] ; const learningRate = 0.3 ; const limit = 1000 ; function updateSecondLayerWeight ( targetY , y , prevY , updatedWeight ) { const v1 = – ( targetY – y ) + 0 ; const v2 = y * ( 1 – y ) ; const def = v1 * v2 * prevY ; return updatedWeight – learningRate * def ; } function updateFirstLayerWeight ( t1 , t2 , y1 , y2 , w1 , w2 , a , updatedWeight ) { const e1 = – ( t1 – y1 ) * y1 * ( 1 – y1 ) * w1 ; const e2 = – ( t2 – y2 ) * y2 * ( 1 – y2 ) * w2 ; const v1 = a * ( 1 – a ) ; const v2 = a ; const def = ( e1 + e2 ) * v1 * v2 ; return updatedWeight – learningRate * def ; } let i = 0 ; for ( i ; i < limit ; i ++ ) { let z10 = x1 * w0 [ 0 ] [ 0 ] + x2 * w0 [ 1 ] [ 0 ] ; let a10 = sigmoid ( z10 ) ; let z11 = x1 * w0 [ 0 ] [ 1 ] + x2 * w0 [ 1 ] [ 1 ] ; let a11 = sigmoid ( z11 ) ; let z20 = a10 * w1 [ 0 ] [ 0 ] + a11 * w1 [ 1 ] [ 0 ] ; let a20 = sigmoid ( z20 ) ; let z21 = a10 * w1 [ 0 ] [ 1 ] + a11 * w1 [ 1 ] [ 1 ] ; let a21 = sigmoid ( z21 ) ; let e_t = MSE ( [ t1 , t2 ] , [ a20 , a21 ] ) ; console . log ( ` [ ${ i } ] y1 = ${ a20 } , y2 = ${ a21 } , E = ${ e_t } ` ) ; const newW0 = [ [ updateFirstLayerWeight ( t1 , t2 , a20 , a21 , w1 [ 0 ] [ 0 ] , w1 [ 0 ] [ 1 ] , a10 , w0 [ 0 ] [ 0 ] ) , updateFirstLayerWeight ( t1 , t2 , a20 , a21 , w1 [ 1 ] [ 0 ] , w1 [ 1 ] [ 1 ] , a11 , w0 [ 0 ] [ 1 ] ) , ] , [ updateFirstLayerWeight ( t1 , t2 , a20 , a21 , w1 [ 0 ] [ 0 ] , w1 [ 0 ] [ 1 ] , a10 , w0 [ 1 ] [ 0 ] ) , updateFirstLayerWeight ( t1 , t2 , a20 , a21 , w1 [ 1 ] [ 0 ] , w1 [ 1 ] [ 1 ] , a11 , w0 [ 1 ] [ 1 ] ) , ] , ] ; const newW1 = [ [ updateSecondLayerWeight ( t1 , a20 , a10 , w1 [ 0 ] [ 0 ] ) , updateSecondLayerWeight ( t2 , a21 , a10 , w1 [ 0 ] [ 1 ] ) ] , [ updateSecondLayerWeight ( t1 , a20 , a11 , w1 [ 1 ] [ 0 ] ) , updateSecondLayerWeight ( t2 , a21 , a11 , w1 [ 1 ] [ 1 ] ) ] , ] ; newW0 . forEach ( ( v , i ) => { v . forEach ( ( vv , ii ) => ( w0 [ i ] [ ii ] = vv ) ) ; } ) ; newW1 . forEach ( ( v , i ) => { v . forEach ( ( vv , ii ) => ( w1 [ i ] [ ii ] = vv ) ) ; } ) ; } console . log ( ` t1 = ${ t1 } , t2 = ${ t2 } ` ) ;

계산된 결과들을 보면 처음에 Multi Layer Network 에 넣었던 x1 과 x2 가 점점 t1 과 t2 로 수렴하는 것을 볼 수 있다. 1000번 돌린 결과를 전부 볼 수는 없으니까 처음과 중간, 마지막 진행 상황을 첨부한다.

다음 포스팅에서는 좀 더 구조화한 네트워크를 만들어보려고 한다. 이상으로 Backpropagation 포스팅을 마친다.

딥러닝 역전파 backpropagation이란?

<개요>

이전 글에서 설명했듯이 활성화 함수를 적용시킨 MLP에서 XOR과 같은 non-linear 문제들은 해결할 수 있었지만 layer가 깊어질수록 파라미터의 개수가 급등하게 되고 이 파라미터들을 적절하게 학습시키는 것이 매우 어려웠다.

그리고 이는 역전파 알고리즘이 등장하게 되면서 해결되었고 결론적으로 여러 layer를 쌓은 신경망 모델을 학습시키는 것이 가능해졌다.

<역전파>

역전파 알고리즘은 출력값에 대한 입력값의 기울기(미분값)을 출력층 layer에서부터 계산하여 거꾸로 전파시키는 것이다.

이렇게 거꾸로 전파시켜서 최종적으로 출력층에서의 output값에 대한 입력층에서의 input data의 기울기 값을 구할 수 있다.

이 과정에는 중요한 개념인 chain rule이 이용된다.

출력층 바로 전 layer에서부터 기울기(미분값)을 계산하고 이를 점점 거꾸로 전파시키면서 전 layer들에서의 기울기와 서로 곱하는 형식으로 나아가면 최종적으로 출력층의 output에 대한 입력층에서의 input의 기울기(미분값)을 구할 수가 있다. 이를 그림으로 나타내면 아래와 같다.

출처 : https://www.youtube.com/watch?v=nJyUyKN-XBQ&list=PLkDaE6sCZn6Ec-XTbcX1uRg2_u4xOEky0&index=14

1. 그럼 이렇게 기울기(미분값)을 구하는 이유는 무엇이고

2. 최종 output에 대한 기울기 값을 각 layer별로 구하는 이유가 무엇일까??

역전파 알고리즘이 해결한 문제가 바로 파라미터가 매우 많고 layer가 여러개 있을때 가중치w와 b를 학습시키기 어려웠다는 문제이다. 그리고 이는 역전파 알고리즘으로 각 layer에서 기울기 값을 구하고 그 기울기 값을 이용하여 Gradient descent 방법으로 가중치w와 b를 update시키면서 해결된 것이다.

즉, layer에서 기울기 값을 구하는 이유는 Gradient descent를 이용하여 가중치를 update하기 위함이다.

이때 각 layer의 node(parameter)별로 학습을 해야하기 때문에 각 layer의 node별로 기울기 값을 계산해야하는 것이다.

Gradient descent notation

04-3) 역전파(BackPropagation) 이해하기

인공 신경망이 순전파 과정을 진행하여 예측값과 실제값의 오차를 계산하였을 때 어떻게 역전파 과정에서 경사 하강법을 사용하여 가중치를 업데이트하는지 직접 계산을 통해 이해해봅시다.

1. 인공 신경망의 이해(Neural Network Overview)

우선 예제를 위해 사용될 인공 신경망을 소개합니다. 역전파의 이해를 위해서 여기서 사용할 인공 신경망은 입력층, 은닉층, 출력층 이렇게 3개의 층을 가집니다. 또한 해당 인공 신경망은 두 개의 입력과, 두 개의 은닉층 뉴런, 두 개의 출력층 뉴런을 사용합니다. 은닉층과 출력층의 모든 뉴런은 활성화 함수로 시그모이드 함수를 사용합니다.

위의 그림은 여기서 사용할 인공 신경망의 모습을 보여줍니다. 은닉층과 출력층의 모든 뉴런에서 변수 $z$가 존재하는데 여기서 변수 $z$는 이전층의 모든 입력이 각각의 가중치와 곱해진 값들이 모두 더해진 가중합을 의미합니다. 이 값은 뉴런에서 아직 시그모이드 함수를 거치지 않은 상태입니다. 즉, 활성화 함수의 입력을 의미합니다. $z$ 우측의 |를 지나서 존재하는 변수 $h$ 또는 $o$는 $z$가 시그모이드 함수를 지난 후의 값으로 각 뉴런의 출력값을 의미합니다. 이번 역전파 예제에서는 인공 신경망에 존재하는 모든 가중치 $w$에 대해서 역전파를 통해 업데이트하는 것을 목표로합니다. 해당 인공 신경망은 편향 $b$는 고려하지 않습니다.

2. 순전파(Forward Propagation)

주어진 값이 위의 그림과 같을 때 순전파를 진행해봅시다. 위의 그림에서 소수점 앞의 0은 생략하였습니다. 예를 들어 .25는 0.25를 의미합니다. 파란색 숫자는 입력값을 의미하며, 빨간색 숫자는 각 가중치의 값을 의미합니다. 앞으로 진행하는 계산의 결과값은 소수점 아래 여덟번째 자리까지 반올림하여 표기합니다.

각 입력은 입력층에서 은닉층 방향으로 향하면서 각 입력에 해당하는 가중치와 곱해지고, 결과적으로 가중합으로 계산되어 은닉층 뉴런의 시그모이드 함수의 입력값이 됩니다. $z_{1}$과 $z_{2}$는 시그모이드 함수의 입력으로 사용되는 각각의 값에 해당됩니다.

$$z_{1}=w_{1}x_{1} + w_{2}x_{2}=0.3 \text{×} 0.1 + 0.25 \text{×} 0.2= 0.08$$ $$z_{2}=w_{3}x_{1} + w_{4}x_{2}=0.4 \text{×} 0.1 + 0.35 \text{×} 0.2= 0.11$$ $z_{1}$과 $z_{2}$는 각각의 은닉층 뉴런에서 시그모이드 함수를 지나게 되는데 시그모이드 함수가 리턴하는 결과값은 은닉층 뉴런의 최종 출력값입니다. 식에서는 각각 $h_{1}$과 $h_{2}$에 해당되며, 아래의 결과와 같습니다. $$h_{1}=sigmoid(z_{1}) = 0.51998934$$ $$h_{2}=sigmoid(z_{2}) = 0.52747230$$ $h_{1}$과 $h_{2}$ 이 두 값은 다시 출력층의 뉴런으로 향하게 되는데 이때 다시 각각의 값에 해당되는 가중치와 곱해지고, 다시 가중합 되어 출력층 뉴런의 시그모이드 함수의 입력값이 됩니다. 식에서는 각각 $z_{3}$과 $z_{4}$에 해당됩니다. $$z_{3}=w_{5}h_{1}+w_{6}h_{2} = 0.45 \text{×} h_{1} + 0.4 \text{×} h_{2} = 0.44498412$$ $$z_{4}=w_{7}h_{1}+w_{8}h_{2} = 0.7 \text{×} h_{1} + 0.6 \text{×} h_{2} = 0.68047592$$ $z_{3}$과 $z_{4}$이 출력층 뉴런에서 시그모이드 함수를 지난 값은 이 인공 신경망이 최종적으로 계산한 출력값입니다. 실제값을 예측하기 위한 값으로서 예측값이라고도 부릅니다. $$o_{1}=sigmoid(z_{3})=0.60944600$$ $$o_{2}=sigmoid(z_{4})=0.66384491$$ 이제 해야할 일은 예측값과 실제값의 오차를 계산하기 위한 오차 함수를 선택하는 것입니다. 오차(Error)를 계산하기 위한 손실 함수(Loss function)로는 평균 제곱 오차 MSE를 사용합니다. 식에서는 실제값을 target이라고 표현하였으며, 순전파를 통해 나온 예측값을 output으로 표현하였습니다. 그리고 각 오차를 모두 더하면 전체 오차 $E_{total}$가 됩니다. $$E_{o1}=\frac{1}{2}(target_{o1}-output_{o1})^{2}=0.02193381$$ $$E_{o2}=\frac{1}{2}(target_{o2}-output_{o2})^{2}=0.00203809$$ $$E_{total}=E_{o1}+E_{o2}=0.02397190$$

3. 역전파 1단계(BackPropagation Step 1)

순전파가 입력층에서 출력층으로 향한다면 역전파는 반대로 출력층에서 입력층 방향으로 계산하면서 가중치를 업데이트해갑니다. 출력층 바로 이전의 은닉층을 N층이라고 하였을 때, 출력층과 N층 사이의 가중치를 업데이트하는 단계를 역전파 1단계, 그리고 N층과 N층의 이전층 사이의 가중치를 업데이트 하는 단계를 역전파 2단계라고 해봅시다.

역전파 1단계에서 업데이트 해야 할 가중치는 $w_{5}, w_{6}, w_{7}, w_{8}$ 총 4개입니다. 원리 자체는 동일하므로 우선 $w_{5}$에 대해서 먼저 업데이트를 진행해보겠습니다. 경사 하강법을 수행하려면 가중치 $w_{5}$를 업데이트 하기 위해서 $\frac{∂E_{total}}{∂w_{5}}$를 계산해야 합니다.

$\frac{∂E_{total}}{∂w_{5}}$를 계산하기 위해 미분의 연쇄 법칙(Chain rule)에 따라서 이와 같이 풀어 쓸 수 있습니다. $$\frac{∂E_{total}}{∂w_{5}} = \frac{∂E_{total}}{∂o_{1}} \text{×} \frac{∂o_{1}}{∂z_{3}} \text{×} \frac{∂z_{3}}{∂w_{5}}$$ 위의 식에서 우변의 세 개의 각 항에 대해서 순서대로 계산해봅시다. 우선 첫번째 항에 대해서 계산해보겠습니다. 미분을 진행하기 전에 $E_{total}$의 값을 상기해봅시다. $E_{total}$은 앞서 순전파를 진행하고 계산했던 전체 오차값입니다. 식은 다음과 같습니다. $$E_{total}=\frac{1}{2}(target_{o1}-output_{o1})^{2} + \frac{1}{2}(target_{o2}-output_{o2})^{2}$$ 이에 $\frac{∂E_{total}}{∂o_{1}}$는 다음과 같습니다. $$\frac{∂E_{total}}{∂o_{1}}=2 \text{×} \frac{1}{2}(target_{o1}-output_{o1})^{2-1} \text{×} (-1) + 0$$ $$\frac{∂E_{total}}{∂o_{1}}=-(target_{o1}-output_{o1})=-(0.4-0.60944600)=0.20944600$$

이제 두번째 항을 주목해봅시다. $o_{1}$이라는 값은 시그모이드 함수의 출력값입니다. 그런데 시그모이드 함수의 미분은 $f(x) \text{×} (1-f(x))$입니다. 앞으로의 계산 과정에서도 계속해서 시그모이드 함수를 미분해야 하는 상황이 생기므로 기억해둡시다. 이에 따라서 두번째 항의 미분 결과는 다음과 같습니다.

(시그모이드 함수 미분 참고 링크 : https://en.wikipedia.org/wiki/Logistic_function#Derivative)

$$\frac{∂o_{1}}{∂z_{3}}=o_{1}\text{×}(1-o_{1})=0.60944600(1-0.60944600)=0.23802157$$ 마지막으로 세번째 항은 $h_{1}$의 값과 동일합니다. $$\frac{∂z_{3}}{∂w_{5}}=h_{1}=0.51998934$$ 우변의 모든 항을 계산하였습니다. 이제 이 값을 모두 곱해주면 됩니다.

$$\frac{∂E_{total}}{∂w_{5}} = 0.20944600 \text{×} 0.23802157 \text{×} 0.51998934 = 0.02592286$$ 이제 앞서 배웠던 경사 하강법을 통해 가중치를 업데이트 할 때가 왔습니다! 하이퍼파라미터에 해당되는 학습률(learning rate) $α$는 0.5라고 가정합니다.

$$w_{5}^{+}=w_{5}-α\frac{∂E_{total}}{∂w_{5}}=0.45- 0.5 \text{×} 0.02592286=0.43703857$$ 이와 같은 원리로 $w_{6}^{+},\ w_{7}^{+},\ w_{8}^{+}$을 계산할 수 있습니다.

$$\frac{∂E_{total}}{∂w_{6}} = \frac{∂E_{total}}{∂o_{1}} \text{×} \frac{∂o_{1}}{∂z_{3}} \text{×} \frac{∂z_{3}}{∂w_{6}} → w_{6}^{+}=0.38685205$$ $$\frac{∂E_{total}}{∂w_{7}} = \frac{∂E_{total}}{∂o_{2}} \text{×} \frac{∂o_{2}}{∂z_{4}} \text{×} \frac{∂z_{4}}{∂w_{7}} → w_{7}^{+}=0.69629578$$ $$\frac{∂E_{total}}{∂w_{8}} = \frac{∂E_{total}}{∂o_{2}} \text{×} \frac{∂o_{2}}{∂z_{4}} \text{×} \frac{∂z_{4}}{∂w_{8}} → w_{8}^{+}=0.59624247$$

4. 역전파 2단계(BackPropagation Step 2)

1단계를 완료하였다면 이제 입력층 방향으로 이동하며 다시 계산을 이어갑니다. 위의 그림에서 빨간색 화살표는 순전파의 정반대 방향인 역전파의 방향을 보여줍니다. 현재 인공 신경망은 은닉층이 1개밖에 없으므로 이번 단계가 마지막 단계입니다. 하지만 은닉층이 더 많은 경우라면 입력층 방향으로 한 단계씩 계속해서 계산해가야 합니다.

이번 단계에서 계산할 가중치는 $w_{1}, w_{2}, w_{3}, w_{4}$입니다. 원리 자체는 동일하므로 우선 $w_{1}$에 대해서 먼저 업데이트를 진행해보겠습니다. 경사 하강법을 수행하려면 가중치 $w_{1}$를 업데이트 하기 위해서 $\frac{∂E_{total}}{∂w_{1}}$를 계산해야 합니다.

$\frac{∂E_{total}}{∂w_{1}}$를 계산하기 위해 미분의 연쇄 법칙(Chain rule)에 따라서 이와 같이 풀어 쓸 수 있습니다. $$\frac{∂E_{total}}{∂w_{1}} = \frac{∂E_{total}}{∂h_{1}} \text{×} \frac{∂h_{1}}{∂z_{1}} \text{×} \frac{∂z_{1}}{∂w_{1}}$$ 위의 식에서 우변의 첫번째항인 $\frac{∂E_{total}}{∂h_{1}}$는 다음과 같이 다시 식을 풀어서 쓸 수 있습니다.

$$\frac{∂E_{total}}{∂h_{1}} = \frac{∂E_{o1}}{∂h_{1}} + \frac{∂E_{o2}}{∂h_{1}}$$ 위의 식의 우변의 두 항을 각각 구해봅시다. 우선 첫번째 항 $\frac{∂E_{o1}}{∂h_{1}}$에 대해서 항을 분해 및 계산해보겠습니다.

$$\frac{∂E_{o1}}{∂h_{1}} = \frac{∂E_{o1}}{∂z_{3}} \text{×} \frac{{∂z_{3}}}{∂h_{1}} = \frac{∂E_{o1}}{∂o_{1}} \text{×} \frac{∂o_{1}}{∂z_{3}} \text{×} \frac{{∂z_{3}}}{∂h_{1}}$$ $$= -(target_{o1}-output_{o1}) \text{×} o_{1}\text{×}(1-o_{1}) \text{×} w_{5}$$ $$= 0.20944600 \text{×} 0.23802157 \text{×} 0.45 = 0.02243370$$ 이와 같은 원리로 $\frac{∂E_{o2}}{∂h_{1}}$ 또한 구합니다. $$\frac{∂E_{o2}}{∂h_{1}} = \frac{∂E_{o2}}{∂z_{4}} \text{×} \frac{{∂z_{4}}}{∂h_{1}} = \frac{∂E_{o2}}{∂o_{2}} \text{×} \frac{∂o_{2}}{∂z_{4}} \text{×} \frac{{∂z_{4}}}{∂h_{1}} = 0.00997311$$

$$\frac{∂E_{total}}{∂h_{1}} = 0.02243370 + 0.00997311 = 0.03240681$$ 이제 $\frac{∂E_{total}}{∂w_{1}}$를 구하기 위해서 필요한 첫번째 항을 구했습니다. 나머지 두 항에 대해서 구해보도록 하겠습니다. $$\frac{∂h_{1}}{∂z_{1}} = h_{1}\text{×}(1-h_{1}) = 0.51998934(1-0.51998934)=0.24960043$$ $$\frac{∂z_{1}}{∂w_{1}} = x_{1} = 0.1$$ 즉, $\frac{∂E_{total}}{∂w_{1}}$는 다음과 같습니다. $$\frac{∂E_{total}}{∂w_{1}} = 0.03240681 \text{×} 0.24960043 \text{×} 0.1 = 0.00080888$$ 이제 앞서 배웠던 경사 하강법을 통해 가중치를 업데이트 할 수 있습니다. $$w_{1}^{+}=w_{1}-α\frac{∂E_{total}}{∂w_{1}}=0.3- 0.5 \text{×} 0.00080888=0.29959556$$ 이와 같은 원리로 $w_{2}^{+},\ w_{3}^{+},\ w_{4}^{+}$을 계산할 수 있습니다.

$$\frac{∂E_{total}}{∂w_{2}} = \frac{∂E_{total}}{∂h_{1}} \text{×} \frac{∂h_{1}}{∂z_{1}} \text{×} \frac{∂z_{1}}{∂w_{2}} → w_{2}^{+}=0.24919112$$ $$\frac{∂E_{total}}{∂w_{3}} = \frac{∂E_{total}}{∂h_{2}} \text{×} \frac{∂h_{2}}{∂z_{2}} \text{×} \frac{∂z_{2}}{∂w_{3}} → w_{3}^{+}=0.39964496$$ $$\frac{∂E_{total}}{∂w_{4}} = \frac{∂E_{total}}{∂h_{2}} \text{×} \frac{∂h_{2}}{∂z_{2}} \text{×} \frac{∂z_{2}}{∂w_{4}} → w_{4}^{+}=0.34928991$$

5. 결과 확인

업데이트 된 가중치에 대해서 다시 한 번 순전파를 진행하여 오차가 감소하였는지 확인해보겠습니다.

$$z_{1}=w_{1}x_{1} + w_{2}x_{2}=0.29959556 \text{×} 0.1 + 0.24919112 \text{×} 0.2= 0.07979778$$ $$z_{2}=w_{3}x_{1} + w_{4}x_{2}=0.39964496 \text{×} 0.1 + 0.34928991 \text{×} 0.2= 0.10982248$$ $$h_{1}=sigmoid(z_{1}) = 0.51993887$$ $$h_{2}=sigmoid(z_{2}) = 0.52742806$$ $$z_{3}=w_{5}h_{1}+w_{6}h_{2} = 0.43703857 \text{×} h_{1} + 0.38685205 \text{×} h_{2} = 0.43126996$$ $$z_{4}=w_{7}h_{1}+w_{8}h_{2} = 0.69629578 \text{×} h_{1} + 0.59624247 \text{×} h_{2} = 0.67650625$$ $$o_{1}=sigmoid(z_{3})=0.60617688$$ $$o_{2}=sigmoid(z_{4})=0.66295848$$ $$E_{o1}=\frac{1}{2}(target_{o1}-output_{o1})^{2}=0.02125445$$ $$E_{o2}=\frac{1}{2}(target_{o2}-output_{o2})^{2}=0.00198189$$ $$E_{total}=E_{o1}+E_{o2}=0.02323634$$ 기존의 전체 오차 $E_{total}$가 0.02397190였으므로 1번의 역전파로 오차가 감소한 것을 확인할 수 있습니다. 인공 신경망의 학습은 오차를 최소화하는 가중치를 찾는 목적으로 순전파와 역전파를 반복하는 것을 말합니다.

https://medium.com/@14prakash/back-propagation-is-very-simple-who-made-it-complicated-97b794c97e5c

https://www.youtube.com/watch?v=ZMgax46Rd3g

3.14. 순전파(forward propagation), 역전파(back propagation), 연산 그래프 — Dive into Deep Learning documentation

3.14. 순전파(forward propagation), 역전파(back propagation), 연산 그래프¶

앞에서 우리는 모델을 학습 시키는 방법으로 미니 배치 확률적 경사 강하법(stochastic gradient descent) 최적화 알고리즘을 사용했습니다. 이를 구현할 때, 우리는 모델의 순전파(forward propagation)을 계산하면서 입력에 대한 모델의 결과만을 계산했습니다. 그리고, 자동으로 생성된 backward 함수를 호출함으로 autograd 을 이용해서 gradient를 계산합니다. 역전파(back-propagation)을 이용하는 경우 자동으로 그래디언트(gradient)를 계산하는 함수를 이용함으로 딥러닝 학습 알고리즘 구현이 굉장히 간단해졌습니다. 이 절에서는 순전파(forward propagation)와 역전파(back propagation)를 수학적이고 연산적인 그래프를 사용해서 설명하겠습니다. 더 정확하게는 한개의 은닉층(hidden layer)를 갖는 다층 퍼셉트론(multilayer perceptron)에 \(\ell_2\) 놈 정규화(norm regularization)를 적용한 간단한 모델을 이용해서 순전파(forward propagation)와 역전파(back propagation)를 설명합니다. 이 절은 딥러닝을 수행할 때 어떤 일이 일어나고 있는지에 대해서 더 잘 이해할 수 있도록 해줄 것입니다.

3.14.1. 순전파(forward propagation)¶ 순전파(forward propagation)은 뉴럴 네트워크 모델의 입력층부터 출력층까지 순서대로 변수들을 계산하고 저장하는 것을 의미합니다. 지금부터 한개의 은닉층(hidden layer)을 갖는 딥 네트워크를 예로 들어 단계별로 어떻게 계산되는지 설명하겠습니다. 다소 지루할 수 있지만, backward 를 호출했을 때, 어떤 일이 일어나는지 논의할 때 도움이 될 것입니다. 간단하게 하기 위해서, 입력은 \(d\) 차원의 실수 공간 \(\mathbf{x}\in \mathbb{R}^d\) 으로 부터 선택되고, 편향(bias) 항목은 생략하겠습니다. 중간 변수는 다음과 같이 정의됩니다. \[\mathbf{z}= \mathbf{W}^{(1)} \mathbf{x}\] \(\mathbf{W}^{(1)} \in \mathbb{R}^{h \times d}\) 은 은닉층(hidden layer)의 가중치 파라미터입니다. 중간 변수 \(\mathbf{z}\in \mathbb{R}^h\) 를 활성화 함수(activation functino) \(\phi\) 에 입력해서 벡터 길이가 \(h\) 인 은닉층(hidden layer) 변수를 얻습니다. \[\mathbf{h}= \phi (\mathbf{z}).\] 은닉 변수 \(\mathbf{h}\) 도 중간 변수입니다. 출력층의 가중치 \(\mathbf{W}^{(2)} \in \mathbb{R}^{q \times h}\) 만을 사용한다고 가정하면, 벡터 길이가 \(q\) 인 출력층의 변수를 다음과 같이 계산할 수 있습니다. \[\mathbf{o}= \mathbf{W}^{(2)} \mathbf{h}.\] 손실 함수(loss function)를 \(l\) 이라고 하고, 샘플 레이블을 \(y\) 라고 가정하면, 하나의 데이터 샘플에 대한 손실(loss) 값을 다음과 같이 계산할 수 있습니다. \[L = l(\mathbf{o}, y).\] \(\ell_2\) 놈 정규화(norm regularization)의 정의에 따라서, 하이퍼파라미터(hyper-parameter) \(\lambda\) 가 주어졌을 때, 정규화 (regularization) 항목은 다음과 같습니다. \[s = \frac{\lambda}{2} \left(\|\mathbf{W}^{(1)}\|_F^2 + \|\mathbf{W}^{(2)}\|_F^2\right),\] 여기서 행렬의 Frobenius norm은 행렬을 벡터로 바꾼 후 계산하는 \(L_2\) 놈(norm)과 같습니다. 마지막으로, 한개의 데이터 샘플에 대한 모델의 정규화된 손실(regularized loss) 값을 계산합니다. \[J = L + s.\] \(J\) 를 주어진 데이터 샘플에 대한 목표 함수(objective function)라고 하며, 앞으로 이를 ’목표 함수(objective function)’라고 하겠습니다.

3.14.2. 순전파(forward propagation)의 연산 그래프¶ 연산 그래프를 도식화하면 연산에 포함된 연산자와 변수들 사이의 관계를 시각화 하는데 도움이 됩니다. 아래 그림은 위에서 정의한 간단한 네트워크의 그래프입니다. 왼쪽 아래는 입력이고, 오른쪽 위는 출력입니다. 데이터의 흐름을 표시하는 화살표의 방향이 오른쪽과 위로 향해 있습니다.

3.14.3. 역전파(back propagation)¶ 역전파(back propagation)는 뉴럴 네트워크의 파라미터들에 대한 그래디언트(gradient)를 계산하는 방법을 의미합니다. 일반적으로는 역전파(back propagation)은 뉴럴 네트워크의 각 층과 관련된 목적 함수(objective function)의 중간 변수들과 파라미터들의 그래디언트(gradient)를 출력층에서 입력층 순으로 계산하고 저장합니다. 이는 미적분의 ’체인룰(chain rule)’을 따르기 때문입니다. 임의의 모양을 갖는 입력과 출력 텐서(tensor) \(\mathsf{X}, \mathsf{Y}, \mathsf{Z}\) 들을 이용해서 함수 \(\mathsf{Y}=f(\mathsf{X})\) 와 \(\mathsf{Z}=g(\mathsf{Y}) = g \circ f(\mathsf{X})\) 를 정의했다고 가정하고, 체인룰(chain rule)을 사용하면, \(\mathsf{X}\) 에 대한 \(\mathsf{Z}\) 의 미분은 다음과 같이 정의됩니다. \[\frac{\partial \mathsf{Z}}{\partial \mathsf{X}} = \text{prod}\left(\frac{\partial \mathsf{Z}}{\partial \mathsf{Y}}, \frac{\partial \mathsf{Y}}{\partial \mathsf{X}}\right).\] 여기서 \(\text{prod}\) 연산은 전치(transposotion)나 입력 위치 변경과 같이 필요한 연산을 수항한 후 곱을 수행하는 것을 의미합니다. 벡터의 경우에는 이것은 직관적입니다. 단순히 행렬-행렬 곱셈이고, 고차원의 텐서의 경우에는 새로 대응하는 원소들 간에 연산을 수행합니다. \(\text{prod}\) 연산자는 이 모든 복잡한 개념을 감춰주는 역할을 합니다. 하나의 은닉층(hidden layer)를 갖는 간단한 네트워크의 파라매터는 \(\mathbf{W}^{(1)}\) 와 \(\mathbf{W}^{(2)}\) 이고, 역전파(back propagation)는 미분값 \(\partial J/\partial \mathbf{W}^{(1)}\) 와 \(\partial J/\partial \mathbf{W}^{(2)}\) 를 계산하는 것입니다. 이를 위해서 우리는 체인룰(chain rule)을 적용해서 각 중간 변수와 파라미터에 대한 그래디언트(gradient)를 계산합니다. 연산 그래프의 결과로부터 시작해서 파라미터들에 대한 그래디언트(gradient)를 계산해야하기 때문에, 순전파(forward propagation)와는 반대 방향으로 연산을 수행합니다. 첫번째 단계는 손실(loss) 항목 \(L\) 과 정규화(regularization) 항목 \(s\) 에 대해서 목적 함수(objective function) \(J=L+s\) 의 그래디언트(gradient)를 계산하는 것입니다. \[\frac{\partial J}{\partial L} = 1 \text{ and } \frac{\partial J}{\partial s} = 1\] 그 다음, 출력층 \(o\) 의 변수들에 대한 목적 함수(objective function)의 그래디언트(gradient)를 체인룰(chain rule)을 적용해서 구합니다. \[\frac{\partial J}{\partial \mathbf{o}} = \text{prod}\left(\frac{\partial J}{\partial L}, \frac{\partial L}{\partial \mathbf{o}}\right) = \frac{\partial L}{\partial \mathbf{o}} \in \mathbb{R}^q\] 이제 두 파라메터에 대해서 정규화(regularization) 항목의 그래디언트(gradient)를 계산합니다. \[\frac{\partial s}{\partial \mathbf{W}^{(1)}} = \lambda \mathbf{W}^{(1)} \text{ and } \frac{\partial s}{\partial \mathbf{W}^{(2)}} = \lambda \mathbf{W}^{(2)}\] 이제 우리는 출력층와 가장 가까운 모델 파라미터들에 대해서 목적 함수(objective function)의 그래디언트(gradient) \(\partial J/\partial \mathbf{W}^{(2)} \in \mathbb{R}^{q \times h}\) 를 계산할 수 있습니다. 체인룰(chain rule)을 적용하면 다음과 같이 계산됩니다. \[\frac{\partial J}{\partial \mathbf{W}^{(2)}} = \text{prod}\left(\frac{\partial J}{\partial \mathbf{o}}, \frac{\partial \mathbf{o}}{\partial \mathbf{W}^{(2)}}\right) + \text{prod}\left(\frac{\partial J}{\partial s}, \frac{\partial s}{\partial \mathbf{W}^{(2)}}\right) = \frac{\partial J}{\partial \mathbf{o}} \mathbf{h}^\top + \lambda \mathbf{W}^{(2)}\] \(\mathbf{W}^{(1)}\) 에 대한 그래디언트(gradient)를 계산하기 위해서, 출력층으로부터 은닉층까지 역전파(back propagation)를 계속 해야합니다. 은닉층(hidden layer) 변수에 대한 그래디언트(gradient) \(\partial J/\partial \mathbf{h}\in \mathbb{R}^h\) 는 다음과 같습니다. \[\frac{\partial J}{\partial \mathbf{h}} = \text{prod}\left(\frac{\partial J}{\partial \mathbf{o}}, \frac{\partial \mathbf{o}}{\partial \mathbf{h}}\right) = {\mathbf{W}^{(2)}}^\top \frac{\partial J}{\partial \mathbf{o}}.\] 활성화 함수(activation function) \(\phi\) 는 각 요소별로 적용되기 때문에, 중간 변수 \(\mathbf{z}\) 에 대한 그래디언트(gradient) \(\partial J/\partial \mathbf{z}\in \mathbb{R}^h\) 를 계산하기 위해서는 요소별 곱하기(element-wise multiplication) 연산자를 사용해야합니다. 우리는 이 연산을 \(\odot\) 로 표현하겠습니다. \[\frac{\partial J}{\partial \mathbf{z}} = \text{prod}\left(\frac{\partial J}{\partial \mathbf{h}}, \frac{\partial \mathbf{h}}{\partial \mathbf{z}}\right) = \frac{\partial J}{\partial \mathbf{h}} \odot \phi’\left(\mathbf{z}\right).\] 마지막으로, 입력층과 가장 가까운 모델 파라미터에 대한 그래디언트(gradient) \(\partial J/\partial \mathbf{W}^{(1)} \in \mathbb{R}^{h \times d}\) 를 체인룰(chain rule)을 적용해서 다음과 같이 계산합니다. \[\frac{\partial J}{\partial \mathbf{W}^{(1)}} = \text{prod}\left(\frac{\partial J}{\partial \mathbf{z}}, \frac{\partial \mathbf{z}}{\partial \mathbf{W}^{(1)}}\right) + \text{prod}\left(\frac{\partial J}{\partial s}, \frac{\partial s}{\partial \mathbf{W}^{(1)}}\right) = \frac{\partial J}{\partial \mathbf{z}} \mathbf{x}^\top + \lambda \mathbf{W}^{(1)}.\]

3.14.4. 모델 학습시키기¶ 네트워크를 학습시킬 때, 순전파(forward propagation)과 역전파(backward propagation)은 서로 의존하는 관계입니다. 특히 역전파(forward propagation)는 연관되는 관계를 따라서 그래프를 계산하고, 그 경로의 모든 변수를 계산합니다. 이것들은 연산이 반대 방향인 역전파(back propagation)에서 다시 사용됩니다. 그 결과 중에 하나로 역전파(back propagation)을 완료할 때까지 중간 값들을 모두 가지고 있어야하는 것이 있습니다. 이것이 역전파(back propagation)가 단순 예측을 수행할 때보다 훨씬 더 많은 메모리를 사용하는 이유들 중에 하나입니다. 즉, 체인룰(chain rule)을 적용하기 위해서 모든 중간 변수를 저장하고 있어야, 그래디언트(gradient)인 텐서(tensor)들을 계산할 수 있습니다. 메모리를 더 많이 사용하는 다른 이유는 모델을 학습 시킬 때 미니 배치 형태로 하기 때문에, 더 많은 중간 활성화(activation)들을 저장해야하는 것이 있습니다.

3.14.5. 요약¶ 순전파(forwards propagation)은 뉴럴 네트워크의 그래프를 계산하기 위해서 중간 변수들을 순서대로 계산하고 저장합니다. 즉, 입력층부터 시작해서 출력층까지 처리합니다.

역전파(back propagation)은 중간 변수와 파라미터에 대한 그래디언트(gradient)를 반대 방향으로 계산하고 저장합니다.

딥러닝 모델을 학습시킬 때, 순전파(forward propagation)과 역전파(back propagation)는 상호 의존적입니다.

학습은 상당히 많은 메모리와 저장 공간을 요구합니다.

3.14.6. 문제¶ 입력 \(\mathbf{x}\) 가 행렬이라고 가정하면, 그래디언트(gradient)의 차원이 어떻게 되나요? 이 절에서 설명한 모델의 은닉층(hidden layer)에 편향(bias)을 추가하고, 연산 그래프를 그려보세요

순전파(forward propagation)와 역전파(backward propagation) 공식을 유도해보세요. 이 절에 사용한 모델에 대해서 학습과 예측에 사용되는 메모리 양을 계산해보세요. 2차 미분을 계산을 해야한다고 가정합니다. 그래프 연산에 어떤 일이 생길까요? 좋은 아이디어인가요? 연산 그래프가 사용 중인 GPU에 비해서 너무 크다고 가정합니다. 한개 이상의 GPU로 나눌 수 있나요?

작은 미니배치로 학습을 할 경우 장점과 단점이 무엇인가요?

Jaejun Yoo’s Playground: Backpropagation 설명 예제와 함께 완전히 이해하기

“신경망은 구체적으로 어떻게 학습이 되는거지?” 뭔가 직관적인 설명으로는 신경망이 계산한 답과 정답 사이의 오차를 계산하고 그 오차를 줄이도록 피드백을 주어 학습을 시킨다고 하는데…. 1. 구체적으로 어떻게 그 변화 값들을 구하고 전파하는거지? 2. 그리고 그 방법이 “왜” 되는 것이지?

저 글을 한 문장으로 요약하자면 다음과 같습니다: “The problem with Backpropagation is that it is a leaky abstraction .”

그럼 이 부분은 Andrej Karpathy에게 넘기고, 여기서는 첫 번째 의문에 대해 나름대로 정리해보겠습니다.

물론 이미 같은 내용에 대한 답을 하기 위해 많은 자료들이 인터넷에 존재하고 여러 사람들이 다양한 관점으로 설명을 잘 해두었지만, 역시 무엇이든 제대로 이해하기 위해서는 스스로 시간을 투자해서 공부한 것을 나만의 언어와 논리로 정리하고 소화할 필요가 있는 것 같습니다.

이해를 위해 하는 것인데 너무 복잡한 문제로 시작하면 문제 자체보다 푸는 기술에만 집중할 수 있으니 가장 단순한 binary classification 문제에서 시작해보겠습니다.

Classification problems with two classes (binary classification)

Multiple, independent, binary classification 문제로의 확장은 아주 쉬운데, 각각의 target이

independent하므로 loglikelihood들을 더해주면 됩니다. 즉,

단일 unit

이었던 때

(

single target)

와 달리 마지막 layer에서 여러 unit을 갖습니다;

.

예시를 들자면 아마 이진 값으로 채워져있는 흑백 이미지 벡터를 생각하면 되지 않을까 싶네요. 그러면 각각의 픽셀에 대해 값이 있는지 없는지를 확률적으로 계산하는 문제가 되겠습니다.

여기서 multi-class 문제로 좀 더 확장하는 것은 생각보다 간단하고 심지어 수식을 유도해보면 binary 문제와 거의 다를 것이 없습니다. 하지만 정작 이 글의 주제인 역전파에서 벗어날 수 있기 때문에 이 얘기는 다음에 따로 정리해보겠습니다.

Backpropagation in 2-layer neural network

2-layer neural network로 풀기 위해

그림 1. 2-layer neural network

* Layer의 개수가 3개인데 왜 2-layer NN이라 하냐면 보통 neural network의 input layer는 세지 않기 때문에 그렇습니다.

** fully connected이기 때문에 각 층 사이에는 weight 값을 갖는 연결이 모든 조합에 대해 존재하고 편의상 그림에서는 생략해두었습니다.

*** Hidden layer와 output layer의 activation function은 sigmoid 함수로 통일합니다.

앞서 문제를 설정한대로 우리의 error function, E는 다음과 같습니다.

$$E = -\sum_{i=1}^{nout}(t_i log(x_i)+(1-t_i)log(1-x_i))$$

where, $x_i = \frac{1}{1+e^{-s_i}}$, $s_i = \sum_{j=1}x_jw_{ji}$.

수식이 무엇을 의미하는지 직관적으로 이해하려면 극단적인 예제를 넣어보는게 가장 빠르죠ㅎㅎ 실제 class가 1일 때($t_i=1$), 신경망이 계산한 답이 1일 확률이 0이라는($x_i = 0$) output 결과가 나왔다고 해보고 E 값을 계산해보면 쉽게 무한대가 나오는 것을 알 수 있습니다.

반대로 제대로 확률 값이 1 즉, target $t_i$의 class가 1일 때, 실제로 1이라고 계산할 확률이 100%라고($x_i=1$) 신경망이 결과를 내었다면, E 값은 0으로 최소값을 갖습니다.

즉, 우리의 목표는 E 값을 줄이는 것.

그럼 이제 이 오차 값을 줄이는 방향으로 네트워크를 업데이트 하면 되는데…

여기서 gradient descent라는 개념이 나옵니다.

gradient)를 계산하면 $x$로부터 단위($\Delta x$)만큼 움직였을 때, $f$ 값이 변화하는 양을 표현하는 벡터가 나오고, 이 벡터는 항상 가장 가파르게 $f$ 값이 증가하는 방향을 가르키기 때문 E로 두고 구배가 가르키는 반대방향(descent)으로 네트워크를 업데이트 해주면 됩니다. 어떤 함수 $f$의 임의의 점 $x$에서의 구배()를 계산하면 $x$로부터 단위($\Delta x$)만큼 움직였을 때, $f$ 값이 변화하는 양을 표현하는 벡터가 나오고,에 함수 $f$를로 두고 구배가 가르키는 반대방향()으로 네트워크를 업데이트 해주면 됩니다.

Data인 input을 바꾸는 것이 목적이 아니기 때문에 네트워크의 output 값에 영향을 주는 변수 중 우리가 수정할 것은 layer 간의 weight, $w$들입니다. 따라서 우리가 해야하는 것은 각 layer의 weight에 대한 E 함수의 gradient를 계산하고 이 변화량을 원래 w에 반대 방향 (negartive, -1)으로 더해주는 것이죠.

신경망이 학습하는 것을 순서대로 나열해보면, Input layer로부터 각 layer를 지나치며 weight들을 곱하고, activation function을 지난 다음, 마지막 output layer에서 오차 값을 계산한 이후(feed forward), 업데이트를 위해 순차적으로 거꾸로(back) 돌아가야(propagation)합니다.

따라서 돌아갈 때 순서대로 가장 바깥 쪽 output과 hidden layer 사이의 weight부터 바꿔보겠습니다. $i$번째 output인 $x_i$에 대한 오차값에 대해 $w_{ji}$가 바뀌어야하는 정도를 계산해려면 다음과 같은 수식이 필요합니다:

$$\frac{\partial E}{\partial w_{ji}} = \frac{\partial E}{\partial x_i} \frac{\partial x_i}{\partial s_i} \frac{\partial s_i}{\partial w_{ji}}$$

$\frac{\partial E}{\partial x_i} = \frac{-t_i}{x_i}+\frac{1-t_i}{1-x_i} = \frac{x_i-t_i}{x_i(1-x_i)}$ $\frac{\partial x_i}{\partial s_i} = x_i(1-x_i)$ $\frac{\partial s_i}{\partial w_{ji}} = x_j$

$$\therefore \frac{\partial E}{\partial w_{ji}} = (x_i-t_i)x_j$$

(여기서 순서를 잠시 짚고 넘어갈 필요가 있습니다. 1번과 2번을 곱하면 $\frac{\partial E}{\partial s_i}$ 가 나옵니다. 그 후 3번을 차례로 계산하여 곱하면 결과적으로 $\frac{\partial E}{\partial w_{ji}} = (x_i-t_i)x_j$ 가 됩니다. 먼저 $\frac{\partial E}{\partial s_i}$를 계산했다는 것을 기억해주시면 됩니다.)

같은 논리로 그 다음 hidden과 input layer 간의 weight, $w_{kj}$에 대해 변화량을 계산하면,

$$\frac{\partial E}{\partial w_{kj}} = \frac{\partial E}{\partial s_j} \frac{\partial s_j}{\partial w_{kj}}$$

$\frac{\partial E}{\partial s_j} = \sum_{i=1}^{nout} \frac{\partial E}{\partial s_i}\frac{\partial s_i}{\partial x_j}\frac{\partial x_j}{\partial s_j} = \sum_{i=1}^{nout}(x_i-t_i)(w_{ji})(x_j(1-x_j))$ $\frac{\partial s_j}{\partial w_{kj}} = x_k ~(\because s_j=\sum_{k=1}x_kw_{kj})$

여기서 $x_k$는 feed forward할 때도 $i=\{1,\cdots, nout\}$까지의 모든 값에 영향을 주기 때문에 backprop 때도 $\sum_{i=1}^{nout}$을 고려하여 계산해야합니다. 위 그림에서 빨간 화살표들을 보면 되겠습니다.

여기서도 $\frac{\partial E}{\partial s_j}$를 구한 것을 보실 수 있습니다. 앞에서도 강조했었는데 이걸 기억하면 위에서 유도한 식들을 general multiplayer network로 확장하는 것도 매우 쉽습니다. 각 layer의 $\frac{\partial E}{\partial w_{ij}}$를 구하고 싶다면, 항상 $\frac{\partial E}{\partial s_j}$를 계산하고, $\frac{\partial s_j}{\partial w_{kj}} = x_k$를 곱해주는 식이 되면 됩니다.

참고문헌:

(이 문헌을 참고해서 공부하긴 했지만 보시다보면 수식 전개에서 약간의 오타가 있으니 감안하고 보셔야 합니다.) 참고문헌: https://www.ics.uci.edu/~pjsadows/notes.pdf

역전파(Backpropagation) 설명

# 역전파(Backpropagation)에 대해서 쉽게 설명한다면?

Gradient Descent를 이용해 가중치 갱신을 해야하고, GD를 하기 위해선 loss function의 gradient가 필요한데, 그 loss function의 gradient를 Backpropagation으로 전달받는다.

“즉, 가중치 갱신을 위해서 필요한 loss function의 gradient를 chain rule을 이용해 앞으로 전달해주는 알고리즘이 Backpropagation!”

“나의 목표 target 값과 실제 모델이 예측한 output값이 얼마나 차이나는지 구한 후, 오차값을 다시 뒤로 전파해가며 변수들을 갱신하는 알고리즘”

잘 설명된 블로그

: https://bskyvision.com/718

[딥러닝] 뉴럴 네트워크 Part. 4

쉬운 설명을 위해 예제 신경망을 구성해보았습니다. Input 값은 1개이고 Output 값은 2개, Hidden Layer 수는 2개인 작은 신경망입니다. 각 노드의 Activation Function 은 Sigmoid Function 을 사용했으며 Bias 는 제외하였습니다.

초록색 값들은 처음 주어진 값들이고 파란색 값들은 초기값을 바탕으로 계산한 값입니다. 처음 x_1 의 값은 0.5 이고 w_10 은 0.15 이기 때문에 둘을 곱한 0.075가 계산값으로 나온 것을 알 수 있습니다.

[딥러닝기초] 역전파 알고리즘(Back Propagation)1_ Delta Rule

이 글은 연세대학교 정보대학원 기본머신러닝 과목 수강하면서 공부한 내용을 바탕으로 작성한 글입니다.

역전파 알고리즘(Back Propagation)

– 모델의 출력값(output)과 기대값(target)을 비교하여 차이(오차/error)를 줄여나가는 방향으로 가중치를 업데이트하는 방법

– 출력층(ouput layer)에서 입력층(input layer) 방향으로 오차(error)를 역으로 전파하면서 가중치를 업데이트 하기 때문에 역전파(Back Propagation) 알고리즘이라고 합니다.

– 역전파 알고리즘에 대한 설명은 Delta Rule을 기본으로 시작하여 이를 일반화하여 확장한 역전파알고리즘을 설명하는 순으로 진행하겠습니다.

1. Delta Rule

1) Delta란?

: 정답(target)과 출력값(output)간의 차이, 즉 오차(error)를 delta라고 한다.

(= difference between desired and actual output)

2) Delta Rule이란?

: 단층신경망(Single Layer Perceptron)에서 뉴런의 연결강도(가중치, weight)를 갱신하는데 쓰이는 방법으로,

모든 입력값으로부터 얻어지는 출력과 정답간 오차의 제곱합을 최소화하도록 연결강도(가중치)를 조정하는 방법.

: 오차를 비례하여 가중치를 조절한다는 점에서 ‘실수(오차)로부터 배운다(learning from mistakes)’고 한다.

: “Perceptron learning rule”이라고 한다.

<단층신경망과 Delta Rule 그림 설명>

Fei-Fei Li & Justin Johnson & Serena Yeung 단층신경망(Simple Layer Perceptron) [Delta Rule] 가중치 변화량에 대한 식

-> 가중치를 업데이트 하는 양은 오차(delta)와 입력값, η(에타, Learning rate)에 의해서 정해진다

<제한적인 'Delta Rule'의 기본 가정>

① 네트워크가 입력과 출력만으로 구성된 단층신경망(Single Layer Perceptron)이다.

② 활성화함수(Activation funciton)가 선형(linear)이거나 없다.

-> 오차역전파 알고리즘의 기초가되는 Delta Rule은 위와 같이 아주 제한적인 조건에서만 성립합니다.

하지만 일반적인 네트워크는

i) 입력층, 출력층 외에 많은 은닉층(Hidden Layer)이 존재하고

ii) 활성화함수도 선형적이지 않으며

iii) 손실함수(Loss function)는 아래 그림과 같이 Convex 하지 않기 때문에

일반적인 네트워크의 가중치를 업데이트하기위해서는 Delta Rule을 일반화 해야합니다.

Backpropagation 설명 (역전파)

이 페이지는 다음 강의 영상을 정리한 것이다.

www.youtube.com/watch?v=dB-u77Y5a6A&list=PL5-TkQAfAZFbzxjBHtzdVCWE0Zbhomg7r&index=6

살펴볼 주제

1. computational graph로 backpropagation을 계산했을 때 발견되는 pattern의 의미와 그 쓰임

2. input과 output이 scalar가 아닌 vector 또는 tensor일 때 backpropagation이 진행되는 구체적인 과정

computational graph를 통해 backpropagation 을 계산할 때

미분 값이 역전파 되어가는 데 있어 몇 가지 pattern 을 발견할 수 있다

1. add gate : gradient distributor

node 연산이 더하기일 경우 ( 덧셈 연산을 수행하는 함수를 미분할 경우) 미분 값(local gradient)은 1이 된다

이때는 downstream gradient가 upstream gradient x 1 이 되므로

f(x, y) = x + y,

df(x, y)/dx = 1 , df(x, y)/dy = 1

downstream gradient는 upstream gradient와 같은 값이 된다. (즉 gradient가 그대로 propagate 된다)

그래서 add node를 단순한 gradient distributor로 간주할 수 있다.

2. copy gate : gradient adder

input이 하나고 output은 두 개를 갖는 노드인 경우

각각의 upstream gradient 단순히 더해주면 된다.

이런 형태의 노드는 weight regularization 에서 볼 수 있다.

* add gate의 input, output 값을 forward pass 관점에서 보면 copy gated의 역전파와 같고

copy gate의 input, output값을 forward pass 관점에서 보면 add gate의 역전파와 같다.

3. mul gate : swap multiplier

곱하기 노드의 경우, downstream gradient는 upstream gradient 에 input값을 서로 바꾸어 곱한 값과 같다.

f(x, y) = xy,

df(x, y)/dx = y , df(x, y)/dy = x

왜냐하면 각 input의 local gradient는 상대의 input값과 같기 때문이다.

Q1 : 강의에선 mul gate 는 forward pass 일 때와 backward pass 일 때 모두 곱하기 연산이 일어나서

mul gate를 많이 갖고 있는 모델일 때, 문제가 될 수 있는 모델이 있을 수 있다고 하는 데,

어떤 모델이, 왜 문제가 되는걸까?

4. max gate : gradient router

input 값 중 더 큰 값을 취하는 노드의 경우, cf) Relu함수

backpropatation을 하면 input이 더 컸던 쪽은 upstream gradient를 그대로 받게 되고

input이 더 작았던 쪽은 gradient가 0이 된다.

(max함수의 정의에 따라 더 큰 값만 의미가 있고 작은 값은 아무 역할도 하지 못하므로)

Q2 : 강의에선 max gate를 많이 갖고 있는 모델은, backpropagation을 할 때 gradient가 0이 되는 경우가 많아지므로

good gradient flow 를 얻기가 어려워지는 문제가 생겨 max gate를 선호하지는 않게 된다고 한다.

분명히 이해가 되지는 않는데, 이것이 leaky Relu와 관련이 있는걸까?

computational graph로 backpropagation을 실행한 과정을 code로 구현하는 두 가지 방식

1. ‘flat’ gradient code

위의 코드들은 파이썬 언어로 작성한 것인데,

backward pass 코드들이 forward pass 코드의 순서를 거꾸로 되짚어 가며 만든 형태를 띤다.

backpropagation을 코딩하는 건

위에서 살펴본 backpropagation gate pattern 들을

forward pass의 역방향으로 순서에 맞춰 쓰기만 하면 되는 걸 알 수 있다.

그래서 이런 방식의 backpropagation coding을 강의에선 ‘flat’ 한 backpropagation code 라고 부르고

이런 방식의 코딩에 먼저 충분히 익숙해 질 것을 권유한다. (기초를 다지는 의미에서)

그런데 flat gradient coding은

모델을 바꾼다거나 활성화 함수, loss function 또는 rerularization term을 다른 걸 쓰면

바뀐 모델의 형태나 식에 맞춰 코드를 전부 다시 써야 한다.

2. Modular API

좀더 모듈러한 방식으로 코딩을 한다면 아래와 같이 할 수 있다.

위 코드는input 과 output이 scalar 라고 가정한 mul node(gate)를 파이토치로 구현한 것이다.

이 코드가 flat version 보다 좀 더 modular 한 까닭은

node 단위로 코딩을 한 점,

클래스를 써서 forward pass 부분과 backward pass부분을 메소드로 처리한 점,

forward 함수의 코드블럭을 보면 입력으로 받은 x, y를 local gradient로 쓰기 위해 미리 저장해 두는 코드를 쓴 점 등

flat version에서 모든걸 하나의 함수에 넣은 것과 비교해

훨씬 수정이 용이하고 갖다 붙여 쓰기 편하다는 데 있다.

* pytorch github repo에 들어가보면 위와 같은 모듈 코드들이 많이 있으니 참고.

github.com/pytorch/pytorch/tree/master/aten/src

지금까진 input과 output이 scalar일 때의 backpropagation 과정을 살펴보았다.

그럼 이제 실전에서와 같이

input, output이 vector, tensor 형태일 때의 backpropagation은 어떻게 실행되는지 살펴보자.

input은 n차원 vector이고 output은 scalar일 때,

downstream gradient는 input과 같은 n차원 vector 형태가 될 것이다.

좀 더 일반화 해서

input이 n차원 vector, output이 m차원 vector 라면

downstream gradient는 n by m 형태의 matrix가 될 것이다. (이러한 행렬을 Jacobian 자코비언 행렬이라고 부른다)

Q3. 이게 무슨 뜻일까?

*Jacobian matrix 참고

angeloyeo.github.io/2020/07/24/Jacobian.html

computational graph를 통해 backpropagation을 이해하는 방법의 장점은

single node 단위에서 backpropagation이 어떻게 진행되는지 따져보기만 하면 된다는 데 있으므로

이제 input과 output이 모두 벡터인 경우는 어떻게 되는지 아래 그림을 통해 살펴보자.

여기서 input은 각각 x, y 두 벡터이고 (Dx, Dy로 표기) output은 역시 vector인 z이다. (Dz로 표기)

*여기서 z가 vecotor라고 해서, loss가 vector 형태일 거라고 생각해선 안된다.

*최종 loss값은 항상 scalar다.

따라서 upstream gradient인 dL/dz의 의미는

이 node의 output인 z의 각 원소들이 아주 미세하게 변할 때, scalar값인 loss가 어떻게 변하는 지를 의미한다.

*좀 더 수학적으로 말하면 dL/dz 벡터는 loss값을 z로 편미분한 벡터다.

dz/dx 의 의미는 이 node에서 함수 f에 대해 입력 벡터 x의 각 원소들이 미세하게 변할 때

출력 벡터 z의 각 원소들이 얼마나 변하는 지를 편미분한 local gradient이다.

그런데 함수 f는 여러 개의 변수 (여기서는 x, y)를 가진 다변수 벡터함수(vector valued function) 이다.

* 여기서 벡터함수는 벡터를 입력 받아 벡터를 출력하는 함수를 의미하는 함수로 쓰였다

여기서 잠시 vector valued function와 자코비언 행렬이 backpropagation에서 무슨 의미를 지니는 것인지 살펴보자

Q3의 답 : 예를 들면 위 그림에서 함수f는 변수 두 개(x, y)를 입력으로 받아 출력을 3개로 내놓는 다변수 벡터함수다.

이 함수f의 도함수f’를 구하려면 각 함수 f1, f2, f3에 대해 편미분을 해야 한다.

변수가 x, y두 개 이므로 두 변수에 x, x + y, xy를 각각 편미분을 하면

오른쪽과 그림과 같이 2 by 3 행렬이 된다. 이 행렬이 함수 f의 자코비언 행렬이다.

즉 자코비언 행렬이란 편미분할 변수가 많고, 그 변수들로 이루어진 함수도 많을 때

각 변수에 대한 각 함수의 편미분 값을 원소로 갖는 행렬이다.

다시 말해 n개의 변수를 가진 함수가 m개 있다면 그 함수의 자코비언 행렬은 n by m 형태를 띤다.

다시 위 노드로 돌아가면,

따라서 이 local gradient dz/dx는

x가 n차원 벡터, z가 m차원 벡터인 경우 n by m 형태의 jacobian matrix 형태가 된다.

정리하면, 이 node에서 local gradients는 jacobian matrix 의 각 원소가 된다.

결과적으로 우리는 x, y, z의 값을 알기 때문에

x와 y의 local gradient 값을 바로 계산할 수 있고

dz/dx , dz/dy

upstream gradient인 dL/dz가 주어졌으므로 chain rule을 써서

downstream gradient인 dL/dx와 dL/dy를 구할 수 있다.

dL/dx = dz/dx * dL/dz

dL/dy = dz/dy * dL/dz

이 때 dz/dx, dz/dy는 자코비언 행렬이고, dL/dz는 벡터이므로

최종적으로 우리가 구하고자 하는 dL/dx, dL/dy는 행렬-벡터 곱 (matrix vector product) 연산이 된다.

중요한 것은 이 matrix-vector multiplication 의 결과가 입력 벡터 x, y 의 shape과 똑같다는 것이다.

이제 구체적인 사례를 통해 vector를 edge로 갖는 node의 backpropagation 과정을 살펴보자.

예를 들어 우리의 모델에 아래와 같은 노드가 있다고 하자.

여기서 함수f는 vector valued Relu function이라고 볼 수 있다.

(입력 벡터의 원소 중 0보다 큰 값만 그대로 출력 벡터의 원소가 되게 하고, 0보다 작은 원소는 0이 되게 하는)

이제 upstream gradient가 위와 같이 주어졌을 때

(Relu function의 output vector 값들이 아주 조금 변했을 때 최종 loss 값이 얼마나 변하는 지의 비율)

맨 처음 살펴본 backpropagation pattern 들 중 하나인 max gate에 따라

dy/dx 는 위와 같은 형태의 행렬이 된다

(여기서 jacobian matrix dy/dx의 의미는 input값의 변화에 따라 output값이 변하는 정도를 나타내는 비율을 의미한다)

여기에 upstream gradient dL/dy 를 곱해주면, downstream gradient dL/dx를 얻을 수 있다.

활성화 함수로 Relu function을 쓴 경우, 그 노드의 backpropagation을 위한 Jacobian matrix는

그림과 같이 일종의 대각선 행렬과 같은 형태가 되는데,

대각선을 제외한 모든 원소들은 0이 되는 ‘sparse’한 특징을 보인다.

input vector의 차원수가 n이라면 , Jacobian matrix의 shape는 n제곱만큼 늘어난다.

일반적으로 neural network에서 처음에 입력받는 feature값은 최소 수백개이므로

자코비언 행렬도 엄청나게 커지지만 무엇보다 그 행렬의 원소들 중 거의 대부분이 0이라는 게

컴퓨터 연산자원 활용에 있어 아주 큰 비효율을 낳게 된다.

그래서 자코비언 행렬을 있는 그대로(explicitly form) 쓰지 않고

implicit하게 사용하는데 그 방법은

그냥 upstream gradient vector를 max function(Relu function?)에 넣어버리는 것이다.

즉 Relu함수를 쓴 node의 backpropagation은 foward pass때와 마찬가지로 max function을 gate로 쓰는 것이다.

여기서 중요한 것은 upstream gradient 값 중에서 0보다 큰 값을 선별하는 기준으로 x input vector를 쓴다는 점이다

이제 마지막으로 matrix 또는 tensor를 를 edge로 갖는 node의 backpropagation을 살펴보자.

tensor란 vector와 matrix를 일반화한 것을 뜻한다.

(예컨대 한 image의 경우 가로, 세로 pixel의 개수와 RGB 3 channel 총 3개의 차원을 가지므로 3차원 텐서라 할 수 있다)

위의 그림의 경우 입력값 x, y와 출력값 z는 matrix 형태다.

upstream gradient는 y와 r같은 형태의 행렬로 주어진다.

여기서 자코비언 행렬은 [(Dx * Mx) * (Dz * Mz)] 처럼 very high rank tensor가 된다.

dL / dx를 또는 dL/dw를 어떻게 구하면 좋을까?

원소별로 접근해본다.

dy(1,1) / dx(1,1) 를 구하기 위해선

x(1,1)w(1,1) + x(1,2)w(2,1) + x(1,3)w(3.1) 을 x(1,1)에 대해 편미분 해주면 된다.

그 값은 w(1,1)과 같다.

이러한 방법으로 dy/d(x1,1)을 모두 구하면

y 는 2 x 4 행렬이므로

1행은 w(1,:)과 같고 2행은 모두 0이 되는 2 x 4 행렬을 얻을 수 있다.

*2행이 모두 0이 되는 이유는 x(1,1)에 대해서 편미분을 하는 중이므로

2행의 원소값에는 x(1,1)이 들어 있지 않아 모두 상수처리 되기 때문이다.

이제 chain rule을 적용해 dy/dx(1,1) X (dL/dy)를 하면

dL/dx(1,1)은 W(1,:) 과 dL/dy(1,:)를 element-wise product해 모두 더한 값과 같게 된다.

처음에 여기서 dy/dx(1,1)과 (dL/dy)은 똑같이 2 x 4 행렬인데 어떻게 곱셈을 할 수 있느냐는 함정에 빠졌는데

dy/dx(1,1)은 위 [(2 x 3) x (2 x 4)] 자코비언 행렬에서 x(1,1)에 해당하는 행렬을 떼어낸 것이므로

2차원이 아니라 3차원적인 관점에서 봤을 때, 평면에 놓인 좌우 두 행렬의 곱이 아닌

3차원 공간에 놓인 앞뒤 행렬의 같은 위치에 놓인 원소별 곱으로 보면 이해가 됐다.

아마 이것이 matrix backpropagation을 할 때 자코비언 행렬이 very high rank tensor로 불리는 까닭인 것 같다.

만약 내 해석이 맞다면, 2차원 matrix 가 아니라 3차원 배열, 다차원 배열로서의 tensor가 input으로 주어질 때

자코비언 행렬은 도저히 상상이 안된다.

그렇다면 이러한 복잡한 연산과정이 Q1에 대한 한 가지 답변이 될 수 있을까?

이 연산을 dL/dx(i,j)에 일반화하면 downstream gradient는 아래와 같은 form으로 구할 수 있다.

x에 대한 downstream gradient는 upstream gradient 곱하기 w의 전치행렬이 되고

w에 대한 downstream gradient는 x의 전치행렬 곱하기 upstream gradient가 된다.

행렬곱 연산을 위해 reshape해준 걸 차치하면

곱하기 노드를 backpropagation 할 때 보게 되는 mul gate와 유사한 pattern을 가진다.

키워드에 대한 정보 back propagation 설명

다음은 Bing에서 back propagation 설명 주제에 대한 검색 결과입니다. 필요한 경우 더 읽을 수 있습니다.

이 기사는 인터넷의 다양한 출처에서 편집되었습니다. 이 기사가 유용했기를 바랍니다. 이 기사가 유용하다고 생각되면 공유하십시오. 매우 감사합니다!

사람들이 주제에 대해 자주 검색하는 키워드 오차역전파 (Backprogation)의 개념을 쉽게 이해해 봅시다

  • 텐서플로우
  • 딥러닝
  • tensorflow
  • 텐서플로우 자격증
  • tensorflow certificate
  • 텐서플로우 강좌
  • 텐서플로우 2.0
  • 텐서플로우 강의
  • 딥러닝 강의
  • 딥러닝 입문
  • 비전공자 딥러닝
  • 비전공자 머신러닝
  • 머신러닝
  • 데이터분석
  • 비전공자 데이터 분석
  • 패스트캠퍼스
  • 런어데이
  • 딥러닝 수학
  • deep learning
  • 딥러닝 교육
  • 머신러닝 입문
  • 파이썬 데이터분석
  • 파이썬 강의
  • 파이썬 코딩
  • 텐서플로우 튜토리얼
  • 딥러닝 튜토리얼
  • 구글 텐서플로우
  • 딥러닝 자격증
  • 머신러닝 자격증
  • 텐서플로우 자격
  • 딥러닝 소개
  • 딥러닝 취업
  • 데이터분석 취업
  • 데이터분석 이직
  • 패스트캠퍼스 딥러닝
  • 패스트캠퍼스 데이터분석
  • python 강의
  • python 강좌
  • 파이썬 강좌
  • 딥러닝 강좌
  • 머신러닝 강좌
  • 머신러닝 수학
  • 캐글
  • kaggle
  • 자연어처리
  • 시계열분석
  • 테디노트
  • 인공지능강의
  • 데이터 취업
  • 오늘코드
  • 생활코딩

오차역전파 #(Backprogation)의 #개념을 #쉽게 #이해해 #봅시다


YouTube에서 back propagation 설명 주제의 다른 동영상 보기

주제에 대한 기사를 시청해 주셔서 감사합니다 오차역전파 (Backprogation)의 개념을 쉽게 이해해 봅시다 | back propagation 설명, 이 기사가 유용하다고 생각되면 공유하십시오, 매우 감사합니다.

See also  어둠 인도자 야스오 | 어둠의 인도자 야스오 (Nightbringer Yasuo Skin Spotlight) 상위 200개 베스트 답변

Leave a Comment