[CS182] Lecture 4: Optimization
인공지능/CS182 스터디

[CS182] Lecture 4: Optimization

해당 글은 CS182: Deep Learning의 강의를 정리한 글입니다. 여기서 사용된 슬라이드 이미지의 권리는 강의 원작자에게 있습니다.

Neural network의 Loss surface

지금까지 모델을 학습시키는 optimizer로 Gradient descent를 사용했습니다. 이전 강의에서 살펴보았던 머신러닝 모델들은 loss surface가 단순해 Gradient descent으로도 충분히 global optima에 도달할 수 있었습니다.

 

하지만 앞으로 우리가 다룰 딥러닝 모델의 loss surface는 위의 그림처럼 매우 복잡합니다. 이러한 surface는 Gradient descent로는 global optima에 도달하기에는 수많은 방해물들이 존재합니다. 보통 딥러닝 모델에서 보이는 방해물들은 보통 세가지가 있습니다.

Optima 도달을 방해하는 세가지

Local Optima

gradient descent는 기울기가 0이 되는 순간 멈춥니다. 그러다보니 gradient descent로 local optima에 도달하게 되면 global optima에서 도달한 것 처럼 멈추게 됩니다. 그러다보니 성능이 아직 충분히 좋지 않음에도 모델 학습이 더이상 진행되지 않습니다.

하지만 local optima는 모델이 복잡해질수록 문제가 되지 않습니다. 모델이 복잡해질수록 local optima와 global optima의 loss 차이가 줄어들게 됩니다. 그렇다면 local optima에 도달하더라도 global optima와의 성능 차이가 크지 않아서 큰 문제는 발생하지 않게 됩니다.

Plateaus

Plateaus(고원)는 위의 그림처럼 기울기가 낮은 구간을 말합니다. Gradient descent는 해당 위치에서 구한 gradient 크기 만큼 움직이기 때문에 기울기가 낮다면 그만큼 움직이는 거리도 작아집니다. 만약 학습 도중에 이 구간에 빠지게 된다면 global optima를 향해 엄청 느린 속도로 움직여 학습이 지연됩니다. 이런 경우에는 learning rate를 높이거나 이후에 살펴볼 momentum을 적용한다면 plateaus를 빠르게 통과할 수 있습니다.

Saddle Points

Saddle points(안장점)는 이름처럼 안장과 같은 모습을 가지고 있습니다. 위의 그림처럼 어느 방향에서는 오목, 다른 방향에서는 볼록한 모습을 보입니다. 하지만 이 구간 또한 기울기가 0이기 때문에 학습이 Saddle point에서 멈출 수 있습니다. 특히 Saddle point의 경우 모델이 복잡할 수록 자주 보이기 때문에 특히 치명적인 방해물입니다.

 

그렇다면 Saddle points는 어떻게 피할 수 있을까요? 이는 Hassian 행렬을 구한다면 피할 수 있습니다. Hassian 행렬은 다변수함수의 2차 미분값을 말합니다. 일변수 함수에서 2차 미분을 통해 극대점과 극소점을 구분할 수 있는 것처럼, 머신러닝 모델이나 딥러닝 모델과 같은 다변수 함수는 2차 미분값인 Hassian 행렬을 통해 해당 위치가 극대점, 극소점, Saddle points 중 어떤 것인지 구분할 수 있습니다.

극대점, 극소점, Saddle point을 구분하기 위해서는 Hassian 행렬의 고유값을 구해야 합니다. 만약 모든 고유값이 양수면 극소점, 모두 음수면 극대점이 됩니다. 그리고 고유값에 양수와 음수 모두 존재한다면 해당 점은 Saddle point가 됩니다. 이렇게 Hassian 행렬의 고유값을 구해서 해당 위치가 saddle point라면 해당 점에서 조금 벗어나 학습을 계속 진행하면 됩니다.

여담으로 Saddle point를 구분하는 방법에서 왜 복잡한 모델일수록 saddle point가 많은지 추즉할 수 있습니다. 모델이 복잡해질 수록 파라미터도 커지고, Hassian 행렬도 커져 행렬의 고유값 수도 늘어나게 됩니다. 그렇다면 해당 점이 극대점이나 극소점이려면 고유값 모두 양수 또는 음수여야 합니다. 이는 고유값이 많을수록 불리하게 작용해 그 극점이 saddle point가 아닐 확률이 줄어들게 됩니다. 역으로 saddle point일 확률이 높아지기 때문에 복잡한 모델일수록 saddle point가 많을 확률이 높다고 생각할 수 있습니다.

