devmoon

[논문 리뷰] An overview of gradient descent optimization algorithms 본문

AI/논문 리뷰

[논문 리뷰] An overview of gradient descent optimization algorithms

Orca0917 2022. 8. 19. 01:13

경사하강법과 관련된 여러 기법들을 정리해서 소개하는 이번 논문은 각 경사하강법의 최적화 방법 또는 이론들이 어떻게 등장하였고, 그 원리가 무엇인지 간단하게 이해하기 좋다고 생각되었다. 실제로 읽으면서 각 최적화 알고리즘들이 어떻게 이전의 단점들을 개선시켜 나갔는지 그 흐름을 파악하기가 좋았었다.

 

 

 

 

이 논문에서 소개하는 것들은 정말 기본적인 Gradient Descent(GD)를 시작으로 SGD, Mini-batch GD 과 최적화 기법인 momentum, NAG, Adagrad, Adadelta, RMSprop, Adam 등이 있다. 이외에도 2가지 최적화 방법 AdaMax와 Nadam이 있지만 자주 등장하는 개념은 아닌 것 같아 세세하게 읽어보지는 않았다.

 

 

 

 

저자는 처음에 경사하강법이 무엇인지 짧지만 매우 간결하고 이해하기 쉽게 다루고 지나간다. 딥러닝에서 각 레이어에 사용되는 파라미터인 $d$ 차원의 $\theta$ 를 목적(손실) 함수인 $J(\theta)$를 사용해 최적화하는 방법이라고 한다. 목적함수를 $\theta$ 에 대해서 최소화시켜야 하기 때문에, 그 미분 값인 그래디언트 $\nabla_\theta J(\theta)$ 를 구해야 한다. 또 등장하게 되는 $\eta$ 는 학습률로, (local) minimum에 도달하기 위한 보폭의 크기를 결정한다. 저자는 쉽게 설명해 경사하강법을 아래와 같이 표현한다.

 

 

"어떤 산에서 골짜기로 내려가기 위해 경사를 따라서 내려가는 방법"


 

 


 

 

 

 

경사하강법이 무엇인지 알았으니 이번에는 그 종류에 대해서 알아봐야 한다. 경사하강법의 종류는 최적화할 때 사용하는 데이터의 수에 따라 크게 3가지로 분류한다. 사용하는 데이터의 크기에 따라 trade-off 관계가 있는데, 바로 최적화를 하는 데 걸리는 시간과 최적화의 정확도이다. 최적화의 정확도가 높을수록, 걸리는 시간이 높다는 의미이다.

 

 

 

 

 

 

 Batch Gradient Descent 

 

배치 경사하강법은 Vanilla(순수) 경사하강법이라고도 불리며, 학습에 사용되는 데이터셋 전부를 사용하여 파라미터 $\theta$ 를 업데이트하는 방법이다.

 

$$\theta = \theta - \eta \cdot \nabla_\theta J(\theta)$$

 

한 번의 업데이트를 진행할 때마다 모든 데이터셋을 활용해야 하기 때문에, 속도가 느릴 수밖에 없다. 만약 데이터의 크기가 너무 커서 메모리에 조차 모두 올릴 수 없는 상황이 온다면 상당히 난감해지게 된다. 또한 실시간으로 추가되거나 변화하는 데이터에 적합하지 않다. 코드로 보면 다음과 같이 표현할 수 있다.

 

 

 

for i in range(EPOCH):
    params_grad = evaluate_gradient(loss_function, data, params)
    params = params - learning_rate * params_grad

 

 

 

미리 정의한 epoch 수만큼 반복하면서 최적화를 진행하게 되며, evaluate_gradient 함수는 손실 함수와 전체 학습 데이터 그리고 학습 파라미터를 사용하여 그래디언트를 계산하는 함수이다. 그리고 이 계산된 그래디언트를 사용하여 학습률과 곱해 현재 파라미터인 $\theta$ 를 업데이트한다. 사실 위의 수식을 그대로 코드로 옮겨 작성한 것이라 매우 비슷하게 표현되어 있다. 배치 경사하강법의 특징으로는 convex 한 목적 함수인 경우에는 반드시 global minimum에 도달하는 것이 보장되며 non-convex 하게 그려지는 경우에는 적어도 local minimum에 도달하는 것이 보장된다.

 

 

 

 

 

 

 

 Stochastic Gradient Descent 

 

