본문 바로가기
Coursera 강의/Deep Learning

Optimization(최적화 알고리즘) : Mini-batch/Momentum/RMSprop/Adam

by 별준 2020. 10. 2.
해당 내용은 Coursera의 딥러닝 특화과정(Deep Learning Specialization)의 두 번째 강의 Improving Deep Neural Networks: Hyperparameter tuning, Regularization and Optimization를 듣고 정리한 내용입니다. (Week 2)

 

이번 주 학습내용은 다음과 같다.

1. Stochastic Gradient Descent(Mini-batch GD), Momentum, RMSProp, Adam과 같은 다양한 최적화 알고리즘에 대해서 알아본다. 

2. Random Mini-batch는 더 빠르게 수렴하도록 하고, 최적화를 향상시킨다.

3. Learning Rate를 감소시키면서 학습하는 것에 대해서 알아본다.

 

- Optimization Algorithms

이번에는 알고리즘이 더 빠르게 학습할 수 있도록 도와주는 최적화 알고리즘에 대해서 알아볼 것이다. 학습을 시킬 때, 우리는 여러가지 모델들을 시도해보아야하므로, 빨리 모델을 학습시키는 것이 중요하다. 

그래서 더 빠르게 학습시키게 도와주는 다양한 최적화 알고리즘에 대해서 알아보자.

[Mini-batch Gradient Descent]

일반적인 Gradient Descent는 Batch Gradient Descent라고 부르며, 파라미터를 업데이트할 때 모든 training examples m에 대해서 gradient를 계산한 다음에 파라미터를 업데이트하게 된다. 즉, GD를 진행하기 전에 전처리 과정(Gradient 계산)이 필요하고, m이 매우 커질수록 느려지게 된다.(물론 벡터화를 통해서 꽤 효율적으로 계산할 수는 있지만)

그래서 모든 training example m에 대해서가 아니라, 중간에 파라미터를 업데이트한다면, 훨씬 더 빠르게 알고리즘을 진행할 수 있을 것이다. 

training example을 mini-batch라고 부르는 baby-training set들로 나눈다고 생각해보자.

m = 5,000,000인 training set이 있다고 할 때, 각각 1000개의 example을 같도록 나눈다. 

새로운 표기법이 등장하는데, 1000개의 examples로 묶은 set를 중괄호를 사용해서 \(x^{\{1\}}\)로 표현하고, 그 다음 set를 \(x^{\{2\}}\)로 표현한다. 이렇게 각각의 mini-batch들이 1000개의 example들을 가지게 되면, 이 mini-batch들은 총 5,000개가 된다. 최종적으로 \(x^{\{5,000\}}\)가 된다. Y에 대해서 동일하게 나누어주어야 한다.

 

따라서 각각의 X(\(n_x\), m)의 mini-batch들은 (\(n_x\), 1000)의 dimension을 갖게되고, Y(1, m)은 (1, 1000)의 dimension을 갖게된다.

정리하면 mini-batch t : \(X^{\{t\}}, Y^{\{t\}}\) 이며, t는 mini-batch의 index이다.

 

여기서 batch는 모든 example들에 대해서 한 번에 처리하는 우리가 알고 있는 일반적인 Gradient Descent를 의미하며, mini-batch GD는 mini-batch를 한번에 처리해서 파라미터를 업데이트 한다는 것을 의미한다.

 

mini-batch gradient descent의 알고리즘은 간단하다. mini-batch의 size만큼의 example에 대해서 GD를 진행하면 된다.


for t = 1, ..., 5000 {

    Forward Propagation on \(X^{\{t\}}\)

        \(Z^{[1]} = W^{[1]}X^{\{t\}} + b^{[1]}\)

        \(A^{[1]} = g^{[1]}(Z^{[1]})\)

        ...

        \(A^{[L]} = g^{[L]}(Z^{[L]})\)

    Compute Cost \(J^{\{t\}} = \frac{1}{1000}\sum_{i = 1}^{L}\mathscr{L}(\hat{y}^{(i)}, y^{(i)}) + \frac{\lambda}{2\cdot 1000}\sum_{l} \| W^{[l]} \|_F^2\)  (for \({\color{red}X^{\{t\}}, Y^{\{t\}}}\))

    Backward Propagation to compute gradient expect to \(J^{\{t\}}\) (using \(X^{\{t\}}, Y^{\{t\}}\))

    \(W^{[l]} = W^{[l]} - \alpha dW^{[l]}, b^{[l]} = b^{[l]} - \alpha db^{[l]}\)

    }