진행방향 개선하기

위에서 알아본 대로 딥러닝 모델이 local optima, plateaus, saddle point 세가지에게 학습을 방해받게 됩니다. 이는 gradient descent가 기울기가 0인 구간을 향해 움직이기 때문에 발생합니다. 그렇다면 바로 global optima을 향할 수는 없을까요?

Newton's Method

 

Gradient descent처럼 점진적으로 global optima를 찾아내는 방법으로 Newton's method가 있습니다. Newton's method는Gradient descent처럼 미분값을 통해 파라미터를 업데이트합니다. 하지만 Newton's method는 1차 미분 뿐만 아니라 2차 미분값까지 사용합니다. 이덕분에  Newton's method는 Gradient descent보다 더 빠르게 global optima에 도달할 수 있습니다. 하지만 2차 미분값까지 구해야 하기 때문에 필요한 계산량이 많고, 수렴하지 못하는 경우도 있기 때문에 모델 학습에 적용하기에는 어렵습니다.

Momentum

 

Gradient Descent에서 모델 학습이 느려지는 문제 중 하나로 진동 문제가 있습니다. 진동 문제란 학습이 한 방향으로 쭉 이어지지 않고 그림처럼 지그재그로 움직이는 현상을 말합니다. 지그재그로 움직이다보니 전체적으로 global optima에 수렴하는 속도가 느려지게 됩니다.

진동 문제를 줄이기 위한 한가지 방법으로 현재 스탭의 그래디언트에 이전 그래디언트를 더하는 방식이 있습니다. 만약 이전 방향과 현재 방향이 비슷하다면 해당 방향으로 빠르게 움직이게 되고, 반대 방향이면 움직임이 둔화됩니다. 이러한 움직임이 관성과 비슷해서 Momentum 기법이라고도 불립니다.

Momentum 기법을 사용하면 plateaus같은 계곡에서 global optima에 빠르게 도달할 수 있습니다. 대신, 높은 위치에서 계곡의 바닥에 도달하는데 기존 방법보다 더 오래 걸리게 됩니다.

Gradient Scale

그래디언트를 계산하다보면 각 파라미터마다 나오는 기울기 값의 범위가 다를 수 있습니다. 이로 인해 어떤 파라미터는 민감하게, 다른 파라미터는 둔감하게 반응하게 됩니다. 이를 완화하기 위해 learning rate를 바꾸려도 해도 모두에 맞게 조절하기 어렵습니다.

이를 위해 각 파라미터마다 그래디언트 값을 scaling할 수 있습니다. 그래디언트 값을 scaling하면 각 파라미터의 영향을 비슷하게 맞출 수 있어 그래디언트 값으로 인한 영향력을 줄일 수 있습니다.

개선된 Optimizer

지금까지 알아본 방법을 Gradient descent에 적용해 복잡한 loss surface에서도 global optimum에 도달하는 다양한 optimzer들이 있습니다. 여러가지 optimizer가 존재하지만 여기서는 AdaGrad, RMSProp, Adam 세가지만 알아보겠습니다.

AdaGrad

AdaGrad는 Gradient Scale을 적용한 optimizer입니다. 여기서 scale 값 $s_k$를 구하기 위해 이전 그래디언트의 제곱값을 계속 누적합니다.

RMSProp

RMSProp은 AdaGrad에서 좀 더 발전된 형태로, 이전 그래디언트값과 현재 그래디언트값의 반영 비율$\beta$을 추가한 방식입니다. RMSProp은 AdaGrad보다 더 많은 상황에서 빠르게 global optima를 찾습니다.

Adam

Adam은 RMSProp에 Momentum을 결합한 optimizer입니다. 두가지 방식을 결합하다보니 learning rate $\alpha$, momentum에서 반영 비율 $\beta_1$, gradient scale에서 반영 비율 $\beta_2$ 세가지 하이퍼 파라미터를 정해야 합니다.

