[CS231n] Lecture 4 : Introduction to Neural Networks

정재윤·2021년 10월 6일
0

Introduction

지난 시간에 저희는 loss function과 optimization에 대해서 배웠습니다. 그리고 최적의 weight를 찾기 위해서 우리는 편미분을 통해 gradient를 구해야 한다는 점도 배웠습니다. gradient를 구하는 방식은 Numerical gradient와 Analytic gradient로 크게 2가지를 설명했습니다. 각각의 특징를 확인하고 Numerical gradient의 경우, 직접 예시를 통해 확인했습니다. 그러나 Numerical gradient의 경우, 차원이 커지면 커질 수록 너무 비효율적이라는 단점을 가지고 있었습니다. 그래서 일반적으로는 analytic gradient를 사용하고, 확인용으로 numerical gradient를 사용한다고 했습니다.

이번에는 analytic gradient에 대해서 이야기하겠습니다.

Backpropagation

analytic gradient를 하기 위해서는 Backpropagation에 대해서 제대로 이해해야합니다. 예시를 통해 차근차근 알아보겠습니다.

다음과 같은 함수가 있다고 가정합시다. x,y,z는 각각 -2, 5, -4의 값을 가집니다. 이를 이해하기 쉽게 그래프로 나타내면 오른쪽과 같습니다. 함수에 따라 값을 구하면 우리는 최종적으로 -12라는 값을 가지게 됩니다.

이 때 우리가 알고 싶은 것은 x,y,zx,y,zff에 미치는 영향력을 알고 싶은 것입니다. 즉, 각각의 편미분 값인 fx,fy,fz\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}, \frac{\partial f}{\partial z}을 구해야하는 것이죠. 이 값들을 찾기 위해서는 가장 끝부터 차근차근 계산을 해야합니다.

우선 가장 끝값인 ff\frac{\partial f}{\partial f}값부터 구해봅시다. 이 때는 자기 자신을 미분한 것이므로 1의 값을 가질 것입니다.

이제 fz\frac{\partial f}{\partial z}값을 구해봅시다. f=qzf = qz이므로 z로 편미분을 진행하면 위에서 구한 것과 같이 qq가 될 것입니다. 즉, fz\frac{\partial f}{\partial z}는 현재 qq값인 3이 될 것입니다.

fq\frac{\partial f}{\partial q}값 역시 위에서 구해뒀기 때문에 쉽게 구할 수 있습니다. f=qzf = qzqq로 편미분한 값이기에 zz가 나올 것이고 현재 zz의 값은 -4이므로 fq\frac{\partial f}{\partial q}는 -4가 될 것입니다.

그렇다면 fx,fy\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}는 어떻게 구할까요? 지금까지는 간단한 편미분을 통해서 구했습니다. 하지만 지금부터는 ff에 직접적으로 연결되어 있지 않습니다. xxqq에 영향을 주고, qqff에 영향을 주게 되죠. 그래서 저희는 Chain rule이라는 미분의 연쇄법칙을 적용합니다.

Chain rule을 적용하게 되면 위의 공식처럼 fy=fqqy\frac{\partial f}{\partial y} = \frac{\partial f}{\partial q}\frac{\partial q}{\partial y}가 되면서 앞서 우리가 구해놨던 조건들을 사용할 수 있게 됩니다. 따라서 fy\frac{\partial f}{\partial y}는 (-4)*1이 되면서 -4라는 값을 가지게 됩니다.


fx\frac{\partial f}{\partial x}값도 같은 방식으로 구할 수 있으며 -4라는 값을 얻을 수 있게 됩니다.


이를 일반화해보자면 위의 그림과 같이 표현할 수 있습니다. 우선 각 노드들은 모두 output값을 가지고 있습니다. 그리고 이를 노드의 변수들로 미분한 값을 local gradient라고 합니다. 앞에서 넘어온 gradient(global gradient, upstream gradient 등으로 불림)에 local gradient를 곱해 gradient는 구하는 것입니다. 그리고 뒤에 노드들이 연결되어 있다면 계산한 gradient를 뒤로 넘기는 것입니다. 이 과정을 더 이상 뒤로 넘길 node가 없을 때까지 반복하는 것입니다.


앞선 예시보다 더 복잡한 예시를 보겠습니다. f(w,x)f(w,x)를 위와 같이 정의해봅시다. 그러면 연산에 대한 그래프는 다음과 같이 나타낼 수 있을 것입니다. 그리고 저희가 앞으로 사용할 local gradient를 미리 구하면 위와 같이 총 4개의 수식을 구할 수 있습니다.

앞서 계산했듯이 처음 gradient는 1이 될 것입니다.