위의 Batch Gradient Descent는 학습 데이터 전부를 사용하여 파라미터 $\theta$ 를 업데이트했다면, 이번 SGD는 매 업데이트마다 하나의 학습 데이터를 사용하여 파라미터를 업데이트한다. 그리고 뽑은 학습데이터를 여기서는 수식으로 입력값 $x^{(i)}$ 와 출력 값(라벨) $y^{(i)}$ 로 표현한다. 하나 주의할 점은 한 번의 epoch에서 한 번의 파라미터 업데이트가 이루어지는 것이 아니라, 데이터의 개수만큼 파라미터의 업데이트가 이루어진다는 것이다.

 

 

$$ \theta = \theta - \eta \cdot \nabla_\theta J(\theta; x^{(i)}; y^{(i)}) $$

 

 

Batch Gradient Descent에서는 모든 데이터를 사용하기 때문에 비슷한 업데이트 효과를 만들어내는 값들이 있게 되면 불필요한 연산을 하도록 만들었다. 하지만, SGD는 한 번에 단 한 개의 데이터를 사용하여 업데이트를 하기 때문에 불필요한 연산이 나올 수 없도록 제거하였다. 그렇기 때문에 훨씬 빠른 속도로 파라미터를 업데이트할 수 있었지만, 파라미터의 업데이트 변화량이 매우 높게 진동하는 모습을 보여주게 된다.

 

 

출처: An overview of gradient descent optimization algorithms

 

 

 

이 높은 변화량은 파라미터를 업데이트할 때, 잠재적으로 local minimum이 될 만한 파라미터 값으로 업데이트를 진행해서 좋을 수는 있지만, 정확한 minimum 값에 수렴하는 것을 방해하게 될 수도 있다. 이 문제는 간단하게 학습률을 줄여나가면 해결이 되며 심지어 Batch Gradient Descent와 유사한 성능을 내는 것으로 보인다고 한다. 코드를 보면, 앞서 본 코드에 하나의 데이터를 추출하는 것이 추가되었다.

 

 

 

for i in range(EPOCH):
    np.random.shuffle(data)
    for example in data:
    	params_grad = evaluate_gradient(loss_function, example, params)
        params = params - learning_rate * params_grad

 

 

여기서 매번 동일한 순서의 데이터를 사용하게 되면, 편향된 정보를 학습할 가능성이 있기 때문에, 매 epoch 마다 전체 데이터를 shuffle 해서 사용하는 것을 눈여겨볼 필요가 있다. 실제로 이렇게 매번 순서를 뒤섞어주면, 더 향상된 성능과 나은 수렴성이 관측된다고 한다.

 

 

 

 

 

 

 

 Mini-batch gradient descent 

 

미니 배치를 사용한 경사하강법은 앞서 설명한 2가지 방법의 장점들을 모두 가져올 수 있는 방법이다. 전체 학습 데이터셋에서 미니 배치 크기만큼 임의로 데이터를 추출하고, 이 추출된 데이터를 바탕으로 파라미터를 업데이트하는 방법이다.

 

 

$$ \theta = \theta - \eta \cdot \nabla_\theta J(\theta; x^{(i:i+n)}; y^{(i:i+n)}) $$

 

 

이 방식을 사용하게 되면, SGD에서 파라미터의 변화량이 크게 요동치는 것을 막아 더 안정적인 수렴을 할 수 있고, 좋은 딥러닝 라이브러리에서 제공하는 미니배치 그래디언트 계산을 사용하면 효율적으로 빠른 시간에 미분 값을 알아낼 수 있다. 일반적으로 미니 배치의 크기는 50 ~ 256으로 설정하지만, 문제에 맞게 설정하는 것이 가장 좋다. 처음에 딥러닝을 공부하면서 많이 헷갈렸던 게 SGD와 Mini-batch GD의 개념이었는데 그럴 수 있었던 것이 Mini-batch GD를 SGD라고 많이 혼용해서 사용한다고 한다.

 

 

 

for i in range(EPOCH):
    np.random.shuffle(data)
    for batch in get_batches(data, batch_size=50):
        params_grad = evaluate_grad(loss_function, batch, params)
        params = params - learning_rate * params_grad

 

 

 


 

 

 

 

 

