본문 바로가기

Study doc./Deep Learning

[cs231n] Neural Network - part 2

 

지난 파트에 이어 이번 파트에서는 최적화(Optimization) 알고리즘의 종류, regularization의 종류 그리고 transfer learning에 대해서 공부해 보겠습니다.

바로 시작해볼게요!

 

순서

  1. Optimization
    1. Stochastic Gradient Descent (SGD)
    2. SGD + Momentum
    3. Nesterov momentum
    4. AdaGrad
    5. RMSProp
    6. Adam
  2. Regularization
    1. Dropout
    2. Batch Normalization
    3. Data Augmentation
  3. Transfer Learning

 


 

1. Optimization

1-1. Stochastic Gradient Descent (SGD)

지금까지는 최적화의 방법으로 SGD(Stochastic Gradient Descent)를 고려해왔습니다.

매 순간 gradient를 계산하며 loss 값이 최소인 지점으로 이동했고, gradient가 0인 지점을 최소값이라고 판단했습니다.

하지만 이런 SGD 방법에는 세 가지 문제점이 있었습니다.

 

첫 번째로는 가중치를 업데이트 할때 loss에 영향을 미치는 정도가 다를때 비효율적이라는 것입니다.

아래 그림을 보면 붉은 점이 최적의 지점인 스마일까지 지그재그로 이동하는 모습을 확인할 수 있습니다.

이는 loss가 수평방향의 가중치보다 수직방향의 가중치에 더 민감하게 반응하기 때문입니다.

가중치가 많아질수록 이 문제는 더 심각해집니다.

 

 

두 번째 문제는 local minia 와 saddle point 에 빠질 수 있다는 것 입니다.

아래 그림과 같은 그래프에서 SGD를 사용한다면 붉은 점에서 gradient가 0이기 때문에 최솟값이라고 판단합니다.

하지만 이는 실제 최솟값은 아니기 때문에 잘못된 판단이죠.

특히 saddle point의 경우에는 매우 빈번하고, 붉은 점 주변의 gradient가 매우 작기 때문에 시간이 오래 걸립니다.

 

 

세 번째 문제는 SGD는 데이터의 일부분으로 loss의 추정값을 구하기 때문에 매번 정확한 gradient를 얻을수 없다는 것입니다.

따라서 noise에 매우 취약하며, 실제 최솟값까지 도달하는데 시간이 오래 걸릴수 있습니다.

아래 그림처럼 비틀거리기 때문입니다.

 

 

이렇게 기본 SGD 방법은 세 가지 문제점이 있습니다.

여기서 똑똑한 사람들이 이 문제를 해결하는 아이디어를 제시하는데 그게 바로 momentum 입니다.

 

 

1-2. SGD + Momentum

이 방법은 loss의 최솟값을 구할때 gradient의 방향 뿐만 아니라 velocity도 고려하는 것입니다.

다음 수식을 보시면 rho*vx 를 gradient에 더해준 것을 확인할 수 있는데, 

하이퍼 파라미터인 rho는 momentum의 비율입니다. 

즉 velocity의 영향력을 rho 비율로 맞춰주는 것이고, 보통 0.9를 사용합니다.

 

 

이를 통해서 SGD의 문제를 해결할 수 있었습니다.

local minia와 saddle point에서 gradient 가 0이더라도 가속도로 인해 더 내려올 수 있었고,

지그재그로 업데이트 되는 상황을 velocity로 상쇄시켜주었습니다.

또한 noise 역시 평균화 됨으로써 모두 해결되었습니다.

 

SGD Momentum 을 좀 더 살펴보겠습니다.

아래 그림에서 빨간 점이 현재 지점입니다. 그리고 각각 gradient 방향과 velocity 방향입니다.

실제 gradient의 업데이트는 이 두가지를 모두 고려한 파란색 벡터로 결정됩니다.

이런 원리로 SGD의 문제를 해결할 수 있었던 것입니다.

 

 

하지만 이런 momentum 에도 단점이 있으니, 실제 최소값에 도달하더라도 가속도로 인해 추월할 수 있다는 점입니다.

따라서 이전 가속도를 조금 덜 반영하고 싶은데, 그래서 나온 개념이 바로 Nesterov momentum 입니다.

 

 

1-3. Nesterov momentum

Nesterov momentum 은 Nesterov accelerated gradient 라고도 불리며, SGD momentum의 변형된 형태입니다.

계산하는 순서가 바뀐 것인데요, 먼저 velocity의 방향으로 이동한 후 gradient의 방향으로 이동하는 방법입니다.

 

 

왜 이렇게 해주냐고요?

이는 velocity의 방향이 잘못되었을 경우 gradient의 방향을 좀 더 활용할 수 있도록 해줍니다.

직관적으로 생각하면 velocity를 진행하고 난 후의 gradient를 고려하면 최솟값을 추월하는 현상을 줄일수 있다는 아이디어 입니다.

수식을 통해 더 이해해보겠습니다.

 

 

파란색 박스의 의미는 현재 위치(x_t)에서 velocity 방향으로 이동한(pv_t) 후의 gradient 계산입니다.

