이번 시간에는 Regularization and Optimization에 대해 다룬다.

 

우선 지난 시간에 이어서, 이 예시의 classifier는 결과를 보면 좋은 classifier는 아니다. 

 

 

우리는 loss function을 통해 classifier의 성능을 측정할 수 있다.

 

맨 아래 수식을 보면, linear classifier 결과값과 실제 label을 비교하는 loss function을 적용한 뒤 평균을 구하는 방식으로 Loss 값을 구하고 있다.

저번 강의에서 이와 관련하여 가장 많이 사용되는 Softmax loss, Cross Entropy loss에 대해 설명했었다.

 

 

1. Regularization (정규화)

지금까지 설명한 내용이 Data Loss에 해당하는 내용이다.

우리의 모델(Classifier)이 얼마나 학습 데이터를 잘 맞추는지에 관한 값이고, 우리는 이 값이 최대한 작아지길 원하는 것이다.

 

추가적으로 우리는 여기에 Regularization에 해당하는 값을 더할 것이다.

이 값은 모델이 학습 데이터를 너무 잘 맞추게 되는 것을 방지하기 위한 값이다.

(Regularization에 해당하는 내용을 종종 문제집을 풀 때 답지까지 외워버려서 문제집은 잘 푸는데, 막상 시험에서 처음 보는 문제는 못 푸는 상황에 비유하곤 한다.)

 

즉 학습 데이터에 대해서는 성능이 낮아지지만 테스트 데이터에 대해서는 더 잘 작동하도록 해주기 위한 값이다.

 

 

위 이미지가 Regularization을 이해하는 데 직관적으로 와닿는 예시이다.

f1은 학습 데이터에 대해서는 완벽하지만, 위 예시가 아닌 일반적인 다른 데이터에 대해서는 매우 성능이 나쁠 것이다. (Overfitting)

그에 비해 f2는 f1에 비해 현재 학습 데이터 기준 성능은 낮겠지만 훨씬 일반적이고 나은 모델링임을 알 수 있다.

 

 

 

다시 수식으로 돌아와서, 람다(λ)에 해당하는 값은 우리가 설정하는 hyperparameter 중 하나이다.

값을 어떻게 설정하느냐에 따라서 얼마나 Regularization을 하느냐가 정해진다.

 

또한 R(W)에 해당하는 식도 여러 가지 예시가 있다.

L2 Regularization의 경우, 각 W(weight)에 해당하는 값을 제곱하여 다 더해주는 방식이다. 

특징은 W 자체가 매우 작은 값이므로 제곱하면 더 작아진다는 것이다. 따라서 Regularization 값(=Penalty)이 매우 작다.

그에 반해 L1 Regularization은 W의 절댓값을 모두 더해서 Regularization값으로 지정하는 방식이다. 

 

이외에도 Regularization 방법으로 Dropout, Batch normalization 등 많은 방법들이 있다. 

이는 추후에 더 다루게 될 것이다.

 

Regularization에 대해 정리하자면,

  • Weight를 더 분산시킬 수 있으며
  • 모델을 더 simple하게 만들 수 있고
  • 곡률을 더해서 optimization을 개선할 수 있다.(특히 L2 regularization)

 

 

 

이제 예시를 보자.

 

두 개의 weight 예시가 있다. (w1, w2)

L2 Regularization을 한다면 둘 중 무엇을 더 선호할까?

 

답은 w2. 모든 w를 다 제곱해서 더하는 것이므로 w1을 사용하면 R(W) = 1, w2를 사용하면 R(W) = 1/4이다.

R(W)은 최종 Loss에 더해지는 값이고, 우리는 Loss를 최소화하는 게 목적이므로 w2가 더 선호되는 것이다.

이 예시를 통해 L2 Regularization의 경우 weight 값들을 더 퍼뜨리는 것을 선호함을 확인할 수 있다.

 

 

그렇다면 L1 Regularization의 경우는 어떨까?

이 경우에는 w 절댓값의 합이므로 w1, w2 둘 다 R(W)의 관점에서는 1로 값이 같다.

 

 

 

 

 

지금까지 한 내용을 정리해보자.

 