이렇게 기본적인 경사하강법 기법들을 살펴보았지만 아직 완벽하게 모든 문제를 해결한 것은 아니다. 어떻게 보면, 전체 데이터를 사용하면 Batch GD부터 SGD, 미니 배치 GD 까지 점점 발전되면서 많은 개선이 있다고 볼 수 있지만, 논문의 저자는 아직 해결해야 할 것이 4개가 더 있음을 정리한다.

 

 

 

1. 적절한 learning rate $\eta$ 를 설정하는 것이 어렵다.

 

학습률이 너무 낮으면 수렴 속도가 너무 낮아 시간이 오래 걸리게 되고, 학습률이 너무 높으면 수렴이 잘되지 않고 minimum 값 주위에서 크게 변동하거나 minimum을 벗어나버리는 현상이 발생한다.

 

 

 

2. learning rate scheduler를 미리 지정해야만 한다.

 

learning rate를 유연하게 바꾸기 위해서 learning rate scheduler를 미리 지정해야만 하는데, 이는 학습 데이터셋의 특징을 완벽하게 반영하기 힘들게 한다.

 

 

 

3. 모든 파라미터에 동일한 학습률이 적용된다.

 

정말 최적의 학습을 하기 위해서는 각 파라미터에 맞는 학습률과 그래디언트가 필요하다. 그래디언트는 미분 값을 통해 구할 수 있었지만, 각 파라미터에 맞는 학습률을 찾아내지는 못했다. 예를 들어 어떤 파라미터는 많이 업데이트되고, 어떤 파라미터는 적게 업데이트 되도록 설정해야 할 수도 있다.

 

 

 

4. global minimum이 아닌 local minimum에 수렴하거나 안장점(saddle point)에 수렴할 수 있다.

 

안장점은 한 차원으로 보았을 때 그 점이 극소가 되는 지점이나, 다른 차원에서는 그 지점이 극대가 되는 지점이 되는 특이한 공간이다. 안장점에 빠지게 되었을 때 다른 최적화 알고리즘을 적용하지 않았다면 더 이상의 파라미터 업데이트가 일어나지 않을 수 있다.

 

 

 

 


 

 

 

 

위에서 제기한 문제를 해결하기 위해 우리는 경사하강법에 최적화 알고리즘을 적용시킬 필요가 있다. 단순히 위의 문제를 해결하는 것이 아니라, 수렴 속도를 빠르게 하기 위해서 최적화 알고리즘을 적용시켜볼 가치는 충분히 존재한다. 여러 가지의 최적화 알고리즘이 존재하지만, 그중에서 저자는 많은 양의 데이터셋에서도 효과적으로 적용 가능한 알고리즘들을 위주로 설명하였다.

 

 

 

 

 Momentum 

 

SGD는 협곡과 비슷한 모양새를 띄는 부분에서 크게 요동치면서 업데이트를 진행했었다. 이렇게 되면 minimum 값에 수렴하는 데 있어서 여러 번 진동해야 하기 때문에 속도가 늦어진다는 단점이 존재했다. 그림으로 보자면 아래에서 왼쪽 그림에 해당한다.

 

 

출처: An overview of gradient descent optimization algorithms

 

 

 

여기서 momentum이라는 개념을 추가하면 우측 그림과 같이 좀 더 빠르게 minimum에 도달하는 것을 볼 수 있다. momentum은 이전의 그래디언트 방향과 현재 그래디언트 방향이 같은 방향을 띈다면 더 큰 보폭으로 파라미터를 업데이트하는 것을 말한다. 흔히 관성이라고 표현을 하게 된다.

 

 

이전의 값을 얼마나 반영할 것인지 나타내는 값 $\gamma$ 가 사용되며, 특정 시점의 업데이트되는 값이 어느 정도인지 저장하는 $v_t$라는 값도 필요하다. 이 값들을 사용해서 기존의 경사하강법 방법론에 추가하면 아래와 같이 나타낼 수 있다.

 

 

\begin{aligned}
v_t &= \gamma v_{t-1} + \eta \nabla_\theta J(\theta)\\ \theta &= \theta - v_t
\end{aligned}

 

 