즉 업데이트된 velocity는 이전의 velocity에서 계산된 gradient에 학습률을 곱해서 뺀 값이지요!

 

이를 좀 더 이해가 쉬운 수식으로 확인할 수도 있습니다.

위의 그림에서 두번째 박스 가장 아래 수식을 보시면 현재 위치에서 velocity를 더한 후 현재와 이전의 velocity 간 차이를 추가해주는 것을 볼 수 있습니다.

즉 기존의 수식에 velocity의 오차 보정(error-correcting term)값을 넣은 것입니다.

 

Nesterov gradient 방법은 convex function에서는 좋은 성능을 보인다고 합니다.

하지만 non-convex function에서는 성능이 보장되지 않는다고 하네요.

 

 

1-4. AdaGrad

지금까지는 velocity를 고려한 momentum 기법에 대해서 다뤘습니다.

AdaGrad는 훈련 도중 계산되는 gradient를 활용하는 최적화 기법입니다.

아래 그림과 같이 gradient가 계산되는 반복마다 gradient를 제곱해주고 모두 더해줍니다.

그리고 이 누적으로 더해지는 gradient에 루트를 씌우고 나눠서 업데이트를 진행합니다.

 

 

이렇게 해줌으로써 위 그림에서 gradient가 작은 수평축으로는 작은 값으로 나눠주어 가속도가 붙을 것이고,

gradient가 큰 수직축으로는 큰 값으로 나눠주어 속도가 줄어드는 효과가 있습니다.

velocity를 사용하지 않고 momentum과 같은 효과를 냈습니다.

 

하지만 반복이 계속될수록 누적되는 gradient값이 점점 커지기 때문에 업데이트 되는 속도가 점점 줄어들게 됩니다.

이는 convex case에서는 최솟값 부근에서 속도가 줄어들어 좋은 효과일 수 있지만, non-convex case에서는 saddle point와 같은 지점에서 멈춰버리게 되어 단점이 될 수 있습니다.

 

이와 같은 문제를 해결하기 위해 AdaGrad를 살짝 변형하는데, 이게 바로 RMSProp 입니다.

 

 

1-5. RMSProp

RMSProp 는 누적되는 gradient에 decay rate를 곱해줌으로써 값이 계속 커지게 하는 것을 막아줍니다.

아래 그림을 보며 자세히 설명해보겠습니다.

 

 

decay_rate는 보통 0.9 혹은 0.99로 사용합니다.

예시를 위해 decay_rate를 0.9로 가정한다면,

grad_squared 는 지금까지 누적된 gradient 값에 0.9를 곱하고, 현재 gradient 제곱에 0.1을 곱해서 더한 값입니다.

누적된 그라디언트를 90% 반영하고, 현재 그라디언트를 10% 반영한다는 말입니다.

 

이렇게 수정된 식이 실제로 성능이 좋기 때문에 AdaGrad는 잘 사용하지 않는다고 합니다.

따라서 Momentum 방식을 적용해보고, 성능이 좋지 않을 경우 RMSProp를 적용시켜 decay_rate를 잘 조절해보는 것도 좋을 것 같습니다.

 

 

1-6. Adam

지금까지 velocity를 이용한 momentum 계열의 최적화, gradient를 이용한 Ada 계열(RMSProp)의 최적화를 배웠습니다.

그리고 이 둘을 합친 최적화 기법이 Adam 입니다.

 

일단은 그냥 합쳐보겠습니다(아직 완성된 Adam이 아님).

 

 

빨간색 박스는 gradient의 가중합으로 momentum 계열입니다.

파란색 박스는 gradient의 제곱합의 루트를 나눠준 Ada 계열입니다.

이렇게 합쳐서 gradient의 변화를 보니 문제가 있습니다.

 

바로 초기 step 에서 큰 폭으로 가중치가 업데이트 되는 것인데요,

보통 beta2 값이 0.99 이고, 초기 second_moment 값이 0 이기 때문에 첫번째로 계산된 second_moment 값이 0에 가까운 아주 작은 수가 됩니다.

그리고 이 작은수로 나눠주기 때문에 매우 큰 폭으로 업데이트 될 수밖에 없습니다.

이는 실제 loss 모양이 가파른게 아닌, 인공적인 원인이기 때문에 문제가 됩니다.

 

따라서 이를 해결하기 위해 보정하는 항(bias correction term)을 추가하는데요, 

이제 최종 Adam 식이 완성되었습니다. 

 

 

일반적으로 beta1을 0.9, beta2를 0.99, learning rate를 0.001 또는 0.0001로 설정하면 대부분 좋은 성능이 나온다고 합니다.

지금까지 다양한 최적화 방법에 대해서 배웠습니다. 그리고 아래 사진은 오늘 배운 Optimization 을 도식화 한 것입니다.

 

https://www.slideshare.net/yongho/ss-79607172

 

 

2. Regularization

다양한 Optimization을 배우는 과정은 train error를 줄이기 위한 것이었습니다.

하지만 아무리 train error가 작다고 하더라도 test set에서 성능이 좋지 않으면 말짱 꽝입니다.