여기서 한번의 for문 진행을 '1 epoch'라고 하며, 여기서는 한 번의 Gradient Descent에서 총 5000 epoch를 진행한다. 

따라서 전체 iteration을 위한 또 하나의 for loop가 필요하다.

 

대체로 m이 매우 클 때, mini-batch는 batch보다 훨씬 빠르게 진행된다.

mini-batch는 전체 데이터를 나누어서 훨씬 더 빠르게, 자주 업데이트하는 방법이다. 그리고 전체 데이터를 mini-batch size만큼 나누게 되면, 그만큼 계산량이 줄어들어서 더 빠르게 파라미터를 업데이트할 수 있어서, 이론상 mini-batch size배 만큼 더 빠른 학습이 가능하다.

 

[Understanding mini-batch gradient descent]

이번에는 mini-batch를 GD에 도입하는 방법과 역할, 그리고 왜 잘 동작하는지 이해하는 시간을 갖도록 하겠다. 

전체 training set에서 GD를 진행하면 우리는 매 반복마다 Cost가 계속 감소할 것을 기대한다. 만약 한 번의 iteration에서 Cost가 증가한다면, 어딘가 문제가 발생했다는 것을 의미한다. 아마 learning rate가 매우 큰 경우에 이러한 현상이 발생할 수 있다.

 

하지만, mini-batch gradient descent의 경우에는 매 반복마다 \(X^{\{t\}}, Y^{\{t\}}\)를 처리하게 되는데, 이 값들을 통해서 \(J^{\{t\}}\)를 구하게 되고, 매 반복마다 다른 training set에서 학습을 진행하는 것과 동일한 것이다. 이렇게 학습을 진행하게 되면 Cost 함수는 아래와 같이 noisy한 모습을 보게될 것이다.

mini-batch GD에서 우리가 선택해야하는 파라미터 중에 하나는 바로 mini-batch의 size이다.

만약 mini-batch size가 m인 경우에는 단순 batch GD를 의미한다.

그리고 mini-batch size가 1인 경우에는 Stochastic Gradient Descent(확률적 경사하강법)이라고 하는데, 각각의 example하나가 mini-batch가 되는 것이다.

이 두 가지의 경우에서 최적의 값을 찾아가는 모습을 보면 아래와 같다. 파란색이 batch GD이고, 보라색이 Stochastic GD를 나타낸다.

실제로 우리가 사용하는 mini-batch size는 1과 m사이의 값이 될 것이다. 

mini-batch size를 m으로 설정한다면, 매 iteration마다 아주 많은 training sets을 처리하게 되고, m이 너무 크다면 긴 시간이 소요된다. 만약 m이 작다면 batch GD를 그냥 사용해도 괜찮다.

반대로 mini-batch size를 1로 설정한다면, 1개의 example만 처리해도 파라미터를 업데이트할 수 있다는 점에서 괜찮다. noise가 많이 발생할 수도 있지만, 더 작은 값의 learning rate를 사용해서 개선시키거나 감소시킬 수 있다. 하지만, Stochastic GD는 각각의 sample을 처리한다는 점에서 벡터화의 효율을 잃어버리기 때문에 벡터화를 통한 빠른 계산 속도를 잃는다는 단점이 있다.

 

그러므로 실제로 가장 잘 동작하는 것은 mini-batch size가 너무 크거나 작지 않은 경우이다. 실제로 가장 빠른 학습 속도를 보여주며, 이러한 경우에 2가지 부분에서 좋은 점이 있다.

1. Stochastic GD와 비교해서 벡터화를 통한 속도를 잃지 않는다.(1000개씩 처리하는 것이 하나씩 처리하는 것보다 빠름)

2. 전체 training set m을 처리하기까지 기다릴 필요없이 파라미터를 업데이트(GD 수행)할 수 있다. (한 번의 iteration으로 5000 epoch의 GD step을 수행)

적절한 mini-batch size를 선택한다면, 최적값을 찾아갈 때에 다음과 같이 진행된다.

매 GD step에서 최소값을 향한다는 보장은 없지만, 전체적인 과정에서 최소값을 향해 진행하는 경향이 있다. 만약 변동이 너무 크다면 언제든지 learning rate를 감소시켜서 개선할 수 있다.

 

