딥 러닝에서 parameter는 크게 학습 이전에 결정하고 사용하는 값인 hyperparameter와 학습도중 조정되는 변수인 parameter가 있는데요. 이러한 parameter를 잘 조정하는 것은 학습 효율에 많은 영향을 끼치기 때문에 상당히 중요한 문제들 중 하나입니다.
Hyperparameter 값의 업데이트
Hyperparameter 값을 결정하는 최적의 방법론은 아직
알려지지 않았는데요. 아직까지는 감이나 운, 우연에 의존하는
방법이 많이 사용되고 있어요.
먼저 여러 선행논문을 참조해서 경험적으로 적당히 hyperparameter를 결정하는 게 많이
사용되고 있구요. 이를 좀 더 세분화하여 먼저 가능한 모형들과 가설들을 세워놓고 학습시켜 그 결과물을
보는 방식은 Grid Search 방식도 많이 사용되고 있어요.
다른 방법은 무작위로 탐색하는 것(Random search)인데요. 아직까지는 그렇게 효율적인 방법이 없어 랜덤 서치도 상당히 효율적인 방법 중 하나에 속합니다.
그 외에는 베이지안 최적화나 그 외의 이론적으로 정립된 모형들을 이용해 결정하는 방식이 있는데, 방법론이
정립된 분야에서는 랜덤 서치보다는 좀 더 낫다고 하네요.
파라미터 값의 업데이트 (Parameter updates)
수식적으로 Gradient 값은 역전파(backpropagation)으로 계산되고, 이는 파라미터값 업데이트를 위해 사용된다고 하네요. 이러한 업데이트를 효율적으로 수행하기 위한 몇 가지의 접근법들이 있어요.
바닐라(SGD) 업데이트 (Vanilla update - SGD). 가장 간단한
업데이트 형태는 Gradient의 반대방향으로 파라미터를 업데이트하는 것인데요.
파라미터의 벡터를 x라 하고 Gradient를 dx라
쓰면…. 이렇게 되는데요.
# Vanilla update
x += - learning_rate *
dx
여기서 gradient는 보통 커지는 경향이 있으므로, 음수를 곱해서 loss를 감소시킨다고 하네요.
모멘텀 업데이트 (Momentum update)는, 이 방법은 최적화 문제(optimization problem)를 물리학적 관점에서 바라보는 데서 유래했는데요. 관성을 부여하기 위해 parameter에 직접 적용하는 게 아니라
속력변수 v 를 부여하여 이를 이용해 변화를 주는 방식을 사용한다고 go요.
# Momentum update
v = mu * v -
learning_rate * dx # integrate velocity
x += v # integrate position
Mu는 운동량(마찰 계수)이고
v를 지속적으로
감소시켜 수렴하게 하기 위한 방법 중 하나이며 일종의 hyperparameter입니다.(보통 초기값은 0.9로 한다고 하네요)
epoch에 따라 모멘텀의
크기를 조정한다면….
이를테면 시작할
때는 0.5의 모멘텀으로 시작하되 몇 번의 epoch을 지나면 0.99로 설정하는 방식으로, 시간이 지날수록 더욱 효율적으로 loss가 감소하게 할 수도 있다고 합니다.
Nesterov
모멘텀 (Nesterov Momentum)
momentum방식은 momentum과 gradient가 따로 합쳐지는 방식인데요.
이를 조금 개선한 Nestrov momentum은
이와는 조금 달리, 먼저 momentu을 이동했다고 먼저
계산한 뒤 그 자리에서 gradient를 다시 구해 이동하는 방식이라고 하네요.
Momentum 방식에서는 관성에 의하 잘못된
경향성이 오래 지속될 수도 있는데 반해, nestrov momentum에서는 이런 관성을 조금 줄일
수 있다고 해요.
# evaluate dx_ahead (the
gradient at x_ahead instead of at x)
x_ahead = x + mu *
v
v = mu * v -
learning_rate * dx_ahead
x += v
여기서 먼저
momentum방식에서 예견된 연산 부분이 x + mu *v의
식으로 먼저 계산되구, 이로 인해 위의 momentum 방식에
비해 변화가 좀 더 빠르게 반영된다고 하네요.
v_prev = v # back this up
v = mu * v -
learning_rate * dx # velocity update stays
the same
x += -mu * v_prev
+ (1 + mu) * v # position update changes
form
이 외에도 L-BFGS같은 2차미분을 이용한 최적화도
있는데, 복잡성과 연산효율 문제로 인해 잘 사용되지는 않는다고 하네요.
학습 속도 담금질 (Annealing the learning rate)
학습 속도를
조정하는 건 신경망의 훈련에 있어 중요한 부분들 중 하나인데요.
너무 빨리 줄이면
learning 과정이 최적값에 도달하지 못하고 너무 빨리 중단 될 우려가 있구요.
너무 늦게 줄이면
시간이 많이 소요될 수 있겠지요…
- 계단식 감소 (step decay): 몇 epoch마다 일정량만큼 학습 속도를 줄이는 것을 말하여, 5 epoch마다 반으로 줄이거나 20 epoch마다 1/10씩 줄이기도 한다고 하네요. 고정된 학습 속도로 검증오차(validation error)를 살펴보다가, 검증오차가 개선되지 않을 때마다 학습 속도를 감소시키는 방법을 쓰기도 한다고 하네요. 또한 제일 많이 활용되는 방법이기도 합니다.
- 지수적 감소 (exponential decay)
- 1/t 감소는 t의 역수를 곱해 일정하게 감소하게 하는 방법을 말해요.
파라미터별 데이터-맞춤 학습 속도 (Per-parameter
adaptive learning rates)
위의 SGD나 momentum방식들은 모든 파라미터에 같은 학습 속도를 적용한
것인데요. 최적화 효율성을 향상시키기 위해 이를 조금 개량하여 parameter마다
다른 학습 속도를 적용하기 위한 알고리즘들도 있습니다.
Adagrad의 기본 아이디어는
각각의 변수마다 step size를 다르게 설정해서 연산하는 방식인데요. 많이 변화한 변수들은 이미 최적의 값에 가까우므로 변화량을 작게 하고 적게 변화한 변수들은 step_size(dx)들을 크게 해서 변화량을 크게 하는 방식을 사용한다고 하네요.
# Assume the gradient dx
and parameter vector x
cache += dx**2
x += - learning_rate *
dx / (np.sqrt(cache) + eps)
위에서 변수
cache는 Gradient 벡터의 사이즈와 동일한 사이즈를
갖고 있으며 변수에 대해 웨이트값(dx**2)들을 저장합니다.
높은 Gradient값을 갖는 웨이트값(weight)들은 점점 실질적인 학습속도(effective learning rate)가 감소하고 / Gradient 값이
낮거나 업데이트가 거의 없는 웨이트값들은 실질 학습속도가 증가합니다.
제곱근(square root) 연산이 여기서 중요한 비중을 차지하는데요. 제곱근이
없다면 알고리즘의 성능이 많이 나빠진다고 하네요. 변수 eps는
분모가 너무 0에 가깝지 않도록 안정화 하는 역할을 하고 주로
1e-4에서 1e-8의 값이 할당된다고 해요.
Adagrad의 단점이 있다면, 딥러닝의 경우에는, 학습 속도가 단조적이라 너무 한 방향으로 급진적(aggressive)으로 나가거나, 혹은 학습을 너무 빨리 멈출 가능성도
있다고 합니다.
RMSprop.
RMSProp은 제프리 힌톤이 제안한 방법으로서, Adagrad의 단점을 해결하기 위한 방법이라고 하네요. Adagrad의 식에서 gradient의 제곱값을 더해 나가면서 구한 cache(웨이트들을 저장하는 부분)부분을 dx **2들의 합이 아니라 지수평균으로 바꾸어서 대체한 방법입니다.
cache = decay_rate *
cache + (1 - decay_rate) * dx**2
x += - learning_rate *
dx / (np.sqrt(cache) + eps)
여기서 decay_rate는 학습 속도를 급격하게 줄이지 않기 위한 hyperparameter이고
보통 [0.9, 0.99, 0.999] 중 하나의 값을 취한다고 하네요.
X +=업데이트는 Adagrad와 동등하지만, cache update 부분은 Adagrad와 조금 다른 구조로 구성되어 있어 급격한 학습속도 하락을 방지합니다.
Adadelta는 RMSprop의 마이너 변형판으로, cache를 구하는 방식은 RMSProp와 같으나 x += - learning_rate * dx /
(np.sqrt(cache) + eps)부분에서 dx를 그대로 사용하는 대신 dx의 변화값의 제곱을 사용하는 방식이라고 하네요.
Adam. Adam은 최근에 제안된
방법인데 RMSProp에 모멘텀(momentum)을 혼합한
것인데요. 이 방식에서는 Momentum 방식과 유사하게 지금까지 계산해온 기울기의 지수평균을 저장하며,
RMSProp과 유사하게 기울기의 제곱값의 지수평균을 저장합니다.
m = beta1*m + (1-beta1)*dx
v = beta2*v + (1-beta2)*(dx**2)
x += - learning_rate *
m / (np.sqrt(v) + eps)
업데이트는 RMSProp의 업데이트 방식과 같은데요.
노이즈가 껴있을
수도 있는 Gradient (dx)대신에 “안정화된” 버전인 m이 사용되었다는 점이 달라요.
논문에 따르면
추천되는 hyperparameter값들은 eps =
1e-8, beta1 = 0.9, beta2 = 0.999라고 하네요.
다만, Adam에서는 m과 v가
처음에 0으로 초기화되어 있기 때문에 학습의 초반부에서는 m, v가 0에 가깝게 bias 되어있을 것이라고 판단하여 이를 unbiased 하게 만들어주는 작업을 거친다고 하네요.
현대의 deep learning 연구에서 Adam은 가장 일반적으로 활용되는 parameter tuning 방법 중 하나에요.
댓글 없음:
댓글 쓰기
글에 대한 의문점이나 요청점, 남기고 싶은 댓글이 있으시면 남겨 주세요. 단 악성 및 스팸성 댓글일 경우 삭제 및 차단될 수 있습니다.
모든 댓글은 검토 후 게시됩니다.