따라서 저희는 train error와 test error의 격차를 줄이는 방법에 대해서도 공부해야 합니다.

 

가장 빠르고 쉬운 방법은 모델 앙상블 입니다.

여러가지 독립적인 모델들로부터 예측값을 가져와 평균내는 방식이죠.

혹은 학습 도중의 모델들을 여러가지 사용하는 방법도 있습니다.

 

하지만 저희가 원하는 것은 이게 아닙니다.

단일 모델로부터 train 과 test 의 격차를 줄이고 싶은데, 이를 해결할 방법 중 하나가 regularization 입니다.

그리고 Neural Network 에서 사용하는 regularization 방법에는 dropout이 있습니다.

 

 

 

2-1. Dropout

dropout의 원리는 간단합니다.

forward pass 과정에서 매 iter마다 임의의 뉴런을 0으로 만드는 것인데, 이는 특정 feature에만 의존하지 못하게 강제하는 것입니다.

 

 

dropout을 사용할때 주의해야할 점이 있습니다.

test time 에서는 임의성(Randomness)를 없애야 하는 것입니다.

오늘 고양이라고 분류한 사진이 내일은 다른 사진으로 분류하면 안되니깐요!

 

그럼 test time에서는 임의성을 어떻게 줄 수 있을까요?

train time 에서 실행한 dropout 에 대한 확률값(평균값에 대한 근사)을 test time에 곱해주는 것입니다.

이렇게 말이죠!

 

 

그리고 test 할때의 시간을 줄이기 위해 그냥 train에서 나눠주는 방법도 있습니다.

 

 

 

2-2. Batch Normalization

Batch Normalization 도 dropout과 비슷한 역할을 수행합니다.

drop out 에서 randomness를 average out 시켜준 것과 마찬가지로,

BN에서도 train 에서의 stochastic을 test에서 평균화 시켜주는 작업을 했습니다(train 셋에서의 평균과 분산을 사용).

이런 특성으로 인해 BN도 regularization 효과를 가질 수 있었습니다.

 

 

실제 이런 유사성 때문에 dropout 과 BN 은 동시에 사용하지 않고, 

차이점을 두자면 dropout 에는 조절가능한 파라미터 p가 있기 때문에 좀 더 유연한 사용이 가능하다는 점입니다.

 

 

2-3. Data Augmentation

기존의 CNN은 input을 넣고 해당 label을 연결시켜 학습시키는 전략이었습니다.

따라서 각 레이블에 상응하는 엄청난 양의 데이터가 필요했고, 적은 양으로는 과적합이 되기 쉬웠습니다.

이를 막기 위해 regularization이 필요했고, 그 중 data augmentation 이라는 개념이 등장했습니다.

 

 

data augmentation은 original input을 무작위로 변환시킨, 예를 들어 이미지를 돌리고, 자르고, 밝기를 조절한 input을 학습에 포함시키는 아이디어 입니다.

예를 들어 이런식으로 말이죠.

 

 

이 방법도 이전과 같이 train set의 stochastic 을 test set 에서는 marginalize out 되기 때문에 regularization의 효과가 있다고 할 수 있습니다.

 

 

3. Transfer Learning

과적합(overfitting)은 데이터의 수가 적기 때문에 발생하기도 합니다.

따라서 학습할 데이터가 적은 경우 전이학습 (transfer learning) 이라는 방법을 사용하기도 하는데요,

쉽게 말해 기존에 학습된 모델을 새로운 데이터(적은 데이터)에 적용시키는 방법입니다.

아래 그림과 함께 이해해보죠!

 

 

1번에 Imagenet에서 충분한 데이터를 가지고 학습한 모델이 있습니다.

이 모델은 1000 개의 class를 분류하는 모델이죠.

하지만 저희는 10 개의 class를 분류하는 모델이 필요하다고 가정한다면, 2번처럼 마지막 Fully connected layer 만 초기화하고 나머지는 모두 그대로 사용합니다.

 

그럼 어떤 상황에 얼만큼의 layer를 수정하는게 바람직할까요?

그것은 본인 데이터의 유사도갯수에 따라 결정됩니다.

아래 그림과 같이 유사도가 높고 많은 데이터를 가지고 있다면 거의 그대로의 모델을 사용해도 되겠죠.

또, 유사도가 높고 데이터 갯수가 적다면 마지막 layer만 초기화한 후 모델을 사용하면 됩니다.

하지만 유사도가 낮다면 모델을 사용하기 어려워지는데, 만약 데이터가 충분하다면 모델의 많은 부분을 수정해야 합니다.

 

 

실제로 딥러닝 분야에서 transfer learning은 일반적으로 사용되는 방법이라고 합니다.

그러니 처음부터 끝까지 본인이 다 만들려고 하지 말고, 기존에 있는 모델을 fine-tunning을 통해 적용시키는 방법에 대해서 공부하는 편이 바람직합니다.

 

이로써 Neural Network 의 전반적인 내용을 정리했습니다.

개념만 공부해서는 실력이 늘 수 없겠죠?

앞으로는 지금까지 공부한 개념들에 대한 실습도 동시에 진행해보겠습니다.