일반적으로 momentum $\gamma$ 는 0.9 나 비슷한 값으로 설정해서 사용을 한다. 저자는 momentum의 개념을 더 쉽게 설명하기 위해 어떤 볼록한 골짜기가 있고 여기서 공을 굴린 상황을 떠올리라고 한다. 공은 점점 내려가면서 속도가 붙어 더 빠르게 이동하게 될 것이고 오르막길이 되면, 속도가 점점 내려가다가 거꾸로 가속해가며 떨어지게 된다. 동일한 원리가 바로 이 momentum에 녹아내려져 있다고 표현한다.

 

 

 

 

 

 Nesterov Accelerated Gradient 

 

바로 위에서 설명한 공이 언덕을 타고 내려오는 것에 우리는 만족할 수가 없었다. 언덕을 더 잘 빠르게 내려와 수렴하는 더 똑똑한 공이 필요했고 그 똑똑한 공은 내가 앞으로 어디로 갈지 알고 있는 공이어야 했다. 만약 내가 앞으로 가야 할 곳이 오르막길이라면 미리 서서히 속도를 줄여나가 빠르게 수렴하도록 만들 수 있기 때문이다.

 

 

 

NAG 알고리즘은 이런 똑똑한 공의 개념을 그대로 적용시켰다. momentum에 앞으로 어디로 갈지 알고 있는 통찰력을 부여한 것이다. 파라미터를 업데이트할 때, momentum을 부여해서 앞으로 갈 지점을 대충 예상할 수 있는데, 그 예상된 지점의 그래디언트를 구해 파라미터를 업데이트한다. 쉽게 말해 공이 한 수 앞을 내다본다고 할 수 있다.

 

 

\begin{aligned}
v_t &= \gamma v_{t-1} + \eta \nabla_\theta J(\theta - \gamma v_{t-1})\\
\theta &= \theta - v_t
\end{aligned}

 

 

위의 식에서 눈여겨볼 것은 손실 함수 $J$ 에 전달된 인자인 $\theta - \gamma v_{t-1}$이다. 바로 이 지점이 이전의 momentum을 사용하여 예측한 다음 지점을 의미한다. NAG를 설명하는 그림을 살펴보면 좀 더 쉽게 이해할 수 있다.

 

 

 

출처: An overview of gradient descent optimization algorithms

 

 

 

위의 그림에서 파란색으로 표시된 것은 momentum이고, 초록색으로 표시된 것이 NAG이다. 먼저 파란색인 momentum을 살펴보면 현재의 진행방향과 유사할 경우, 더 큰 진행방향을 가지고 이동하는 것을 확인할 수 있다. 반면에 초록색인 NAG를 살펴보면, 갈색 화살표는 이전의 momentum 값이며, 붉은색 화살표는 앞으로 갈 것 같은 지점에서 계산한 그래디언트를 의미한다. 그리고 이 두 벡터를 더해 최종적으로 업데이트할 값을 결정한다.

 

 

 

NAG의 이런 내다보는 업데이트는 너무 빠르게 공이 이동(값이 크게 업데이트)하거나 특정 값에 크게 반응하는 것을 막아준다. NAG는 특히 RNN에서 큰 성능 향상을 이뤄냈다고 발표된 논문도 존재한다.

 

 

 

momentum과 NAG를 통해 각 상황에 맞게 파라미터들을 얼마나 크게 업데이트할 것인지 결정하는 역할을 대신 수행했다. 하지만, 여전히 남은 것은 전체 파라미터에 대해서 상황에 맞게 업데이트한 것이지 각 파라미터에 맞는 업데이트 크기를 알지는 못했다. 그래서 아래부터는 각 파라미터에 맞추어 최적의 업데이트가 이루어질 수 있도록 돕는 방법들에 대해서 살펴본다.

 

 

 

 

 

 

 Adagrad 

 

Adagrad는 적게 업데이트된 파라미터는 더 크게 업데이트하고, 이미 많이 업데이트된 파라미터는 적게 업데이트시키는 알고리즘이다. 이전까지 우리는 값을 업데이트할 때, 모든 파라미터에 대해 동일한 학습률인 $\eta$ 를 사용했었다. Adagrad는 각 시점과 각 파라미터에 맞는 학습률을 지정해줌으로써 수렴이 더 잘 되도록 만들어 주었다.

 

 

Adagrad의 알고리즘을 살펴보기 전에 각 시점에서 계산된 그래디언트를 저장해야하기 때문에 변수 $g_{t,i}$ 가 필요하다. 이 값은 $t$ 시점에 $i$ 번째 파라미터가 얼마나 업데이트 되었는가? 를 저장하는 변수이다.

 

