Analytic gradient

지난 강의에서 Numerical gradient와 Analystic gradient에 대해서 소개했었다. Numerical gradient는 유한차분 추정을 통해 쉽게 구할 수 있었지만, 느리고 정확하지 않다는 단점이 있었다. 본 강의에서는, 유한차분 추정보다는 어렵지만, 훨씬 더 정확하고 빠르게 gradient를 구할 수 있는 Analytic gradient에 대해서 소개하고자 한다. 이를 위해 먼저 Computation graph를 소개한다.

1. Computational graph

Computational graph는 매우 복잡한 형태의 함수를 node와 edge로 나타낸 그래프이며, 복잡한 함수를 이용한 작업 및 계산시 아주 유용하게 사용된다. 위 예시는 Linear Classifier가 Loss를 구하는 과정을 Computational graph로 나타낸 것이며, hinge loss와 regularization term의 합계가 최종 Loss로 구해지는 과정이 표현되어 있다.

Computational graph의 최대 장점은, 일단 우리가 Computational graph로 함수를 표현하면 backpropagation이라고 불리는 테크닉을 사용할 수 있다는 것이다. backpropagation이란, 재귀적으로 chain rule을 사용하여 computatinal graph의 모든 변수에 대해 경사를 계산하는 기법인데, 자세한 내용은 아래에서 좀 더 구체적인 예시를 가지고 설명해보겠다.



2. backpropagation at scalar

2-1) Example 1

\[f(x,y,z) = (x+y) \times z\]

다음은 function $f(x, y, z) = (x+y) \times z$에 대한 backpropagation 예제이다. input으로는 x=-2, y=5, z=-4가 주어져있다.

여기서 우리의 목표는, f에 대한 x, y, z의 gradient를 얻어 W를 조정하는 것이다. 따라서, 우리가 최종적으로 얻고자 하는 것은, function f의 출력(Loss와 관련)에 대한 x, y, z의 Gradient값이다. 설명이 조금 rough하지만, 뒤에 다른 예제가 또 나오기 때문에, 일단은 이해가 되지 않더라도 이런게 있구나 하며 흐름만 파악하면 된다.

2-1-1) 함수 f를 Computational graph로 표현하기

우선, gradient를 구하고자 하는 함수 f를 Computational graph로 표현해준다. 차근차근 그려나가면 어렵지 않게 그릴 수 있다.

2-1-2) Forward propagation

input을 계속 뒤로(오른쪽) 전달하여 각 노드의 값을 계산한다. 이를 forward pass라고 한다.**

2-1-3) Local Gradient

각 노드의 local gradient를 미리 구한다. 여기서 local gradient란, 해당 노드의 편미분값이라고 생각하면 된다.

\[q = x+y \quad\quad \frac{\partial q}{\partial x} = 1, \frac{\partial q}{\partial y} = 1\\\] \[f = qz \quad\quad \frac{\partial f}{\partial q} = z, \frac{\partial f}{\partial z} = q\\\] \[Want : \frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}, \frac{\partial f}{\partial z}\]

2-1-4) Back propagation

제일 뒷 단부터 앞 단으로 gradient를 전파시킨다. 이를 backward pass라고 한다.

우선, 바로 미분이 가능한 노드부터 미분해준다.

\[-> \; \frac{\partial f}{\partial f} = 1\\\] \[-> \; \frac{\partial f}{\partial z} = q = 3\\\] \[-> \; \frac{\partial f}{\partial q} = z = -4\\\]
f와 직접적으로 연결되어있지 않은 노드들의 gradient는
간단한 수학적 trick을 사용하여 구해줄 수 있는데,
이 trick을 chain rule이라고 한다.
\[-> \; \frac{\partial f}{\partial x}\] \[= \frac{\partial f}{\partial q} \; \frac{\partial q}{\partial x}\\(upstream \; gradient \times local \; gradient)\] \[= -4 \times 1 = -4\\\] \[-> \; \frac{\partial f}{\partial y}\] \[= \frac{\partial f}{\partial q} \; \frac{\partial q}{\partial y}\] \[= -4 \times 1 = -4\\\]