mini-batch size가 1~m사이의 값이면 어떻게 그 값을 선택할 수 있을까?

가이드라인은 다음과 같다.

1. training set의 크기가 작다면, 그냥 batch GD를 사용한다. m의 크기가 작다면 mini-batch GD가 의미가 없다.

(n <= 2000)

2. m이 충분히 크다면, mini-batch size는 64 ~ 512가 보편적이다. 64, 128, 256, 512 이렇게 보편적으로 사용되는데, 이것은 컴퓨터 메모리의 layout과 접근방식에 따라서 달라지고, 2의 지수값을 가질 때, 더 빨리 실행된다.

(\(2^n\)으로 선택, 만약 1000이라면 1024를 권장)

3. 모든 mini-batch \(X^{\{t\}}, Y^{\{t\}}\)가 CPU, GPU memory에 있도록 한다. 이것은 application이나 training sample의 크기에 따라 변할 수 있지만, CPU/GPU에 들어가지 않는 mini-batch를 처리하는 경우에 성능이 저하되고, 더 악화되는 것을 볼 수 있다.

 

mini-batch size가 또 하나의 hyper parameter이며, 2의 지수값을 몇개 시도해보고, 알고리즘을 가장 효율적으로 만들어주는 최적의 한 가지 값을 선택하면 된다. 

 

다음으로 훨씬 더 효율적인 알고리즘에 대해서 알아볼텐데, 알고리즘을 알아보기전에 필요한 수학적 내용을 먼저 알아보고 알고리즘에 대해서 알아보도록 하겠다.

 

[Exponentially Weighted Averages]

Exponentially Weighted Averages(지수 가중 평균)는 통계학에서는 Exponentially (Weighted) Moving Averages : 지수(가중)이동 평균 (EMA)라고 불리며, 간단히 EMA라고 언급하도록 하겠다.

 

1년간의 런던 날씨 예제를 보면서 EMA를 설명해보도록 하겠다.

1년간의 런던 날씨를 표로 나타내면 오른쪽과 같이 나타낼 수 있다. 정형화되어 있지 않고, 모든 날씨데이터를 모두 나타내어서 noisy하게 보이는데, 날씨 변화 trend를 구하고 싶은 경우 local평균 또는 온도에 대한 이동 평균값을 구하기 위해서는 아래와 같이 구하면 된다.

\[\begin{align*} V_0 &= 0 \\ V_1 &= 0.9V_0 + 0.1\theta_1 \\ V_2 &= 0.9V_1 + 0.1\theta_2 \\ V_3 &= 0.9V_2 + 0.1\theta_3 \\ \vdots \\ V_t &= 0.9V_{t-1} + 0.1\theta_t \end{align*}\]

이렇게 구하면, 다음과 같이 빨간색 그래프로 나타낼 수 있고, 각 days의 온도를 moving average로 나타낸 EMA을 구할 수 있다.

위 공식을 다시 살펴보면서, 우리는 0.9를 \(\beta\)로 변경해서 나타내면 다음과 같이 나타낼 수 있다.

\[V_t = \beta V_{t-1} + (1 - \beta)\theta_t\]

여기서 \(V_t\)는 대략적으로 \(\frac{1}{1 - \beta}\) days의 평균 기온이 된다.

즉, \(\beta = 0.9\)는 10일 동안의 평균 기온과 비슷하다고 보면 된다. 빨간색의 그래프로 나타낸 것이다.

만약 \(\beta = 0.98\)로 지정다면 지난 50일간의 평균 기온과 비슷하다고 보면 된다. 그래프로 나타내면 초록색 라인이 된다.

만약 \(\beta = 0.5\)라면 2일간의 평균 기온이기 때문에 아래 노란색 그래프처럼 매우 noisy한 결과를 얻을 것이고, outlier에 취약하게 된다. 하지만 기온이 변하는 것을 더 빨리 반영시켜준다.

여기까지가 기본적으로 EMA를 구하는 방법이고, EMA가 구체적으로 어떤 역할을 하는지 살펴보도록 하자.

 

[Understanding Exponentially Weighted Averages]

 

\[v_t = \beta v_{t-1} + (1 - \beta)\theta_t\]

위 식에서 beta의 값을 0.9, 0.98, 0.5로 설정했을 때, 위와 같은 빨간색/초록색/노란색 그래프를 얻을 수 있었는데, 조금 더 수학적으로 일별 평균 기온을 어떻게 산출하는지 살펴보도록 하자.