Gradient Descent 개선하기

기존 Gradient Descent의 문제점

Gradient descent의 또다른 문제점으로 학습 데이터셋이 커질수록 그래디언트를 구하는데 필요한 계산량이 많아진다는 점이 있습니다. Gradient descent는 모든 학습 데이터의 loss 값을 구한 후 이를 바탕으로 gradient를 구하게 됩니다. 그러다보니 한번 파라미터를 업데이트하는데 많은 시간이 걸리게 됩니다. 특히 데이터셋이 큰 딥러닝에서는 꽤나 치명적인 문제입니다.

Stochastic Gradient Descent

이를 해결할 간단한 방법으로 한번 업데이트 할 때마다 학습 데이터셋에서 일부만 뽑아 minibatch를 만들고 minibatch만 학습합니다. 이를 Stochastic Gradient Descent라고 부릅니다. 전체 데이터셋보다 작은 데이터만 계산하기 때문에 기존 Gradient descent보다 빠르게 업데이트되고, 계속 반복하다보면 Gradient Descent의 학습 결과와 비슷해지기 때문에 성능에도 문제가 없습니다.

다만 실제로는 랜덤으로 minibatch를 만들면 시간이 오래 걸리기 때문에 보통은 학습 데이터셋을 섞고 일정 크기만큼을 minibatch로 묶어 하나씩 사용합니다.

적절한 Learning Rate 설정

Learning rate 또한 학습 속도와 모델 성능에 큰 영향을 주기 때문에 learning rate를 적절한 값으로 설정해야 합니다. loss surface에서 빠르게 움직이려면 learning rate를 큰 값으로 설정하면 됩니다. 하지만 너무 크면 global optima가 있는 계곡에서 탈출해 되려 멀어질 수 있습니다. 이럴때는 learning rate를 줄이면 됩니다. 그러면 조금씩 움직일 수 있기 때문에 global optima에 더 가까이 다가갈 수 있습니다. 그렇다고 너무 줄이면 plateaus 같은 구간 때문에 global optima에 도달하는데 오랜 시간이 걸릴 수 있습니다.

Learning Rate Schedule

위에도 보다싶이 learning rate가 클때와 작을때 모두 장단점이 존재합니다. 그렇다면 필요할 때마다 learning rate를 바꾸면 더 빠르고 정확하게 모델을 학습할 수 있지 않을까요?

이를 위한 방법이 Learning rate schedule입니다. 처음에는 큰 learning rate 값으로 global optima에 빠르게 다다가고, 점점 learning rate를 줄여가면서 global optima에 가까지 다가가는 방법을 사용할 수 있습니다. 위의 그림처럼 특정 횟수마다 learning rate를 줄이면 실제로도 성능이 좋아지는 것을 볼 수 있습니다.

Learning rate schedule도 optimizer와의 상성이 존재합니다. Momentum을 적용한 Stochastic gradient descent에 learning rate schedule을 적용하면 더욱 효과가 높습니다. 하지만 Adam과 같이 Gradient scale을 사용한 optimizer는 이미 알고리즘에서 learning rate를 조절하는 효과가 있기 때문에 큰 효용을 얻을 수 없습니다.

Optimizer 하이퍼파라미터 튜닝

Gradient Descent에서 Stochastic Gradient Descent로 변경하면 minibatch의 크기를 정해줘야 합니다. batch 크기가 학습 결과에도 영향을 미치기 때문입니다. batch 크기를 크게 잡으면 안정된 그래디언트를 얻을 수 있싑나다. 하지만 커진 만큼 그래디언트를 계산하기 위한 계산량이 많아지고 전체적으로 학습 시간이 늘어납니다. 반대로 batch 크기를 작아지면 적은 계산량으로 파라미터를 빠르게 업데이트할 수 있지만 그만큼 그래디언트의 방향이 많이 튀게 되어 더 많이 움직여야 최저점에 도달할 수 있습니다.

또한 선택한 optimizer에서 사용하는 하이퍼 파라미터 또한 최적화 해야합니다. Adam과 같은 경우 learning rate를 포함한 세가지 하이퍼 파라미터가 있기 때문에 데이터를 잘 학습할 수 있는 하이퍼 파라미터를 찾아 적용해야 합니다.