위처럼, chain rule을 사용하면, 어려운 계산 없이 단순한 미분만으로 복잡한 함수에 대한 편미분 gradient 값을 차근차근 구해나갈 수 있다. 지금 이 예시의 함수 f는, 식이 간단해서 바로 편미분할 수 있지만, 함수가 복잡해질 경우 위 방법을 사용하는 것이 유용하다.

2-1-5) 도식화

다음은 위 예제를 간단하게 도식화한 그림이다.

우선, 우리는 x와 y(input)을 f에 넣어 z(output)을 얻어냈다. 이렇게 input을 받아 출력된 output을 바탕으로 Loss를 계산하는 과정을 forward pass라고 한다. 이후, z에 대한 x와 y의 gradient값을 미분을 통해 얻을 수 있는데, 이를 local gradient라고 한다. 여기서 우리가 알고 싶은건, z 값을 통해 계산한 Loss에 대한 x, y의 gradient 값이다. 이 때, 앞에서 설명한 chain rule을 이용하면 쉽게 계산할 수 있는데, Loss를 z에 대해 먼저 미분하고, $\frac{\partial L}{\partial z} \times \frac{\partial z}{\partial x \; or \; \partial y}$를 통해 Loss에 대한 x, y의 gradient 값을 계산하면 된다. 이처럼, forward pass가 끝난 후, 역으로 미분해가며 gradient값을 구하는 과정을 backward pass(backpropagation)라고 한다.

2-1-6) 정리

위 예제를 통해 얻을 수 있는 정보는 다음과 같다. 우선, 각 노드들은 자신과 인접한 노드에 대한 정보만 알 수 있다. 이러한 한계로 인해 고안해낸 trick이 바로 chain rule이며, 우리는 특정 노드의 gradient가 upstream gradient * local gradient임을 확인하였다. 따라서 우리는, forward propagation을 통해 구한 Loss를 다시 back propagation을 통해 앞단으로 전파하여 f의 파라미터에 대한 gradient를 얻을 수 있게 되었다.


2-2) Example 2

다음의 함수 $f(w,x)$에 대하여 파라미터들의 gradient를 구해보자.

\[f(w,x) = \frac{1}{1+e^-{w_0x_0+w_1x_1+w_2}}\]

2-1-1) forward propagation

2-1-2) local gradient 계산

\[f(x) = \frac{1}{x} \quad -> \quad \frac{\partial f}{\partial x} = -\frac{1}{x^2}\\\] \[f_c(x) = x + c \quad -> \quad \frac{\partial f}{\partial x} = 1\\\] \[f(x) = e^x \quad -> \quad \frac{\partial f}{\partial x} = e^x\\\] \[f_a(x) = ax \quad -> \quad \frac{\partial f}{\partial x} = a\\\]

2-1-3) backward propagation

  • step 1.

    $\frac{\partial f}{\partial x}=1$이므로 마지막 노드의 출력에 대한 gradient는 1이다.

  • step 2.

    • upstream gradient : 1.00
    • local gradient : $-\frac{1}{x^2}=\frac{-1}{1.37^2}=-0.53$
    • gradient : (-0.53) $\times$ 1 = -0.53

  • step 3.

    • upstream gradient : -0.53
    • local gradient : 1
    • gradient : 1 $\times$ (-0.53) = -0.53

  • step 4.

    • upstream gradient : -0.53
    • local gradient : $e^x = e^{-1}$
    • gradient : e^{-1} $\times$ (-0.53) = -0.20

  • step 5.

    • upstream gradient : -0.20
    • local gradient : $-x = -1$
    • gradient : -1 $\times$ -0.20 = 0.20

  • step 6.

    • upstream gradient : 0.20
    • local gradient : 1 (both)
    • gradient : 1 $\times$ 0.20 = 0.20 (both)

  • step 7.

    • upstream gradient : 0.20
    • local gradient : $x_0, w_0$
    • gradient

      $w_0$ : -1 $\times$ 0.2 = -0.2

      $x_0$ : 2 $\times$ 0.2 = 0.4

2-1-4) 노드의 그룹화