\(V_{100}\)이 실제로 어떤 의미인지 살펴보기 위해서, 식을 나열해보면 다음과 같이 계산이 된다.

\[V_{100} = 0.1\theta_{100} + 0.1\times0.9\theta_{99} + 0.1(0.9)^2\theta_{98} + 0.1(0.9)^3\theta_{97} + \cdots\]

즉, 일별 기온을 기하급수적으로 감소하는 함수에 곱해서 더하는 것이다(아래 두 그래프의 곱의 합).

이런 점 때문에 Exponentally weighted average라고 불린다. 

여기서 0.9의 10승을 하게 되면 그 값이 0.35정도가 되는데, 이 값은 대략 \(\frac{1}{e}\)이다. 다시 말해서, 지수 그래프가 3분의1 정도로 감소하는데 약 10일 정도가 소요되고, beta가 0.9인 경우에 직전 10일간의 기온만 집중하여 지수 가중 평균을 구하는 것과 같다.

일반적으로 엡실론을 사용해서 \((1 - \epsilon)^{\frac{1}{\epsilon}} = \frac{1}{e}\)로 나타내며, beta가 0.9였다면, 엡실론의 값은 0.1일 것이다.

반면 beta의 값이 0.98이라고 한다면 0.98의 50승이면 대략 \(\frac{1}{e}\)와 비슷한 값이 되고, 이 값은 50일간의 대략적인 평균치라고 보면 된다. 대략적인 평균 일수를 나타낸 것이기 때문에 정식 수학적 표현은 아니다.

 

다음으로 이것을 어떻게 구하는 지 알아보도록 하자.

아까 살펴보았겠지만 \(v_0\)은 0으로 초기화하고, 그 다음에 첫째날의 \(v_1\)을 구하고 다음에 \(v_2\)를 구하게 된다. 

구현을 하게 되면, 오른쪽과 같이 구현될 수 있는데 우리는 하나의 \(v_\theta\)를 가지고 갱신하면서 EMA를 구할 수 있다. 기본적으로 단 한 줄의 코드로 단 하나의 값만 메모리에 저장하면 되기 때문에 아주 적은 양의 메모리가 사용되고, 효율성이 높은 것이 장점이다.

하지만, 위 공식은 정확한 평균 계산 방식은 아니다. 정확한 평균은 최근 10일이나 50일의 기온을 더하고 10이나 50으로 나누면 더 좋은 추정치를 얻을 수 있지만, 이 방법은 그 동안의 기온을 보관하고 더하려면 더 많은 메모리가 필요하고 구현도 더 복잡하고 연산의 부담도 커지게 되는 단점이 있다. 

이러한 이유 때문에, 머신러닝에서 EMA가 많이 사용된다. 

 

[Bias Correction in exponentially weighted averages]

방금까지 EMA를 구현하는 방법에 대해서 배웠는데, 여기에 bias correction(바이어스 보정)이라고 하는 세부적인 테크닉이 있다. 이 방법은 EMA를 조금 더 정확하게 계산할 수 있도록 해준다. 

이전에 beta값이 0.9(빨간색)과 0.98(초록색)인 그래프를 보았는데, 실제로는 위와 같은 그래프가 나오지는 않는다.

beta가 0.98일 경우에 실제로는 보라색과 같은 그래프를 갖게 된다.

보다시피, 보라색 그래프는 매우 낮은 곳에서 시작을 한다. 

우리가 EMA를 구할 때 \(v_0 = 0\)으로 초기화를 하고 진행했다.

따라서 \(v_1 = 0.98v_0 + 0.02\theta_1\)을 계산할 때, 0.98은 무시가 된다.

\(v_1\)은 그냥 \(0.02\theta_1\)이 되는 것이고, 예를 들어서, 화씨 40도인 경우에 \(v_1\)은 0.02x40으로 8이 되어서 훨씬 더 작은 값이 나오게 된다. 첫째날 온도로는 좋은 평균치가 아니고, 그 다음날도 마찬가지가 될 것이다.

이렇게 특히 초반 부분에 대해서는 좋은 평균치가 아니게 되는데, 이런 평균치를 보완해주기 위한 방법이 Bias Correction이다. 

이 방법은 \(v_t\) 대신에 \(\frac{v_t}{1 - \beta^t}\)를 사용하는 것이다.

