4 minute read

신경망에서의 학습이 어떻게 이루어지는지 알아보자. 또한, 손실을 최소화하기 위해서 가중치와 편향을 어떻게 업데이트 시키는지 정리해보자.

신경망 학습 과정

  1. 데이터가 입력되면 각 층에서 가중치-편향 및 활성화 함수 연산을 수행한다. (순전파)

  2. 모든 층에서 연산을 수행한 후 출력층에서 계산된 값을 출력한다. (순전파)

  3. 손실 함수를 사용하여 예측값과 실제값의 차이를 계산한다. (손실 계산)

  4. 경사하강법과 역전파를 통해 각 층의 가중치를 갱신한다. (역전파)

  5. 학습을 중지할 기준을 만족할 때까지 위 과정을 반복한다.

1 ~ 4번까지의 과정을 Iteration이라고 하며 Iteration마다 가중치가 갱신된다.

  • 순전파(Forward Propagation)

순전파는 입력층에서 입력된 신호를 은닉층에서 연산을 거치고 출력층에서 출력값을 내보내는 과정이다.

  • 손실 함수(Loss Function)

손실함수는 손실을 계산하는 함수로 모든 연산을 거쳐 출력층에서 내보낸 값(예측값)과 실제값의 차이를 계산하는 함수이다. 신경망 학습은 이 손실 함수를 최소화하는 방식으로 가중치를 갱신한다. 회귀, 분류에 따라 사용하는 함수가 다르고 같은 회귀 or 분류 문제라도 다른 손실함수를 사용할 수 있고, 회귀에서는 MSE, 분류에서는 Cross Entropy를 주로 사용한다.

  • 역전파(Backward Propagation)

역전파는 순전파와 반대 방향으로 손실 정보를 전달해주는 과정이다. 출력층에서 계산한 손실 정보를 입력층까지 역으로 전달하며 가중치를 갱신하는 알고리즘이다.

경사 하강법(Gradient Descent)

역전파의 목적은 손실을 최소화하는 방향으로 가중치를 갱신하는 것인데, 그렇다면 어떤 방법을 사용해서 손실을 최소화 할까? 여기서 사용하는 것이 경사 하강법이다. 손실 함수를 그래프로 나타내면 이 손실 함수의 경사(기울기)가 가장 작아지는 방향으로 업데이트 하여 손실 함수의 값을 줄일 수 있다. 경사가 가장 낮은 부분이 손실이 가장 작은 부분이기 때문에 매 Iteration마다 해당 가중치에서 손실 함수의 미분값을 계산하여 경사가 작아지도록 가중치를 변경한다.

!기울기가 큰 것은 경사가 가파르다는 뜻이기도 하지만, x의 위치가 최소/최대 값에 해당되는 x좌표로부터 멀어져 있다는 뜻이 됨.



image



위의 그래프를 보면 알 수 있듯이 기울기가 음수라면 양의 방향으로 x를 이동시켜야 손실을 최소화 시키고, 기울기가 양수면 음의 방향으로 이동시켜야 한다. 가중치를 갱신하는 것을 기울기의 부호에 따라 수식으로 표현하면 다음과 같다.

image

여기서 $x$ii 번째 iteration에서 계산된(갱신전) 가중치고, $x$i+1 은 새롭게 갱신될 가중치이다.

새로 갱신 될 가중치는 기존 가중치에서 기울기가 음수냐, 양수냐에 따라 적합한 방향으로 이동한다. 최종수식은 다음과 같다.

image

이미지출처: https://angeloyeo.github.io/2020/08/16/gradient_descent.html

이동거리는 학습률 이라고 하는 $a$와 해당 지점에서의 기울기가 곱해져서 표현된다. 이 학습률이 이동거리를 결정하게 될텐데 학습률이 높다면 이동거리가 커져서 가중치를 갱신하는 시간이 덜 걸리겠지만, 기울기가 최소가 되는 지점을 지나칠 수도 있고, 학습률이 낮아서 이동거리가 너무 작다면 최소의 기울기를 찾기위해 오랜시간이 소요되기 때문에 적당한 학습률을 사용자가 지정해주어야 한다.

가중치 갱신 방법(feat. 경사하강법)

경사하강법을 통해 손실을 최소화시키는 방향으로 가중치를 갱신한다는 것은 알겠는데 어떠한 방법으로 가중치를 갱신할까?

가중치를 갱신하려면 현재 iteration에서의 기울기를 알아야 그 기울기에서 step size만큼 이동해서 갱신할 수 있다.

기울기는 가중치($w$)가 변할 때 손실($y$ = $f(x$i$)$)함수가 어떻게 변하는지를 나타내고, 손실함수는 다음과 같이 표현할 수 있다.

\[f(x) = \frac{1}{2}(y-(wx+b))^2\]

$ \frac{1}{2} $은 계산편의를 위한 것이고, $(wx+b)$는 가중치 연산을 통해 나온 예측값($y’$)이다. 위의 식에서 업데이트 하고자 하는 것은 가중치이므로 $y$, $w$ ,$x$, $b$로 이루어진 다변함수인 손실함수를

1) w에 대해 편미분한다(w 외의 나머지 변수는 모두 상수 취급)

2) Chain rule을 적용한다.($F(x) = f(g(x))$ => $F(x) = f’((g(x)))$ x $g’(x))$ )

-> 밖에꺼 미분 * 안에꺼 미분