다음 gradient를 구해봅시다. 저희가 사용할 local gradient는 1x2\frac{-1}{x^2}이 되고, 이 때의 gradient는 1이 됩니다. 따라서 이 두 값을 곱해주게 되면 111.372=0.531 * \frac{-1}{1.37^2} = -0.53이 됩니다.


이런 식으로 앞의 gradient를 계속해서 뒤로 넘겨주게 됩니다. exe^x의 경우, 편미분했을 때도 exe^x이므로 local gradient가 e1e^{-1}이 되고 들어온 gradient가 -0.53이 되면서 최종적으로 -0.2가 됩니다.




이와 같은 과정을 통해 우리는 최종 gradient를 구할 수 있게 됩니다.

여기서 backpropagation의 한 가지 특징이 나타납니다. 특정 함수들은 앞에서 했던 것처럼 하나하나 계산할 필요가 없다는 것입니다.

앞서 우리가 했던 예시는 sigmoid 함수에 대해서 하나하나 backpropagation을 진행한 것입니다. 하지만 sigmoid 함수 자체를 미분하여 local gradient로도 사용할 수 있습니다. 실제로 dσ(x)dx\frac{d\sigma(x)}{dx}를 구하면 (1σ(x))σ(x)(1-\sigma(x))\sigma(x)를 구할 수 있습니다. 즉, sigmoid gate 부분의 backpropagation 부분을 sigmoid의 local gradient를 통해 한 번에 구할 수 있게 됩니다. 이 과정을 통해 구한 값은 역시 0.2로 같은 값이 나오는 것을 확인할 수 있습니다.

또한 이러한 과정을 통해 우리는 자주 쓰이는 add, mul, max gate 3가지에 대해 또 다른 특징을 발견하게 됩니다. add gate는 local gradient가 1입니다. 그렇기에 upstream gradient를 그래도 전해주기 때문에 distributor라고 불립니다.

max gate는 큰 값에 gradient를 그대로 전하고, 작은 값에는 0을 보냅니다. 이 모습이 최적의 경로를 지정하는 router와 닮아 gradient router라고 불리는 것 같습니다.

mul gate는 앞서 예시에서 풀어본 것과 마찬가지로 서로의 값을 교환하게 됩니다. 즉, switch가 되는 것이죠. 그래서 이 gate는 gradient switcher라고 불립니다.

지금까지는 upstream gradient가 1개 뿐이었습니다. 그렇다면 upstream gradient가 2개면 어떻게 될까요? 단순히 각 node에서 온 gradient들을 더해주시면 됩니다.


하지만 일반적으로 저희는 스칼라 값이 아니라 벡터값을 사용할 것입니다. 그래서 지금부터는 조금 더 확장해서 x,y,zx,y,z가 모두 벡터라고 가정합시다. 전반적인 흐름은 우리가 위에서 한 예시와 다를 바 없습니다. 주의하여야 할 부분은 local gradient들이 모두 jacobian matrix 형태가 된다는 것입니다.

그렇다면 Jacobian matrix는 무엇일까요? n개의 변수를 가지는 함수가 m개 있다고 가정합시다.
즉, F1(x1,...,xn),....,F1(x1,...,xn)F_1(x_1,...,x_n),....,F_1(x_1,...,x_n)라는 함수들이 있는 것이죠. 이 함수들을 모든 변수들에 대해서 편미분을 진행하고 이를 행렬로 나타낸 것을 jacobian matrix라고 합니다. 이 말을 수식으로 나타내면 아래의 행렬이 나타날 것입니다.

[F1x1...F1xn::Fmx1...Fmxn]\left[ \begin{matrix} \frac{\partial F_1}{\partial x_1} & ... & \frac{\partial F_1}{\partial x_n} \\ : & & : \\ \frac{\partial F_m}{\partial x_1} & ...& \frac{\partial F_m}{\partial x_n} \\ \end{matrix} \right]

이제 다시 한번 차근차근 해봅시다. 위의 그림과 같이 input과 output의 차원이 4096일 때, Jacobian matrix의 크기는 행렬의 연산에 따라서 4096 X 4096이 될 것입니다. 이 때 주의하셔야 할 점은 input을 하나만 넣었을 때라는 점입니다.


만약 minibatch의 사이즈를 100으로 두고 진행한다면 저희가 연산해야하는 Jacobian matrix의 크기는 409600 x 409600이 될 것입니다. 그렇지만 이 모두를 염두해서 jacobian matrix를 계산해야 하지는 않을 것 같습니다. 그 이유는 우리의 연산에서 막상 jacobian matrix를 구하게 되면 대각행렬과 유사한 모양이 나오기 때문이죠. 따라서 행렬의 요소값을 전부 다 구할 필요는 없게 됩니다.