예를 들어서, t = 2일 때를 살펴보면 다음과 같다.

이렇게 초기 EMA값들을 \(1-\beta^t\)로 보정해주게 되고, t값이 충분이 커지면 \(\beta_t\)는 0으로 수렴하게 되고 bias correction의 영향은 사라지게 된다. 이 방법을 통해서 초반부 EMA 값을 보정해주고 보라색 그래프가 초록색 그래프에 맞춰 들어가도록 해준다. 

머신러닝에서는 EMA를 구현할 때, Bias Correction을 보통 신경쓰지 않고, 적용하지 않는다. bias된 평균치가 구해지는 초기구간을 기다리거나, bias된 구간부터 시작해도 되기 때문이다. bias correction은 더 좋은 평균치를 일찍 구하는데 도움이 된다.

 

이렇게 EMA와 bias correction을 알아보았고, 이제 이 내용을 바탕으로 더 좋은 최적화 알고리즘에 대해서 알아보도록 하자.

 

[Gradient Descent with momentum]

여기 Momentum 또는 Gradient Descent with momentum이라고 불리는 알고리즘이 있다. 이 알고리즘은 일반적인 GD보다 거의 항상 더 빠르게 동작한다. 

이 알고리즘의 기본 아이디어는 GD의 EMA를 구하고, 이 값을 이용해서 파라미터 weight를 업데이트하는 것이다.

위와 같은 Cost Function을 최적화시키려고 한다고 할 때, GD나 mini-batch GD를 사용하면 파란색 그래프처럼 빨간색의 최소값을 향해 왔다갔다 진동을 하면서 접근하게 된다. 이렇게 왔다갔다하는 진동폭이 GD를 느리게 한다. 만약 훨씬 더 큰 Learning rate를 사용하는 경우에는 보라색처럼 발산할 수도 있다.

이렇게 진동하는 폭을 감소시키기 위해서 우리는 세로축에서는 slower learning, 가로축에 대해서는 faster learning을 원할 것이다. 이것은 GD with momentum을 통해서 감소시킬 수 있다.

 

momentum 알고리즘은 다음과 같다. layer를 나타내는 위첨자 [l]은 생략하였다.


On iteration t:

    Compute dW, db (on current mini-batch)

    \(V_{dW} = \beta V_{dW} + (1 - \beta)dW\)

    \(V_{db} = \beta V_{db} + (1 - \beta)db\)

    \(W = W - \alpha V_{dW}\)

    \(b = b - \alpha V_{db}\)


과정을 설명하자면, 현재의 mini-batch에서 dW와 dB를 구한다. 그 다음에는 dW와 dB에 대해서 EMA를 구하고, 이렇게 구한 EMA를 가지고 W와 b 파라미터를 업데이트한다. 이 과정을 통해서 Gradient Descent를 더욱 smooth하게 해주게 된다. 결과적으로 세로축의 변동 평균은 거의 0이되고, 가로축의 변동 평균이 꽤 큰 값이 되어서, 아래와 같이 빨간색 그래프처럼 최소값을 향해서 접근하게 된다.

(알고리즘에서 dW와 db는 가속도의 역할을 하고, \(V_{dW}, V_{db}\)는 속도의 역할을 하게 되는 것이다.)

 

Momentum은 이전 Step에서 구한 dW와 db를 가지고 업데이트되는 것이 아니라, 이전 iteration들의 dW와 db의 평균치를 가지고 업데이트되는 것이다.

 

위와 같이 정리할 수 있고, 여기서 Hyperparameter는 \(\alpha, \beta\) 2가지이다. 보통 \(\beta\)의 값은 0.9가 default이며, 이것은 지난 10번의 Gradient Descent의 평균치를 의미한다.

그리고 bias correction을 적용할 수도 있는데, 실제로 잘 사용되지는 않는다. 단지 10번의 iteration 이후에는 워밍업이 되어서 더이상 bias correction을 적용할 필요가 없기 때문에 신경쓰지 않는다.

 

그리고, \(v_{dW}\)는 dW와 동일한 dimenstion을 갖고, \(v_{db}\)는 db와 동일한 dimenstion을 갖는다.

 

추가적으로 논문을 살펴보면 \((1 - \beta)\)가 생략되어서 나타나기도 한다.

\(v_{dW} = \beta v_{dW} + dW\)로 나타낸다. 