\[\frac{df(x)}{dw} = (y-y') * x\]

만약 가중치가 하나가 아니라 여러개이고, 한 번에 최종 가중치를 구하기가 힘들다면 Chain rule을 활용하여 특정변수에 대한 편미분 값을 다른 변수의 미분을 사용하여 나타낼 수 있다.

$ \frac{df(x)}{dw_{i}} $ 를 한번에 구하기 복잡하니까 역전파 과정에서 해당 노드 이전의 가중치인 $w_{x}$ 와 $w_{y}$ 를 활용해서(Chain rule. 쪼개서 미분) 최종적으로 $ \frac{df(x)}{dw_{i}} $ 을 구한다.

image

3) 이렇게 구한 기울기를 활용하여 가중치를 갱신 시킨다.

\[w_{new} = w - a * \frac{df(x)}{dw} = w - (a * (y-y') * x)\]

옵티마이저(Optimizer)

옵티마이저는 경사를 내려가는 방법을 결정하는 것으로, 손실을 어떻게 최소화할 것인지 최적화 방법을 정하는 것이다. 경사하강법도 이 옵티마이저 중 하나에 해당한다. 밑의 그림은 여러 옵티마이저를 나타낸 것이고, 이외에도 다양한 옵티마이저가 있지만 이번 포스팅에서는 확률적 경사하강법과 미니배치 경사 하강법에 대해서만 다뤄보자.

image

이미지 출처: https://github.com/JinwoongKim/AI/issues/11

일반적인 경사 하강법(GD)는 모든 입력 데이터에 대한 손실 함수의 기울기를 계산한 후 가중치를 업데이트 한다. 즉, Iteration마다 모든 데이터를 다 사용하게 되는데 입력 데이터가 많다면 손실을 계산할 때 걸리는 시간이 매우 오래 걸려 최적화가 빨리 될 수 없다.

  • 확률적 경사 하강법(Stochastic Gradient Descent, SGD)

위의 문제를 해결하기 위해 SGD를 사용할 수 있는데 SGD는 전체 데이터에서 하나의 데이터만 뽑아서 신경망에 입력한 후 손실을 계산한다. 이 손실 정보를 역전파해서 신경망의 가중치를 업데이트 한다. 이는 곧 Iteration마다 하나의 데이터만 사용하게 되기 때문에 가중치를 빠르게 업데이트 할 수 있다는 장점이 있다. 하지만, 1개의 데이터만 보기 때문에 이 데이터가 이상치일 경우 가중치가 좋게 갱신되지 않을 수 있어서 불안정한 경사 하강을 보인다.

image

이미지 출처: https://datascience-enthusiast.com/DL/Optimization_methods.html

  • 미니 배치 경사하강법(Mini-batch) 경사 하강법

GD와 SGD의 문제를 해결하기 위해서 MBGD를 사용할 수 있다. SGD는 한 개의 데이터로만 손실을 계산할 수 있기 때문에 가중치를 업데이트 하는 과정이 불안정했다. MBGD는 데이터의 수를 늘려서 N개의 데이터로 미니 배치를 구성하고 해당 미니 배치를 신경망에 입력해 손실함수를 계산하고 가중치를 업데이트 한다. 즉 Iteration마다 1개보다는 더 많은 N개의 데이터를 활용함으로써 GD보다는 시간이 적게 걸리고, SGD보다는 가중치 업데이트 과정이 안정적이다.

image

이미지 출처: https://datascience-enthusiast.com/DL/Optimization_methods.html

  • 배치 사이즈(Batch Size)

미니 배치 경사 하강법에서 사용하는 미니 배치의 크기를 배치 사이즈라고 한다. 배치 사이즈는 CPU와 GPU의 메모리 단위인 2의 배수로 사용하고 가능하다면 큰 배치 사이즈를 쓰는 것이 학습에 더 안정적이다.

에포크는 전체 데이터셋을 몇번 반복해서 학습할 지를 결정하는 것이고, Iteration은 순전파-역전파가 1회 즉, 가중치가 한 번 수정되는 단위이다. 이를 통해 전체 데이터 수는 배치사이즈와 Iteration으로 표현할 수 있다.

\[Number\;of\;Data = Batch\;size * Iteration\]

ex) 만약 데이터가 1000개이고 batch_size가 10, epochs가 3이면

\[Iteration = (1000*3) / 10 = 300\]

!위 수식을 통해 GD와 SGD를 비교해보자. Epochs가 1이라고 가정하고, 전체 데이터 수가 1000이면, GD는 batch_size가 1000이고 iteration을 1회 반복한다. 반면 SGD에서는 batch_size가 1이고 iteration을 1000회 반복한다. 두 경사하강법 모두 1x1000 이라는 데이터를 사용하지만 업데이트 관점에서는 SGD가 1개로 빠르게 1000번 가중치를 업데이트하기 때문에 더 빠르다고 한다. 1000개의 데이터에 대해 손실을 구하고 가중치를 한번 업데이트 하는 것보다, 1개의 데이터마다 가중치를 업데이트 하여 1000개의 데이터를 보는 것이 더 효율적인 방법인 것이다.

하지만, 역시 언제나 더 빠른 경사하강법이라는 것이 없으니까 상황에 따라 좋은 성능 대비 적은 시간을 요구하는 옵티마이저를 사용해야한다.

Categories:

Updated: