본문 바로가기
처음부터 하는 딥러닝

[딥러닝 기초] 경사 하강법(Gradient descent)

by 빈이름 2023. 5. 9.

오늘은 경사 하강법에 대해서 알아보겠습니다.

 

딥러닝 모델의 학습은 경사 하강법(gradient descent)에 의해서 이뤄집니다. Gradient descent에 미분을 사용한다고 했었는데, 왜 미분을 이용하는지에 대해 알아보고, 가장 많이 쓰이는 gradient descent 방법인 Adam optimizer에 대해서 알아보도록 하겠습니다.

미분

위키에 따르면 미분(derivate, 도함수)의 정의는 "어떤 함수의 정의역 속 각 점에서 함숫값의 변화량과 독립 변숫값의 변화량 비의 극한 혹은 극한들로 치역이 구성되는 새로운 함수"라고 합니다. 어릴 적 배웠던 수학용어들에 대해서 생각이 안 날 수 있으니까 뜻을 하나하나 알아보겠습니다.

 

  • 정의역 : 함수의 입력값 $x$들의 집합
  • 치역 : 함수에 변수 $x$가 입력되었을 때의 출력값 $y$들의 집합

함수와 정의역과 치역

미분을 쉽게 설명하자면, 함수에서 $x$의 값이 변화했을 때 이 $x$ 값의 변화량과 $f(x)$값의 변화량의 비율을 말하는 것입니다.

예를 들어 $f(x)=x^2+3$이라는 함수의 미분을 생각해 보겠습니다. 입력값 $x$가 2에서 3으로 변화한다면 $x$의 변화량은 1이 됩니다. 이렇게 $x$의 값이 변화했을 때 함수의 결괏값은 7에서 12로 변화하게 되고, 함숫값의 변화량은 5라고 할 수 있습니다. 이 때 이 함수의 함숫값의 변화량과 독립 변숫값의 변화량의 비는 ${5\over 1}=5$가 됩니다.

 

극한은 말 그대로 변화량이 '극한'에 도달하는 것을 말합니다. $x$의 증가값이 1이 아니라 그보다 훨씬 작은, 말 그대로 극한에 다다를 정도로 작은 값(0에 가까운)이 증가했을 때를 말합니다. 변화량이 너무 작아서 점과 다를 바 없을 경우의 변화량의 비를 미분값이라 하고, 이런 점에서의 미분값들의 집합을 "미분"이라고 합니다.

미분은 변화율 dx와 dy의 비를 이용한다. 여기서 dx가 0에 가깝게 작아질 경우의 변화량의 비를 해당 점에서의 미분값이라고 한다.

Gradient descent

그렇다면 gradient descent에서 미분값을 사용하는 이유는 뭘까요? 딥러닝 모델의 학습을 다시 살펴보겠습니다.

 

딥러닝 학습에 사용되는 loss function을 $f(\theta)$라고 하겠습니다. 여기서 $\theta$는 모델의 파라미터를 나타냅니다.

Loss function에서의 미분값

Loss function의 목표는 loss 값을 최소화하는 것입니다. 만약 $f(\theta)$ 그래프가 위와 같이 생겼다고 가정해 봅시다. 이 때, 학습의 목표는 $f(\theta)$ 값이 optimal 지점에 다다르도록 하는 $\theta$값을 찾는 것입니다. 만약 현재 $\theta$값이 A라고 한다면, optimal 지점에 다다르기 위해선 $\theta$값이 감소해야 합니다.

 

여기서, 점 A에서의 미분값은 $lim_{(d\theta\to 0)}{df(\theta)\over d\theta}$가 됩니다. 여기서 $d\theta$와 $df(\theta)$의 값은 모두 양수이므로, 점 A에서의 미분값 역시 양수가 됩니다. 그렇기 때문에 $\theta$에서 loss function에 대한 $\theta$의 미분값(${df(\theta)\over d\theta}$)을 뺀다면, $\theta$값은 감소하게 됩니다!

 

$\theta_{t+1}=\theta_t-\alpha{df(x)\over dx}$, (미분값(${df(\theta)\over d\theta}$)이 양수이므로 $\theta$값은 감소한다.)

 

반대로 $\theta$값이 아래와 같이 B지점에 도달하더라도, 이 지점에서의 미분값이 음수이므로 $\theta$에서 미분값을 뺀 결과는 증가하게 됩니다.

$\theta$에서 미분값을 빼게 되면, optimal 지점으로 $\theta$값이 이동하게 된다.

즉, gradient descent에서 미분은 일종의 "방향" 역할을 한다는 것을 알 수 있습니다.

Learning rate

Learning rate에 대해서도 간단하게 짚어 보고 넘어가겠습니다. Learning rate는 말 그대로 학습이 진행되는 속도를 조절하는 상수입니다.

$$\theta_{t+1}=\theta_t-\alpha{df(\theta)\over d\theta}$$

만약 learning rate($\alpha$)가 커진다면 $\theta$는 해당 방향으로 크게 움직이게 되고, 작아진다면 작게 움직이게 될 것입니다.

Learning rate는 너무 커도, 너무 작아도 문제가 될 수 있습니다. 만약 learning rate가 너무 크다면 파라미터가 optimal 지점을 그냥 지나쳐 계속 수렴되지 못하는 문제가 발생할 수 있습니다.

Learning rate가 너무 클 경우, 1번 위치에서 2번 위치로, 3번 위치로 움직이며 점점 그래프의 optima 지점에서 멀어지게 된다.

반대로 learning rate가 너무 작다면 학습 속도도 느릴 뿐더러, local-optimal(sub-optimal)에 빠지게 될 우려가 있습니다. 

learning rate가 작을 경우 A지점에서 sub-optimal 지점을 벗어나지 못할 수 있다.

위 그림과 같이 sub-optimal 옆에 더 좋은 optimal 지점이 존재함에도 불구하고, learning rate가 작기 때문에 sub-optimal 지점을 벗어나지 못하고, 더 좋은 optimal 지점을 찾을 수 없게 되는 것입니다.

 

좋은 learning rate는 정해져 있지 않습니다. 실험을 통해서 직접 알아내거나, 논문의 모델을 구현하는 경우 논문의 수치를 그대로 사용하는 것이 방법입니다. Learning rate가 학습 성능에 미치는 영향이 생각보다 커서 정확도가 몇%씩 차이나기도 하고, learning rate를 잘못 설정해서 학습이 완전 잘못되버리는 경우도 많습니다. 여러가지 학습 관련 설정들 중에서도 이 learning rate만큼은 반드시 여러가지 실험해 보는 것을 추천드립니다.

SGD (배치 단위 학습)

처음 제시된 gradient descent 방식은, 데이터가 1000개 있다면 1000개의 loss를 모두 계산한 뒤에 하이퍼 파라미터를 한번에 업데이트 했습니다.(이를 batch gradient descent라고 합니다.) 그러나 이 방식은 데이터 수가 많아질수록 한 번 학습하는데 시간이 너무 오래 걸리고, 이 1000개의 데이터를 메모리에 할당하는 것도 무리가 있습니다. 그렇기 때문에 데이터를 '배치' 단위로 나눠서 학습하는 방식이 제시되었습니다. 배치 단위의 gradient descent 방식을 SGD(Stochastic Gradient Descent)라고 합니다.

  큰 배치 작은 배치
속도 빠름 느림
메모리 많이 차지함 적게 차지함
일반화 정도 높음 낮음

배치 크기가 클수록 학습은 빨라집니다. 이는 컴퓨터가 행렬 연산을 통해 데이터들을 병렬적으로 계산할 수 있기 때문입니다. 하지만 계산에 포함되는 데이터가 늘어나는만큼 차지하는 메모리 공간도 증가하게 됩니다. 따라서 컴퓨터 성능에 따라, 학습하고자 하는 데이터의 크기나 모델의 크기에 따라 배치 크기에 제약이 발생합니다.

 

배치 크기는 단순 속도 뿐만 아니라 모델의 성능에도 영향을 미칠 수 있습니다. 데이터를 적게 볼수록 모델이 '편향'될 수 있기 때문입니다. 모든 데이터에는 예외가 존재할 수 있습니다. 만약 배치 크기가 100이라면 100개 중에 하나 정도 예외가 껴있어도 모델은 이를 무시할 수 있습니다. 그러나 배치 크기가 4인데 여기에 예외가 껴있다면 모델은 이 예외에 영향을 크게 받겠죠.

 

Batch size는 leaning rate에 비해 모델 성능에 미치는 영향이 작기 때문에 보통은 성능 보다는 속도를 위해 내 GPU가 감당 가능한 최대한의 배치 크기를 활용합니다.

Adam

모델의 파라미터는 보통 굉장히 많습니다. 그러나 이 파라미터들이 모두 같은 중요도를 갖지는 않을 것입니다. 어떤 파라미터는 더 중요하거나 덜 중요할 수도 있고, 어떤 파라미터는 학습이 많이 필요할 수도 있습니다. 그러나 SGD는 모든 파라미터에 초기에 설정한 learning rate가 일괄적으로 적용되고 변하지 않습니다. 이로 인해서 학습이 진행될수록 gradient가 점점 작아지는 문제가 발생합니다. 이런 문제를 gradient vanishing 또는 sparse gradient 라고 합니다.

 

이런 문제를 해결하기 위해 학습 속도에 관성(momentum)을 적용하는 방법들이 제시되었습니다. 관성에 따라 학습이 많이 이뤄진 파라미터는 learning rate가 작아지도록, 학습이 적게 이뤄진 파라미터는 learning rate가 커지도록 하여 파라미터마다 더 특화된 학습을 할 수 있도록 하는 것입니다.

 

1. Adaptive Gradient Algorithm(AdaGrad)

 

$$\theta_{t+1}=\theta_t-\alpha\cdot {g_t\over \sqrt{\Sigma^t_{i=1}g^2_t}} $$

AdaGrad는 현 step에서의 gradient 값($g_t$)을 현 step까지의 gradient 값들($\sqrt{\Sigma^t_{i=1}g^2_t}$)로 나눠줍니다. 이로 인해 이전 step까지의 gradient 값이 컸을 경우 현 step의 gradient 값은 작아지고(gradient의 분모가 커지므로), 반대로 이전 step까지의 gradient 값이 작을 경우 현 step의 gradient 값은 커지게 됩니다.

 

2. Root Mean Square Propagation(RMSProp)

 

$$v_t=\beta\cdot v_{t-1}+(1-\beta)\cdot g_t^2 \\ \theta_{t+1}=\theta_t-\alpha\cdot{g_t\over\sqrt{v_t}+\epsilon}$$

AdaGrad는 이전 step까지의 gradient값들을 그대로 더하다 보니 학습이 진행될수록 gradient의 분모가($\sqrt{\Sigma^t_{i=1}g^2_t}$) 너무 커지는 문제가 발생합니다. 이로 인해 gradient 값이 너무 작아지면서 gradient vanishing 문제가 그대로 발생하게 되죠.

RMSProp은 이를 보완하기 위해 관성 $v_t$를 이용합니다. $v_t$의 $\beta$는 0에서 1사이의 값을 갖는 상수로, 현재 step 까지의 gradient 값의 크기를 줄여주는 역할을 합니다. 이를 통해 분모의 크기를 줄여주기 때문에 AdaGrad보다 gradient vanishing을 방지할 수 있고, 학습을 더 많이 진행할 수 있습니다. $\epsilon$은 분모가 0이 되는 것을 막기 위한 상수입니다.

 

3. Adam

 

일반적으로 가장 성능이 좋은 Adam은 AdaGrad와 RMSProp의 발전된 버전이라고 볼 수 있습니다. Adam의 특징은 2개의 관성(momentum)을 사용한다는 것입니다. Gradient step은 아래와 같이 이뤄집니다.

 

1) momentum 계산.

      $m_t=\beta_1\cdot m_{t-1}+(1-\beta_1)\cdot g_t$

      $v_t=\beta_2\cdot v_{t-1}+(1-\beta_2)\cdot g_t^2$

 

2) momentum들의 편향성 개선.

      $\hat{m}_t=m_t/(1-\beta_1)$

      $\hat{v}_t=v_t/(1-\beta_2) $

 

3) 최종적으로 파라미터 갱신.

      $\theta_t=\theta_{t-1}-\alpha\cdot\hat{m}_t/(\sqrt{\hat{v}_t+\epsilon})$

 

Adam에는 4개의 상수가 필요합니다. 논문에서 추천하는 기본 세팅은 $\alpha$=0.001, $\beta_1$=0.9, $\beta_2$=0.999, $\epsilon$=1e-8입니다. (PyTorch, Tensorflow에서 제공하는 기본 세팅도 이와 같습니다.)

RMSProp에서는 분모에만 momentum을 적용했던 것과 달리 Adam은 분자에도 momentum을 적용한 것을 알 수 있습니다. 또 2)편향성 개선 과정을 통해 momentum이 0에 가까워지는 것을 막아줍니다. Adam은 이를 통해 RMSProp이나 AdaGrad의 성능을 보완한다고 합니다.

정리

여기까지 gradient descent에 대해 알아봤습니다. 내용을 정리하자면,

 

  • Gradient descent에서 미분은 파라미터가 loss function에서 수렴해야 할 "방향"을 알려주는 역할을 한다.
  • Learning rate는 gradient descent에 큰 영향을 미치며, 이는 모델의 성능에도 큰 영향을 준다.
  • SGD는 배치 단위의 gradient descent를 말한다.
  • Adam은 2개의 momentum을 활용하는 gradient descent 방식으로 일반적으로 제일 좋은 성능을 보여준다.

Adam이 일반적으로 좋은 성능을 보이지만 무조건 가장 좋다는 것은 아닙니다. 다양한 optimizer를 실험해 보는 것도 모델 성능 향상에 큰 도움을 줄 수 있으니 해보는 것도 좋습니다.

 

저는 지금까지 Adam을 많이 써왔지만 이게 뭔지에 대해서는 정확히 잘 몰랐습니다.(대체 beta는 뭐고 epsilon은 뭐지 하면서 써왔습니다.) 그래서 이번 기회에 공부해서 내용을 좀 더 작성해 봤는데요, 역시 지금까지 그랬듯 이를 전부 다 머릿속에 넣으려 하지 말고 '아 그렇구나' 하면서 넘어가셔도 무방합니다. 나중에 필요하면 다시 찾아보면 되니깐요. Adam에 대해 더 자세히 알고 싶은 분들을 위해 Adam의 논문과 소개글의 링크를 남기며 글을 마무리하겠습니다. 감사합니다.

 

Adam 소개 글 : https://machinelearningmastery.com/adam-optimization-algorithm-for-deep-learning/

Adam 논문 : https://arxiv.org/abs/1412.6980