그렇다면 구체적인 예시를 통해 알아보겠습니다. 예시는 그림과 같고, W,xW, x 각각의 값은 위와 같이 정했습니다. 그리고 그래프를 따라 차근차근 계산을 해보면 최종적으로 우리는 0.222+0.262=0.1160.22^2 + 0.26^2 = 0.116의 값을 가지게 됩니다. 그리고 backpropagation을 위해 가장 처음 gradient를 구하면 1이 나옵니다.

이 후 local gradient를 구해봅시다. 앞서 우리는 f(q)=q2f(q) = ||q||^2이라고 정의했습니다. 이 때 ff를 각qiq_i들로 편미분을 진행하면 fqi=2qi\frac{\partial f}{\partial q_i} = 2q_i가 되기 때문에 위의 0.44와 0.52의 값을 얻을 수 있습니다.

gradient를 다음 node로 넘겨 봅시다. 우선 local gradient의 값은 1k=ixj1_{k = i}x_jk=ik = i일 때 xjx_j, 그렇지 않으면 0의 값을 가지게 됩니다. Chain rule에 의하여 최종 gradient를 구하게 되면 2qixj2q_ix_j의 값을 가지게 됩니다. 따라서 우리는 그림 왼쪽 위의 빨간 행렬을 얻을 수 있게 됩니다.

여기서 주의하셔야 할 점은 함부로 곱하는 것이 아닌 xx 행렬을 transpose 시켜야 한다는 점입니다. 왜냐하면 gradient 행렬의 크기는 원래 변수의 크기와 같아야 하기 때문입니다.

마지막으로 xx에 대한 gradient도 구합시다. 우선 local gradient를 구하면 Wk,iW_{k,i}의 값이 나오게 됩니다. 앞서 했던 것처럼 Chain rule을 적용하면 최종적으로 우리는 위와 같은 gradient를 구할 수 있게 됩니다. 역시 여기서 주의하셔야 할 점은 WW를 Transpose 시켜야 한다는 점입니다. 또한 연산의 순서도 앞의 WW를 구할 때와는 다르므로 유의하여야 합니다. (연산의 순서가 다른 이유는 shape을 맞춰주기 위함으로 보입니다.)

Summary

최종적으로 Backpropagation이라는 것은 Chain rule을 재귀적으로 적용해서 input과 parameter의 gradient들을 찾아나가는 과정입니다.

Neural Networks

이전에 저희는 Linear score function과 같이 하나의 함수식만을 사용하여 이미지를 분류했습니다. 그러다보니 class마다 만들 수 있는 템플릿은 하나로 모든 이미지의 평균값 밖에 갖지 못했습니다. 대표적으로 자동차의 템플릿이 빨간색이다보니 다른 색의 자동차가 들어오면 자동차라고 제대로 분류를 못하는 것이죠.

하지만 이제부터는 layer를 여러개 쌓으면서 여러 개의 weight를 가질 수 있게 됐습니다. 그러다보니 템플릿은 더 이상 하나만을 사용하는 것이 아니게 됐습니다. 위의 예시를 보면 가운데 h라는 layer가 생겼고 이 때 노드가 100개가 되면서 총 100개의 템플릿을 만들 수 있게 됐습니다.

3개의 layer는 이렇게 표현할 수 있습니다.


우리가 배울 Neural Network는 인간의 Neuron에서 착안해온 모델이다보니 상당부분 Neuron과 닮았습니다. Neuron은 synapse를 통해 자극이 들어오면 axon을 거친 뒤 그 다음 뉴런으로 신호를 전달합니다.

Neural Network 역시 이와 유사합니다. input이 들어오게 되면 가중치를 곱하고 이를 다 더해준 뒤, 활성함수를 거치게 됩니다. 그리고 그 값을 다음 노드에 전달하는 구조인 것이죠. 여기서 활성함수는 sigmoid와 같은 함수들입니다.

그러나 염두해야할 점은 실제 neuron과 neural network가 서로 같다고 이해하시면 안됩니다. 그 개념을 착안해왔다는 점을 알아두셔야 합니다.

지금까지는 활성화함수를 단순히 sigmoid만을 확인했었는데요. 활성화함수에는 sigmoid 말고도 relu, tanh 등 다양한 종류의 활성화함수가 있습니다.

마지막으로 2 layer neural network과 3 layer neural network는 위와 같은 구조를 가집니다. 그리고 위 모델의 마지막 layer와 그 앞의 hidden layer를 보면 모든 노드들이 다 연결된 것을 볼 수 있습니다. 우리는 이를 fully connected라고 합니다.

Reference

https://deepinsight.tistory.com/98
https://lsjsj92.tistory.com/393?category=792966

0개의 댓글