이런 경우에는 \(\alpha\)값이 그에 상응하는 값으로 setting되어야 하는데, \(\alpha\)는 \(v_{dW}, v_{db}\)의 scaling에도 영향을 주기 때문에 retune해야 할 수도 있어서, 주로 생략되지 않은 공식을 더 선호한다.

 

[RMSProp]

또 다른 최적화 알고리즘인 RMSprop라는 알고리즘이 있다. 이 알고리즘은 root mean square propagation의 약자인데, 이 방법을 사용해서 GD의 속도를 증가시킬 수 있다.

이해를 돕기 위해서 세로축을 파라미터 b라고 하고 가로축을 파라미터 w이라고 할 때, 우리는 세로축은 더 느리고 가로축은 더 빠르게 학습하기를 원한다.

이때, RMSprop 알고리즘은 다음과 같다.

RMSprop 알고리즘은 현재 mini-batch에 대해서 dW, db를 구하고, 이번에는 \(V_{dW}\)가 아닌 \(S_{dW}\) 표기를 사용해서 구하게 되는데, momentum과 유사하지만 dW와 db를 제곱해서 \(S_{dW}, S_{db}\)를 구한다. 이것은 EMA의 제곱 평균을 유지하는 것을 의미하고, 이렇게 구한  \(S_{dW}, S_{db}\)를 가지고 파라미터를 아래와 같이 업데이트하게 된다.

\[W := W - \alpha \frac{dW}{\sqrt{S_{dW}}}, b := b - \alpha \frac{db}{\sqrt{S_{db}}}\]

 

위 예시에서 가로방향은 w, 세로방향은 b 파라미터라고 했는데, 가로방향의 변동은 증가시키고 세로방향의 변동은 늦추고 싶기 때문에 \(S_{dW}\)는 비교적 작은 값이 되어야 하고, \(S_{db}\)는 비교적 큰 값이 되어야 한다. 실제 미분항을 보면, 가로방향에서보다 세로방향으로 더 큰 것을 볼 수 있고, 기울기는 b방향으로 더 크게 된다. 

이것은 가로방향의 변동폭은 무뎌지고, 세로방향의 변동폭은 커지도록 도와주게 되고, 아래와 초록색 그래프와 같은 모양으로 업데이트가 진행된다.

 

간단하게 나타내기 위해서 세로와 가로 방향을 각각 w와 b로 나타냈는데, 실제로는 아주 고차원의 파라미터 공간에 있고, 예를 들어서, 변동을 무디게 하려고 하는 세로 방향의 dimension은 \(w_1, w_2, w_{17}\)과 같은 파라미터 set의 합일 수 있고, 가로 방향의 dimension은 \(w_3, w_4\) 등등 파라미터 set의 합으로 나타내어 질 수도 있을 것이다. 

 

다음 강의에서 우리는 RMSprop와 momentum을 합친 알고리즘에 대해서 배울텐데, 파라미터가 중복되지 않도록 RMSprop에서 사용되는 하이퍼파라미터를 \(\beta_2\)라고 표기할 것이고, momentum의 하이퍼파라미터는 \(beta_1\)으로 표기할 것이다. 

그리고 RMSprop에서 \(\sqrt{S_{dW}}\)가 0에 가까워지면, 이 값이 나누어지면서 폭발적인 값을 가지게 된다. 이 값을 안정적이게 하기 위해서 실제로 RMSprop를 도입할 때, 분모에 아주 작은 엡실론 값을 더하게 된다. 어떤 값이 사용되어도 상관없지만, 이상적인 값은 \(10^{-8}\)이 기본값이다.

정리하면 다음과 같다.


RMSprop

On iteration t:

    Compute dW, db (on current mini-batch)

    \(S_{dW} = \beta_2 S_{dW} + (1 - \beta_2)dW^2\)

    \(S_{db} = \beta_2 S_{db} + (1 - \beta_2)db^2\)

    \(W = W - \alpha \frac{dW}{\sqrt{S_{dW}} + \epsilon}\)

    \(b = b - \alpha \frac{db}{\sqrt{S_{db}} + \epsilon}\)


이것이 RMSprop이며, momentum과 비슷하게 GD를 진행할 때의 진동을 감소시키는 효과가 있다. 이렇게 진동을 감소시키면, 더 큰 learning rate \(\alpha\)를 사용할 수 있고, 학습 알고리즘의 속도를 증가시킬 수 있다.

 

[Adam optimization algorithm]