1. 우리는 학습 데이터셋 (x,y)를 가지고 있다. 

2. 그리고 score function을 이용해 각 x 데이터에 대해 score 값을 얻을 수 있다. 이때 score function으로 Linear function을 사용하고 있다: f(s,W) = Wx

3. 이렇게 각 데이터에 대해 얻은 score 값을 Loss function의 입력으로 넣어서 각 데이터에 해당하는 loss 값을 구할 수 있다. 이때 loss function으론 주로 softmax를사용한다.

4. 최종적으로 이렇게 얻은 Loss 값의 평균과 Regularization 값을 더해서 Final loss(Full loss)를 얻을 수 있다.

 

 

이제 다음 의문점은, 어떻게 하면 좋은 Weights 값을 설정할 수 있느냐이다.

 

이는 우리가 다음으로 공부할 Optimization을 통해 해결할 수 있다.

 

2. Optimization (최적화)

 

Optimization은 주로 위와 같은 예시로 설명된다.

한 사람이 산에 올랐는데, 그곳에서 가장 낮은, 즉 깊은 골짜기를 찾으려고 한다. 

사람이라면 육안으로 바로 관찰할 수 있겠지만, 지금 우리는 사람이 아닌 컴퓨터가 하는 작업을 말하고 있으므로

눈을 가린 사람이 기울기를 통해 골짜기를 찾아 가는 과정이라고 생각하면 된다.

 

그렇다면 이제 어떻게 찾으면 될지 방법을 알아보자.

 

 

그냥 무작정 해보는 방법이다. 랜덤한 Weight matrix 1000개를 해보고 가장 좋은 값을 찾는 방법으로 당연히 좋은 방법은 아니다.

 

 

두번째 방법은 기울기를 구하는 것이다.

낮은 골짜기를 찾기 위해 현재 위치에서 낮은 쪽으로 향하는 기울기 방향으로 나아가는 방법이다.

 

2-1. Gradient Descent

 

 

각 지점에서 기울기를 계산하여, 감소하는 방향으로 나아가는 방법이다.

 

 

빨간색 영역이 고도가 낮은 영역이라고 했을 때, 현재 W의 위치(흰색 동그라미)에서 기울기가 향하는 방향으로 나아간다. 

이때 화살표의 크기를 step size라고 생각하면 된다. 점점 진행할수록 step size는 작아지는 게 일반적이다.

 

2-2. Stochastic Gradient Descent (SGD)

 

가장 많이 사용되는 Stochastic Gradient Descent 는 전체 데이터를 보는 게 아니라 데이터를 나눠서 계산하는 방법이다.

즉 위의 코드처럼 전체 데이터 중 256개의 데이터 사이즈를 정해놓고 그 단위를 batch라 부른다.

각 batch 마다 Loss를 계산해서 gradient를 평가하고 이를 반복한다.

이때 모든 데이터셋에 대한 batch 작업이 끝나면 이를 1 epoch라고 한다.

 

이 방법의 문제점 중 하나는 step size가 만약 너무 크다면, top-down을 향해 가는 과정에서 발산이 일어날 수 있다는 점이다.

또는 진행 과정이 너무 느리다면, oscillation이 일어날 수 있다.

 

 

또다른 문제점은 loss function의 그래프가 슬라이드처럼 local minima를 가지고 있거나, saddle point를 가지고 있을 때 문제가 발생할 수 있다는 점이다. 

참고로 saddle point의 경우 weight matrix의 차원이 높아질수록 더 흔하다.

 

 

SGD의 또다른 문제점은 우리는 앞서 말했듯 모든 데이터를 보고 업데이트를 하는 게 아니라 배치 단위로 전체 데이터를 나누어서 업데이트를 진행한다. 그렇게 되면, 최종적으로 가장 낮은 곳을 향해 나아가기는 하지만 전체 데이터를 보는 게 아니기 때문에 중간중간 noisy한 업데이트가 발생할 수 있다.

 

2-3. SGD + Momentum

 

이러한 세가지 문제점을 해결하기 위해 Momentum 을 적용할 수 있다.

왼쪽은 지금까지 배운 SGD이고, 오른쪽은 SGD에 Momentum을 결합한 것이다.

 