또한, 지금은 가장 작은 단위의 노드를 사용하였지만, 이 노드를 더 복잡한 그룹으로 묶을수도 있다. 그 노드에 대한 local gradient를 구할수만 있다면, 문제없이 더 간단히 gradient를 구할 수 있다(local gradient * upstream gradient).

위 그림과 같이 특정 노드 그룹의 도함수를 알고있는 경우, 그룹화시켜 그래프를 단순하게 만들 수 있는 것이다. 하지만, 계산량과 그래프의 단순함은 trade-off 관계에 있음을 유의하자!

  • 그래프가 단순 -> gradient 계산 복잡
  • 그래프가 복잡 -> gradient 계산 단순


2-3) 패턴

우리는 앞서 살펴본 예제에서 다음과 같은 패턴을 확인할 수 있다.

2-3-1) 덧셈 게이트

upstream gradient를 연결된 브랜치에 정확히 같은 값으로 나누어 준다.

2-3-2) max 게이트 (gradient router)

하나에는 upstream gradient의 전체값이, 나머지 하나에는 0이 들어간다. 왜냐하면 local gradient가 1,0이기 때문이다.

2-3-3) 곱셈 게이트 (gradient switcher or scaler)

반대편 변수의 값이 upstream gradient와 곱해져 들어간다.

2-3-4) 하나의 노드에서 다른 노드 두개로 이어진 경우

뒤의 두개의 노드에서 오는 미분 값을 더한 값이 들어간다. 반대로 앞의 노드 하나만 바뀌어도 뒤의 노드 두 개가 모두 바뀐다.


2-4) 요약

  1. computational graph로 나타내기
  2. 출력으로 이어지는 모든 계산이 무엇인지 파악(순전파)
  3. 역방향 계산 // computational graph에서 정의한, 계산에 필요한 중간 변수에 대한 gradient 가져오기



2. backpropagation at vector

모든 흐름은 같지만 gradient는 jacobian 행렬(각 요소의 미분을 포함하는 행렬)이 될 것이다. 이 때, jacobian matrix는 input matrix의 길이를 변으로 가지는 정방형 행렬이다. 가령 input이 cnn에서 흔히 볼 수 있는 사이즈인 409x4096 벡터라면, jacobian 행렬의 사이즈는 4096x4096이 된다. 이 때, mini batch가 100이면 사이즈는 409600 * 409600으로, 매우 크다. 그러나 실제로 jacobian matrix는 diagonal matrix이기 때문에 이 거대한 값을 일일이 계산할 필요는 없다.

2-1) Calculate

scalar일때와 기본적인 흐름은 동일한 것을 알 수 있다. 자세한 계산 과정은 위에서 자세히 다뤘으므로 생략하겠다.



3. 요약

  • 신경망 -> 매우 크고 복잡함

  • 따라서 모든 파라미터에 대해 gradient를 손으로 구하고 써내려가는 것은 비현실적이다.

  • 따라서 gradient를 계산하기 위해 backpropagation을 사용(신경망의 핵심 기술)

  • 그리고 이것은 computational graph에서 chain rule을 재귀적으로 적용한 것임

  • vector에서, 이를 구현하는 것은 size가 매우 크다.

  • 따라서 forward/backward API 구현하는 방법들을 도입(생략)



Neural Networks

Neural Networks (인공 신경망)는 앞에서 배운 Linear Classifier을 2개 이상 쌓아올리는 형태이다. 여기서 중요한 부분은 이 사이에 Non-linear function를 사용해야 한다는 점이다(그렇지 않으면 결국 Linear function이 됨). 아래의 예시를 살펴보자. 우선, 3072개의 입력 x와 W1의 linear classification 결과로 100개의 h 값을 계산한다. 이후, 이 값에 Non-linear max 함수를 취하고, W2값을 linear classification으로 사용하여 최종적으로 10개의 결과 가지게 된다.

기존에는 선형 레이어 하나만 쌓아서 빨간색 자동차만을 찾을 수 있었지만, Neural Networks를 이용함으로써 빨간색, 노란색 자동차와 같이 여러 색깔(feature)의 찾을 수 있게 되었다. 이러한 방법으로 레이어를 쌓아가면서 여러 특징을 추출 할 수 있음을 확인하였다.

댓글남기기