Adam 알고리즘은 기본적으로 Momentum과 RMSprop를 합치는 것이라고 생각하면 된다. 

바로 어떻게 알고리즘이 진행되는지 살펴보자.


\(V_{dW} = 0, S_{dW} = 0, V_{db} = 0, S_{db} = 0\)

On iteration t:

    Compute dW, db using current mini-batch

    \(V_{dW} = \beta_1 V_{dW} + (1 - \beta_1)dW, V_{db} = \beta_1 V_{db} + (1 - \beta_1)db\) <- momentum

    \(S_{dW} = \beta_2 S_{dW} + (1 - \beta_2)dW^2, S_{db} = \beta_2 S_{db} + (1 - \beta_2)db^2\) <- RMSprop

    \(V_{dW}^{\text{corrected}} = \frac{V_{dW}}{(1 - \beta_1^t)}, V_{db}^{\text{corrected}} = \frac{V_{db}}{(1 - \beta_1^t)}\)

    \(S_{dW}^{\text{corrected}} = \frac{S_{dW}}{(1 - \beta_2^t)}, S_{db}^{\text{corrected}} = \frac{S_{db}}{(1 - \beta_2^t)}\) 

    \(W := W - \alpha \frac{V_{dW}^{\text{corrected}}}{\sqrt{S_{dW}^{\text{corrected}}} + \epsilon}, b := b - \alpha \frac{V_{db}^{\text{corrected}}}{\sqrt{S_{db}^{\text{corrected}}} + \epsilon}\)


momentum과 RMSprop를 각각 적용하면 되고, 추가적으로 Adam에서는 Bias Correction도 같이 진행하게 된다. 이렇게 구한 \(V_{dW}^{\text{corrected}}, V_{db}^{\text{corrected}}, S_{dW}^{\text{corrected}}, S_{db}^{\text{corrected}}\)를 가지고 W,b 파라미터를 위와 같이 업데이트하면 된다. 

이 알고리즘은 아주 다양한 NN Network에서 매우 효과가 있음이 증명되었다.

 

Adam 알고리즘에서는 몇 개의 hyperparameter가 있는데, learning rate인 \(\alpha\)는 여전히 중요하고 튜닝이 필요한 parameter이다. 따라서 다양한 범위의 값을 시도해서 어떤 값이 적합한 지 찾아야한다.

\(\beta_1\)의 기본 설정값은 0.9이고, \(\beta_2\)의 값은 Adam 논문에서는 0.999를 권장한다. 그리고 \(\epsilon\)의 값은 \(10^{-8}\)을 권장하지만, 이 값은 성능에 거의 영향이 없기 때문에 굳이 바꿀 필요는 없다. Adam 알고리즘을 사용할 때에는 보통 기본값을 많이 사용해서 \(\beta_1, \beta_2, \epsilon\)값을 잘 변경하지 않는다. 

\(\alpha\)의 값만 여러가지 값들을 시도해보고 어떤 값이 잘 동작하는지 확인하면 된다.

 

번외로 Adam은 Adaptive Moment Estimation의 약자이고, 대부분 그냥 Adam Optimization Algorithm이라고 부른다.

 

[Learning Rate Decay]

알고리즘을 더 빠르게 학습시킬 수 있는 방법 중의 하나는 Learning Rate를 시간이 지나면서 천천히 감소시키는 것이다. 

이것을 Learning rate decay라고 하며, 어떻게 구현할 수 있는지 살펴보자.

 

mini-batch GD를 사용한다고 가정해보면, 우리는 학습을 반복하면서 최소값으로 향하는 경향이 있지만, 정확하게 최소값으로 수렴하지는 않을 것이다.

위와 같이 최소값 주변을 멤돌면서 절대로 수렴하지 않을 것이다. 이것은 learning rate를 어떤 값으로 고정시켰고, noise가 존재하기 때문이다.

하지만 만약 learning rate \(\alpha\)를 천천히 감소시킨다면, 초기 반복에서는 비교적 큰 learning rate로 빠르게 학습이 가능할 것이다. 그리고, learning rate가 점점 감소하면서 step이 점차 작아질 것이다. 결국에는 최소값 부근에서 매우 좁은 범위를 왔다갔다할 것이다. 이전처럼 큰 learning rate를 가지고 최고값 주변을 왔다갔다하는 것과 비교하면 훨씬 나을 것이다.

Learning Rate Decay의 구현은 다음과 같다.