Momentum을 결합한 식을 살펴보면, velocity라는 새로운 개념을 추가하고 있다. 

이전 velocity값과 현재 gradient값을 더해서 v_t+1이라는 값을 업데이트한다.

ρ가 momentum에 해당하는 값으로, 그 값이 커질수록 현재 velocity가 이전 시점의 velocity에 영향을 많이 받게 된다.

 

2-4. RMSProp

 

또다른 Optimizer로는 RMSProp이 있다.

수도 코드를 보면, grad_squared라는 term이 추가된 걸 볼 수 있는데 들여다보면 dx를 제곱해주고 있는 게 보인다.

즉 gradient가 큰 값은 더 커지고, 작은 값은 더욱 작아진다.

그리고 최종적으로 x를 업데이트하는 과정에서 이 값을 루트를 취해 나눠주고 있다.

 

이를 이론적으로 이해해보자면 변화량이 커서 gradient가 커진다면,

분모의 값이 커질테고 따라서 업데이트 시 해당 방향으로 진행하는 step size가 작아진다.

 

쉽게 말하자면 한 번 업데이트할 때 gradient가 크게 나오면, 즉 변화하는 방향이 크게 변하면 그 step size를 작게 해서 위험을 방지한다고 볼 수 있다.

 

 

 

 

2-5. Adam

 

다음 Optimization 기법으로 현재 가장 많이 쓰이는 Adam 알고리즘이 있다.

앞서 배운 Momentum과 RMSProp의 장점을 합친 방법이다.

 

그러나 first timestep을 생각해보면, first_moment와 second_moment = 0 으로 설정되고, beta1, beta2 값도 1에 매우 가까운 값(ex.0.99)에 가깝게 설정된다. dx에 해당하는 값이 매우 작더라도 최종적으로 x를 업데이트하는 식에서 분모의 값이 매우 작아지므로 업데이트되는 값은 매우 커지게 된다.

 

이를 방지하기 위해 bias term을 추가한다. 

 

 

그렇다면 우리가 앞서 매운 Regularization은 Optimizer과 어떻게 상호작용할까?

 

 

우리가 배운 기존 Adam 방식은 dx = compute_gradient(x) 단계에서 L2 정규화 항을 계산한다.

그러나 AdamW (Weight Decay 적용)는 최종 가중치(파라미터) 업데이트 단계인 최하단의 x -= learning_rate * ... 코드 위치에 가중치 감쇠 항을 직접 더해준다.

 

 

 

2-6. Learning Rate

다음으로 Learning rate에 대해 알아보자.

 

 

 

노란색 그래프의 경우 learning rate가 매우 빠르게 증가한다. 이 경우 앞서 보았던 oscillation case에 해당한다.

파란색 그래프처럼 Learning rate가 느리게 증가하는 경우, 매우 느리게 수렴하는 경우이다.

초록색 그래프처럼 learning rate가 높은 경우, 수렴은 했지만 loss가 큰 값에 수렴하므로 Local minimum하는 케이스이다.

 

이제 learning rate를 조절하는 방법(scheduler)에 대해 알아보자. 

 

Scheduler

 

 

(1) Step Decay

하나의 좋은 방법은 특정 iteration을 기준으로 learning rate의 1/10 비율로 감소시키며 학습을 반복하는 방식이다. 

학습률이 감소할 때마다 loss가 계단형태로 감소하며, Resnet을 학습시킬 때 많이 사용하는 방법이다.

 

 

(2) Cosine Decay

cosine 함수를 이용하는 방법으로 learning rate를 부드럽게 감소시키는 방식이다. 

 

 

 

(3) Linear learning rate decay

learning rate를 직선 모양으로 일정하게 줄여나가는 방식이다.

 

 

(4) Linear Warmup

실제로 매우 많이 활용되는 linear warmup 방식은 학습 초반 특정구간 동안 목표 초기 learning rate까지 선형적으로 증가시킨 후 이후 감수 스케줄러를 적용하는 기법이다.

Empirical rule로는 만약 데이터 배치 사이즈를 N배로 키운다면, initial learning rate도 똑같이 N배로 키워주는 게 잘 작동한다.

 

+ Recent posts