$$ g_{t, i} = \nabla_{\theta_t} J(\theta_{t, i}) $$

 

 

만약, 여기서 SGD를 적용한다고 하면, 값의 업데이트가 이루어지는 수식은 이 그래디언트 값에 학습률을 곱하여 업데이트하는 아래와 같은 수식이 만들어질 것이다.

 

$$ \theta_{t+1, i} = \theta_{t, i} - \eta \cdot g_{t, i} $$

 

 

위의 수식에서는 모든 파라미터에 대해 동일한 학습률 $\eta$ 를 사용했기 때문에, 목적에 맞게 각 파라미터에 맞는 학습률의 지정을 해줘야 한다. 지금까지 각 파라미터가 얼마나 변화했는지 나타내는 대각행렬 $G_t$ 를 사용하여 학습률을 조정한다. 

 

$$ \theta_{t+1, i} = \theta_{t, i} - \frac{\eta}{\sqrt{G_{t, ii} + \epsilon}} \cdot g_{t, i} $$

 

 

여기서 표현하는 $G_{t, ii}$ 는 $i$ 번째 파라미터가 $t$ 시점까지 업데이트된 그래디언트의 제곱들을 모두 더한 값이다. 결과적으로 이를 사용해 학습률 $\eta$ 를 나누어 줌으로써 많이 변화한 파라미터는 적게 업데이트할 수 있는 것이다. 하나 독특한 것은 여기서 제곱근 연산자인 루트를 제거하면 성능이 안 좋아진다고 한다.

 

 

Adagrad의 장점으로는 학습함에 따라 학습률을 직접 튜닝해줄 필요가 없다는 것이다. 일반적으로 초기 학습률은 0.01로 설정하게 된다고 한다. 이렇게 좋아 보이는 Adagrad도 문제점이 존재하는데, 분모에 들어가는 $G_t$ 가 점점 시간이 지남에 따라 커질 수밖에 없기 때문에, 나중에 가서는 학습이 전혀 이루어지지 않을 수도 있다는 것이다. 그리고 이 문제를 해결하기 위해 바로 다음 개념이 소개되었다.

 

 

 

 

 

 

 Adadelta 

 

Adadelta는 Adagrad에서 소개한 문제점을 해결하기 위해 이전의 파라미터 업데이트 크기를 $w$ 개만큼만 저장하여 값이 너무 커지는 것을 방지한다. 정확히 $w$ 크기의 윈도우 크기를 지정하는 것은 비효율적일 수 있기 때문에, 가중 이동평균을 사용하여 너무 먼 이전의 그래디언트의 제곱 값들을 잊어버리도록 하였다.

 

$$ E[g^2]_t = \gamma E[g^2]_{t-1} + (1 - \gamma) g^2_t $$

 

 

위의 식에서 E 기호는 가중이동평균 값을 나타내며, $\gamma$ 값이 1 이하의 값으로 설정되기 때문에 더 먼 과거일수록 잊혀지도록 설정하게 된다. 여기서 사용하는 $\gamma$ 값은 일반적으로 momentum처럼 0.9를 사용한다. Adadelta의 더 깊은 개념을 설명하기 위해 먼저 앞서 등장한 SGD부터 다시 간단하게 알아보면 다음과 같다.

 

 

\begin{aligned}
\Delta \theta_t &= - \eta \cdot g_{t, i} \\
\theta_{t+1} &= \theta_t + \Delta \theta_t
\end{aligned}

 

 

그리고 위의 식에서 각 파라미터의 학습률을 조정하기 위한 Adagrad가 소개되었고, 학습률 $\eta$ 를 지금까지의 변화량으로 나누어주는 연산을 해주었다. 아래에서 성분곱 연산자인 $\odot$ 을 사용한 것은 $G_t$가 대각행렬이기 때문에 연산결과와 같아 사용할 수 있었다.

 

 

$$ \Delta \theta_t = - \frac{\eta}{\sqrt{G_t + \epsilon}} \odot g_t $$

 

 

이제 Adadelta는 위에서 분모가 너무 커지는 것을 방지하기 위해 가중이동평균을 사용했다. 위에서 표기한 것과 마찬가지로 가중이동평균은 $E$를 사용하여 표기를 진행했다.

 

 

$$ \Delta \theta_t = - \frac{\eta}{\sqrt{E[g^2]_t + \epsilon}} g_t $$

 

 

다시 여기서 분모는 제곱 평균 제곱근(Root Mean Squared)과 같기 때문에, $RMS[g]_t$ 라고 대체하여 표현하였다. 이렇게 기호를 단순화시킨 것은, 이후에 설명할 부분을 좀 더 쉽게 표기하기 위해서이다.

 

$$ \Delta \theta_t = - \frac{\eta}{RMS[g]_t} g_t $$

 

 

이제 Adadelta의 저자들은 위의 식에서 한 가지 문제점을 지적한다. 그 문제점은 파라미터를 업데이트하는 과정에서 사용한 분자와 분모의  단위가 맞지 않는다는 것이다. 이 문제를 해결하기 위해 Adadelta의 저자는 그래디언트의 제곱의 합이 아닌, 파라미터의 변화량의 제곱 합을 사용하도록 하였다. 하지만 아직 단위와 관련된 문제가 왜 제기되었고, 파라미터의 변화량 제곱합을 통해서 어떻게 해결했는지 이해하지 못하였다.

 

 

$$ E[\Delta \theta^2]_t = \gamma E[\Delta \theta^2]_{t-1} + (1 - \gamma) \Delta \theta^2_t $$ 

 

 

방금 새롭게 정의한 식을 RMS를 씌워 분자에 포함시키게 되면, Adadelta의 최종 업데이트 식을 만들어낼 수 있다. 하지만 $t$시점에서 $RMS[\Delta \theta^2]_t$ 를 아직 알 수는 없기 때문에, 바로 이전 시점인 $RMS[\Delta \theta^2]_{t-1}$ 의 값을 활용하여 근사한다고 한다.

 

 

$$ \Delta \theta_t = -\frac{RMS[\Delta \theta^2]_{t-1}}{RMS[g]_t} g_t $$

$$ \theta_{t+1} = \theta_t + \Delta \theta_t $$

 

 

Adadelta의 큰 장점은 바로 학습률인 $\eta$ 가 직접적으로 사용되지 않았다는 것이다. 학습을 시작하기 전에 직접 지정하지 않아도, 맞는 학습률을 찾아서 파라미터를 업데이트할 수 있게 되었다.

 

 

 

 

 

 

 RMSprop 

 

RMSprop은 조금 독특하게 논문으로 발표된 최적화 알고리즘이 아니라, 강의 중에 설명에서 나온 개념이다. 이 개념이 실제로 적용해보니 좋게 작용한 경우가 많아 이렇게 유명해지게 되었다고 한다.

 

 

 

RMSprop은 Adagrad의 문제점인 학습률이 0에 가까워지는 문제점을 해결하기 위해 고안된 알고리즘으로 Adadelta와 그 뿌리가 같다고 할 수 있다. 사실은 RMSprop의 수식이 Adadelta를 설명하면서 얻어낸 첫 번째 수식과 동일하다. Adadelta에서 단위를 통일시키기 이전의 결과물이 RMSprop의 수식과 같음을 확인할 수 있다.

 

 

 

\begin{aligned}
E[g^2]_t &= 0.9 E[g^2]_{t-1} + 0.1 g_t^2 \\
\theta_{t + 1} &= \theta_t + \frac{\eta}{\sqrt{E[g^2]_t + \epsilon}} g_t
\end{aligned}

 

 

 

RMSprop의 개념을 소개한 Hinton 교수는 $\gamma$값을 0.9로, 학습률 $\eta$값은 0.001로 초기 설정하는 것을 권장하였다.

 

 

 

 

 

 

 

 Adam 

 

Adam은 Adaptive Moment Estimation의 줄임말로 현재 딥러닝 모델의 학습에서 가장 많이 사용되는 경사하강법 최적화 알고리즘이다. 최적화 알고리즘을 무엇을 선택해야 할지 모르겠다면, Adam을 선택하라는 말이 있을 정도로 다양한 학습 데이터에 대해 좋은 학습 성능을 보여주고 있다.

 

 

 

Adam도 역시 각 파라미터에 맞는 학습률을 계산해주며, Adadelta나 RMSprop과 같이 이전에 그래디언트가 얼마나 업데이트되었는지 그래디언트 제곱 합의 가중이동평균을 사용한다. 하지만, Adam은 여기에 하나 더 업데이트 상태를 저장하는 또 하나의 변수를 추가한다.

 

 

 

기존에는 그래디언트의 제곱합을 사용했다면, 이번에는 그래디언트 값 자체만을 사용해서 가중이동평균을 계산한 값을 사용한다. 수식으로는 아래와 같이 나타낼 수 있으며, 2번의 가중평균이 사용되므로 2개의 가중치값 $\beta_1$과 $\beta_2$ 가 필요하다.

 

 

\begin{aligned}m_t &= \beta_1 m_{t-1} + (1-\beta_1)g_t\\v_t &= \beta_2 v_{t-1} + (1-\beta_2)g_t^2\end{aligned}

 

 

여기서 주의해야 할 점은, $m_t$ 와 $v_t$ 가 각각 처음에 0으로 초기화되기 때문에 초반의 값이 0과 가까운 값을 갖게 된다. 이를 0에 편향되어있다고 표현하는데, Adam의 저자는 다음과 같이 이 문제를 해결하였다.

 

 

\begin{aligned}
\hat{m}_t &= \frac{m_t}{1 - \beta^t_1}\\
\hat{v}_t &= \frac{v_t}{1 - \beta^t_2}
\end{aligned}

 

 

새롭게 정의한 $\hat{m}_t$와 $\hat{v}_t$ 값을 사용하여 Adadelta와 RMSprop에서 봤던 식처럼 파라미터의 업데이트를 해주면 Adam의 수식이 완성된다. Adam의 저자는 초기에 $\beta_1$ 값을 0.9, $\beta_2$ 값을 0.999로, $\epsilon$은 $10^{-8}$로 설정할 것을 제안하였다. 

 

 

$$ \theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{\hat{v}_t} + \epsilon}\hat{m}_t $$

 

 

 

 


 

 

 

 

저자는 경사하강법 알고리즘에 대해서 알아본 이후, 각 알고리즘의 실제 학습이 어떻게 이루어지는지 2개의 사진을 가져와서 비교하였는데 결과가 상당히 흥미로웠다. 사진은 일반적인 목적함수 그래프 위에서 minimum을 찾아 어떻게 학습하는지 알려주는 모습 1개와 안장점(saddle point) 위에서 각 알고리즘들이 어떻게 이를 해결하는지 보여주었다.

 

 

 

출처: An overview of gradient descent optimization algorithms

 

 

먼저 첫 번째 사진은 손실 함수의 표면을 따라서 minimum 값을 찾아 나서는 경로를 보여준다. 각 알고리즘에 따라 찾는 경로가 모두 다른 것이 흥미롭게 느껴졌다. 파라미터에 맞게 학습률을 수정하면서 업데이트하는 Adadelta, Adagrad, RMSprop은 올바른 방향으로 곧장 나아갔고, 수렴 속도도 빠르게 나타났다. 반면에 Momentum과 NAG는 초반에 minimum과 거리가 있는 다른 곳으로 나아갔었다. 하지만 NAG는 초반에 잘못된 길로 들어섰다가 금방 알아차리고 다시 올바른 경로로 나아간 것을 확인할 수 있다.

 

 

 

두 번째 사진은 안장점위에서 파라미터를 업데이트하는 것을 보여준다. SGD와 Momentum, NAG는 다른 차원에서의 minimum을 향해 업데이트하는 것이 어려웠지만, Adagrad와 RMSprop은 안장점 위에서도 경로를 찾아 빠르게 나아가는 것을 확인할 수 있었다. 특히 Adaptive Learning 방법을 사용한 Adagrad, Adadelta, RMSprop, Adam 알고리즘이 이런 시나리오에서 가장 좋은 수렴성을 제공해주었다.

 

 

 


 

 

 

이후에 논문에서는 경사하강법이나 최적화 알고리즘을 더 좋은 방향으로 또는 더 빠르게 학습시킬 수 여러 가지 그 이외의 방법들을 소개하였다. 이 중에 대표적으로 아까 소개했던 SGD에서 샘플을 선택할 때 shuffle을 하는 것들이 왜 좋은지 그 이유와 결과에 대해서 소개하거나 Batch Normalization과 같은 다른 기법들을 소개하고 결론지으며 마무리한다.

Comments