[CS231n] 강의8. Training Neural Networks (3) Optimizer 리뷰
본 글은 2021년 4월에 강의한 스탠포드 대학의 “Convolutional Neural Networks for Visual Recognition” 2021년 강의를 듣고 정리한 내용입니다.
개인 공부 목적으로 작성되었으며, 설명이 맞지 않거나 글 오타가 있으면 알려주시길 바랍니다.
원본 링크 : cs231n.stanford.edu
한글 번역 링크 : aikorea.org - cs231n
강의 링크 : youtube - 2017 Spring (English)
Training Neural Networks
- 이전 섹션들에서는 레이어를 어떻게 쌓을지, 어떤 손실함수를 써야 하는지 등 정적인 부분을 배웠는데, 이번 섹션부터는 동적인 부분을 알아본다.
- Part2에서 배울 내용은 다음과 같다.
- Improve your training error
- (Fancier) Optimizers
- Learning rate schedules
- Improve your test error
- Regularization
- Choosing Hyperparameters
- Improve your training error
(Fancier) Optimizers
-
경사 하강법(Gradient Descent)에서는 가중치 $W$ 값에 대해서 그레이디언트의 반대 방향으로 step만큼 반복적으로 이동하여 손실함수가 최소가 되게 하는 가중치 $W$ 값을 찾는다.
# Vanilla Gradient Descent
while True:
weights_grad = evaluate_gradient(loss_fun, data, weights)
weights += - step_size * weights_grad
- 즉, 미니 배치 안에서 데이터 손실을 계산하고, 그레이디언트의 반대 방향을 이용해서 파라미터(가중치) 벡터를 업데이트 시켜준다.
- 하지만, SGD의 문제점들이 있다.
- Q. 손실이 한 방향으로 빠르게 변화고 다른 방향으로 천천히 변화하면 어떻게 될까?
- A. 얕은 차원을 따라 매우 느리게 진행되고, 가파른 방향을 따라 매우 흔들릴 것이다.
- 손실(loss)는 수직 방향의 가중치 변화에 더 민감하게 반응하여 지그재그 형태로 지점(point)를 찾아간다.
- 하지만, 수평방향의 가중치는 느리게 변하기 때문에 전체적으로 매우 느려지는 단점이 있다.
- 2번째 문제점으로 지역 최소점(local minima) 또는 안장 지점(saddle point)가 있다.
- local minima는 그레이디언트가 0이 되어 중간에 멈춰버리는 것이고,
- saddle point는 순간적으로 그레이디언트가 0에 가까운 지점에서 멈춰버리는 지점을 말한다.
- 보통 고차원에서는 saddle point가 많이 발생한다.
- 3번째 문제점으로, 그레이디언트는 각 미니배치에서 오는 것을 매번 업데이트하는데, 이때마다 정확하지 않고 노이즈가 발생할 수 있다는 것이다.
SGD + Momentum
- SGD의 정의는 다음과 같다.
-
$x_{t+1}=x_t-\alpha \nabla f(x_t)$
while True: dx = compute_gradient(x) x -= learning_rate * dx
-
- 모멘텀(Momentum)은 SGD에 일종의 가속도를 주는 것이다. 즉, 그레이디언트가 0인 지점이 나와도 모멘텀으로 인해 계속 나아갈 수 있게 해준다.
- SGD+Momentum 정의는 다음과 같다.
- $v_{t+1}=\rho v_t+\nabla f(x_t)$
- $x_{t+1}=x_t - \alpha v_{t+1}$
-
즉, 그레이디언트(gradient) 방향으로 가는 게 아니라, 속도(velocity) 방향으로 나아가게 된다.
vx = 0 while True: dx = compute_gradient(x) vx = rho * vx + dx x -= learning_rate * vx # vx = 속도(velocity) # rho = 마찰계수 # 너무 빠르게 가지 않게 마찰을 주는 개념 # 보통 rho를 0.9나 0.99로 준다.
- SGD+Momentum의 다른 대체 공식도 있다.
- $v_{t+1}=\rho v_t-\alpha \nabla f(x_t)$
-
$x_{t+1}=x_t+v_{t+1}$
vx = 0 while True: dx = compute_gradient(x) vx = rho * vx - learning_rate * dx x += vx
이미지출처 1
- 위 그림의 파란색 선같이 부드럽고 빠르게 이동하는 것을 볼 수 있다.
- local minima와 saddle point를 극복하여 계속 내려갈 수 있게 되었다.
Nesterov Momentum
- 위 그림에서 빨간색은 gradient 방향을, 초록색은 velocity 방향을 나타내고, 초록색은 actual step 방향(둘의 가중평균)을 나타낸다.
- Nesterov Momentum은 계산하는 순서를 바꾼 것이다.
- 속도를 사용하여 업데이트 해야하는 지점까지 간다.
- 그 지점에서 그레이디언트를 계산하고 속도와 혼합하여 실제 업데이트 방향을 파악한다.
- 위 식에서 파란색 부분 $x_t+ \rho v_t$는 미리 속도 방향을 예측해서 그레이디언트를 구한다는 의미다.
AdaGrad
- Adagrad(Adaptive Gradient)는 각 차원의 제곱합(sum of squares)에 기반한 그레이디언트의 요소별 스케일링을 추가한 것이다. 2
- 즉, 이전 업데이트의 크기를 기준으로 각 매개 변수에 대한 학습 속도를 조정하는 알고리즘이다.
- 업데이트 횟수가 적은 매개 변수에 대해 업데이트를 더 크게 확장
- 더 많이 업데이트되는 매개 변수에 대해 업데이트를 더 작게 조정
- 공식은 다음과 같다. 3
- $h\leftarrow h+\frac{\partial L}{\partial W}\odot \frac{\partial L}{\partial W}$
- $W\leftarrow W - \alpha \frac{1}{\sqrt{h}}\frac{\partial L}{\partial W}$
-
h에 이전 그레이디언트의 제곱들이 누적되어 더해지게 되는데, 매개변수를 업데이트할 때, $\frac{1}{\sqrt{h}}$를 통해 학습률을 조정한다.
grad_squared = 0 while True: dx = compute_gradient(x) grad_squared += dx * dx x -= learning_rate * dx / (np.sqrt(grad_squared) + 1e-7)
RMSProp
- 하지만, AdaGrad는 non-convex일 때 saddle point에 걸려 학습이 멈출 수도 있다. 즉, 업데이트가 안되는 현상이 일어날 수 있다.
- 또한, RMSProp는 극단적으로 학습률이 감소하는 것을 해결하기 위한 AdaGrad의 수정본이다.
-
이 문제점을 해결하기 위해 나온 것이 RMSProp이다.
grad_squared = 0 while True: dx = compute_gradient(x) grad_squared += decay_rate * grad_squared + (1 - decay_rate) * dx * dx x -= learning_rate * dx / (np.sqrt(grad_squared) + 1e-7)
- RMSProp는 지금까지의 모든 시간 단계에서 그레이디언트 제곱합을 저장되는 대신 그레이디언트 제곱합에 대한 decayed moving average를 사용한다.
- 보통, decay_rate는 0.9 또는 0.99를 사용한다.
- 그리고, 현재 그레이디언트 제곱은 (1-decay_rate)를 곱해주고 앞에 연산에 더해준다.
-
- 이를 통해 속도가 줄어드는 문제를 해결했다.
- 다음은 소개됐던 방법들을 비교한 그림이다.
이미지출처 2
Adam
- Adam은 모멘텀과 Ada 계열을 합친 것이다.
- Adam은 first moment와 second moment를 이용해서 이전의 정보를 유지시킨다.
-
코드는 다음과 같다.
first_moment = 0 second_moment = 0 while True: dx = compute_gradient(x) first_moment = beta1 * first_moment + (1 - beta1) * dx # Momentum 부분 second_moment = beta2 * second_moment + (1 - beta2) * dx *dx # AdaGrad/RMSProp 부분 x -= learning_rate * first_moment / (np.sqrt(second_moment) + 1e-7) # AdaGrad/RMSProp 부분
- 모멘텀(first_moment) 코드는 그레이디언트의 가중합이다.
- Ada(second_moment) 코드는 그레이디언트의 제곱을 이용하는 방법이다.
-
하지만, 초기 step에서 문제가 발생한다. 따라서 보정항을 추가한다.
first_moment = 0 second_moment = 0 while True: dx = compute_gradient(x) first_moment = beta1 * first_moment + (1 - beta1) * dx # Momentum 부분 second_moment = beta2 * second_moment + (1 - beta2) * dx *dx # AdaGrad/RMSProp 부분 first_unbias = first_moment / (1 - beta1**t) # Bias correction second_unbias = second_moment / (1 - beta2**t) x -= learning_rate * first_moment / (np.sqrt(second_moment) + 1e-7) # AdaGrad/RMSProp 부분 # beta1 = 0.9 # beta2 = 0.999 # learning_rate = 1e-3 or 5e-4
-
first moment와 second moment를 업데이트하고 현재 step에 맞는 적절한 편향(bias)를 추가해 값이 튀지 않게 방지시켜준다.
-
Summary
- 옵티마이저(optimzier)는 딥러닝에서 신경망이 빠르고 정확하게 학습하는 것을 목표로 한다.
- 다음은 optimizer의 전반적인 내용이다.
이미지출처 4
Learning rate schedules
- 위의 소개된 옵티마이저들 모두(all) 학습률(learning rate)를 가지고 있다.
- 학습률은 잠깐 뜸들여 방향을 찾는 것을 말한다.
- 하지만, 학습률의 하이퍼파라미터 값을 찾는 건 쉽지 않다.
- 시간의 경과에 따른 학습률 저하(learning rate decay)
- step decay : 몇 에포크마다 감소시킨다.
- exponential decay : $\alpha = \alpha_0 e^{-kt}$
- 1/t decay : $\alpha = \alpha_0 /(1+kt)$
- 방법으로 몇몇 고정된 지점에서 학습 속도를 줄여본다.
- 예시로, ResNet 경우, 에포크 30, 60, 90마다 lr에 0.1씩 곱한다.
- 위 그림에서 갑자기 뚝 떨어지는 이유는 lr을 변경했기 때문이다.
Learning Rate Decay
- learning rate decay 경우, 처음에 학습률을 높게 설정하고 학습이 진행될수록 점점 낮추는 걸 말한다.
-
다음은 각 함수에 대한 leraning rate 그래프이다.
- Cosine : $\alpha_t=\frac{1}{2}\alpha_0$ $(1+cos(t\pi /T))$
- $\alpha_0$ : 초기 학습률
- $\alpha_t$ : 에포크 t마다의 학습률
-
$T$ : 전체 에포크 수
-
Linear : $\alpha_t=\alpha_0(1-t/T)$
- Inverse sqrt : $\alpha_t=\alpha_0 / \sqrt{t}$
Detail
- 지금까지는 모두 1차 미분을 활용한 옵티마이저이다.
- 여기에 second-order optimization을 사용하는 방법이 있다.
- 이를 이용하면 minima에 잘 근접할 수 있다.
- 이계도함수로 구성된 행렬인 Hessian matrix로 계산한다. (역행렬 이용)
- 예를 들어 해시안 행렬의 고유값이
- 모두 양수이면 local minima
- 모두 음수이면 local maxima
- 양수와 음수가 동시에 있으면 saddle point 이다. 5
- second-order Taylor expansion
- $J(\theta)\approx J(\theta_0)+$ $(\theta-\theta_0)^T\nabla_{\theta}J(\theta_0)+$ $\frac{1}{2}(\theta-\theta_0)^TH(\theta-\theta_0)$
- 임계점을 해결함으로써 뉴런 매개변수 업데이트를 얻는다.
- $\theta^*=\theta_0-H^{-1}\nabla_{\theta}J(\theta_0)$
- BGFS : 헤시안을 invert하는 대신, 시간 경과에 따른 랭킹 1을 업데이트
- L-BFGS(lmitied memory BFGS) : full inversed Hessian을 생성/저장하지 않는다.
- 일반적으로, 전체 배치, 결정론적 모드에서 잘 작동한다.
- 하지만, 미니배치 설정에선 잘 전송이 되지 않는다.
Summary
- Momentum or RMSProp : ImageNet을 학습시키기에 충분하다.
- Adam은 대부분 경우 가장 좋은 선택이다.
- 감지(Detection), 분할(segementation) 등에 쓸 때 좋다.
- 하지만, full batch라면 L-BFGS도 좋은 선택이 될 수 있다.
- 지금까지 알아본 옵티마이저와 학습률은 training error를 줄이고, loss function을 최소화시키는 게 목적이다.
댓글남기기