\[\alpha = \frac{1}{1 + \text{decay rate }\ast\text{ epoch-num}}\alpha_0\]

여기서 epoch는 각 mini-batch set에 대해서 진행하는 것을 의미하고, \(\alpha_0\)는 초기 learning rate이며, decay late와 \(\alpha_0\)는 hyperparameter가 된다. 

\(\alpha_0 = 0.2\) 그리고, decay rate = 1인 경우에는 아래와 같이 된다.

Epoch \(\alpha\)
1 0.1
2 0.067
3 0.05
4 0.04
... ...

만약 learning rate decay 방법을 사용한다면, 다양한 값으로 \(\alpha_0\)를 바꿔 보고, decay rate도 바꿔보면서 잘 동작하는 값을 선택해야한다.

위 수식 외에도 또 다른 방법들이 있는데, 다음과 같은 방법들이 있다.

- \(\alpha = 0.95^{\text{epoch num}}\alpha_0\) - exponentially decay

- \(\alpha = \frac{k}{\sqrt{\text{epoch num}}}\alpha_0\)

- discrete staircase

- Manual decay : 수작업으로 learning rate 설정(학습할 모델의 수가 적을 때 사용가능할 것)

 

지금까지 learning rate \(\alpha\)를 조정하는 다양한 방법들을 살펴보았는데, 어떤 것을 고를지는 걱정하지 않아도 될 것이다. 보통 learning rate decay는 나중에 시도해볼만한 것이고, 보통, \(\alpha\)를 어떤 값으로 정해서 잘 튜닝하는 것이 큰 효과가 있고, 나중에 필요할 때 learning rate decay를 사용하는 것을 권장한다.

 

다음으로 local optima와 saddle point

 

[The problem of local optima]

마지막으로는 Local optima와 saddle point에 대해서 알아보도록 하자.

초기 딥러닝 분야에서 최적화 알고리즘이 좋지 않은 local optima로 수렴하는 것에 대해서 매우 불안해했었지만, 딥러닝에 대해서 이론적인 부분이 발전하게 되면서 local optima에 대한 이해가 계속해서 변하고 있다. 

아래는 초기에 local optima에 대해서 걱정을 했을 때의 그림이다.

이런 경우에는 local optima가 매우 많이 존재하고, 학습 알고리즘이 global minimum이 아닌, local optima에 수렴하는 경우가 쉽게 발생할 것이다. 위와 같이 그래프를 그리게 되면, 다수의 local optima를 쉽게 만들 수 있다는 것을 발견할 수 있지만, 실제로는 이 그래프는 올바르지 않다. NN 네트워크를 새로 만들게 되면, 기울기가 0인 지점이 항상 이렇게 local optima인 것은 아니고, Cost Function에서 기울기가 0인 대부분의 지점들은 saddle point이다. 

즉, 대부분의 경우에는 위의 그래프처럼 saddle point가 되고, 실제로 local minimum이 되는 확률은 매우 낮다.

따라서, local optima는 큰 문제가 되지 않는다.

 

그렇다면 어떤 것이 문제가 될까?

plateaus가 문제가 될 수 있는데, 이것은 학습 속도를 저하시킬 수 있다. plateaus는 함수의 기울기 값이 0에 근접한 긴 범위를 뜻하며, 아래 그림과 같은 그래프를 의미한다.

기울기가 0이거나 0에 근접하기 때문에 표면이 매우 완만해서, plateaus 구간을 빠져나오는데 굉장히 많은 시간이 소요될 수 있다.

 

기억해야할 것은 2가지이다.

1. 비교적 큰 NN에서 학습하는 이상(or 파라미터가 많은 경우), local optima 문제가 발생할 확률은 매우 낮다.

2. Plateaus가 문제가 되어서 학습의 속도를 저하할 수 있는데, 이런 문제는 momentum, RMSprop, 또는 Adam과 같은 알고리즘이 plateaus를 빠져나오는 속도를 높혀줄 수 있다.

 

대부분의 네트워크가 고차원의 공간에서 최적화 문제를 풀기 때문에 이러한 공간을 이해하는데 힘들 수는 있지만, 이런 공간을 이해하는 방식이 진행되며, 이번 강의는 우리가 직관적으로 최적화 알고리즘에 대해 이해하는데 도움이 되고, 앞으로 직면하게될 문제를 이해하는데 도움이 될 것이다.

댓글