[CS231n] 7. Training Neural Networks II
📗강의노트/CS231n

[CS231n] 7. Training Neural Networks II

728x90
반응형

Batch Normalization을 다시 보자




   




< Fancier Optimization >


최적화 문제가 NN에서 중요하다


< SGD >


미니 배치 안에서 데이터 loss를 계산, 그리고 Gradient의 반대 방향을 이용해서 파라미터 벡터를 업데이트 한다. 





손실함수의 모양에 따라 영향을 많이 받는다. 위의 경우는 Loss는 수직 방향의 가중치 변화에 훨씬 더 민감하게 반응하는 것이다. 

SGD의 학습 과정을 보면 “지그재그”로 나타나게 된다. gradient의 방향이 고르지 못하기 때문이다. 가로 방향의 가중치는 느리게 변하는 반면에 수직 방향의 가중치가 빠르게 변화하면서 지그재그 모양으로 지저분하게 나타나는 것이다. ( 고차원 공간에서 더 빈번하게 발생한다 )

불균형한 방향이 존재한다면 SGD는 잘 동작하지 않을 것이다. ( 파라미터의 수가 많으면 이런 불균형의 발생 비율 상당히 높음 )




Local minima  & saddle point 문제도 있다. 

X축은 어떤 하나의 가중치 이고 Y축은 Loss이다. 손실함수의 중간에 valley가 존재한다. 이 경우에 SGD는 멈춰버린다. Gradient가 0이 되버리기 때문이다.  ( 위의 그림 )

Saddle point의 문제의 경우 눈에 보이는 valley가 있는 것은 아니지만, 한쪽은 증가하고 한쪽은 감소하는 모습일 때 gradient가 0이 될 수 있다 ( 아래 그림 )

아주 큰 NN은 local minima 보다 saddle point에 더 취약하다고 알려져있다. 뿐만 아니라 saddle point 근처에서도 문제가 발생한다. gradient가 너무 작아서 업데이트가 아주 느리게 진행되기 때문이다. 




미니배치를 가지고 업데이트 하는데, 이는 매번 정확한 Gradient를 얻을 수가 없다는 것을 의미한다. 대신에 gradient의 부정확한 추정값만을 구할 뿐이다. ( minima까지 도달하는데 시간이 오래걸린다 ) 




이 문제를 해결할 수 있는 방법이 있다. 바로 SGD에 momentum term을 추가하는 것이다. 
그저 velocity(속도)를 유지하는 것이다. Gradient를 계산할 때 gradient방향과 velocity를 같이 이용한다. 

Rho 는 velocity의 영향력을 나타내는데 보통 0.9와 같이 높은 값으로 맞춰준다. 이를 통해 gradient vector 그대로 방향이 아니라, velocity vector 의 방향으로 나아가게 된다.




공이 굴러가는 것 처럼 속도로 생각하면 gradient=0이어도 충분히 움직일 수 있다. 그 덕분에 local minima를 극복할 수 있게 되고 계속해서 내려갈 수 있게된다. ( saddle point에서도 마찬가지 )
업데이트가 자 안되는 경우에도 (지그재그) momentum이 이 변동을 서로 상쇄시켜버린다. 이를 통해 loss에 민감한 수직 방향의 변동을 줄이고 수평 방향의 움직임을 점차 가속화 할 것 이다. 

모멘텀을 추가함으로 인해 속도가 생기면 노이즈가 평균화되어 버리는 것이다. 




현재 gradient의 방향은 붉은색이다. 초록색은 속도 vector를 의미한다. 실제 업데이트(actual step)는 이 둘의 가중 평균으로 구할 수 있다. 

 Nesterov Momentum이라는 것도 있는데 이는 계산하는 순서를 조금 바꾼 것이다. 
기본 SGD momentum은 "현재 지점"에서 gradient를 계산한 뒤에 velocity와 섞어준다.
 Nesterov는 먼저 velocity방향으로 움직이고 그 지점에서 gradient를 계산한다. 그리고 다시 원점으로 돌아가서 둘을 합치는 것이다. 

 Nesterov는 convex optimization에서는 뛰어난 성능을 보이지만 NN같은 non convex에서는 그러지 못한다. 

velocity의 초기값은 0으로 둔다 ( 하이퍼파라미터가 아니다 )




수식을 수정하면 새로운 관점에서 볼 수 있다.

(아래 박스에서) 첫 번째 수식은 기존의 momentum과 동일하다. 
Nesterov는 현재/ 이전의 velocity간의 에러보정이 추가되었다.

 Local minima를 지나고 이후에 스스로 경로를 수정하고는 결국 Minia에 수렴한다. 
( 좁고 깊은 minima를 지나칠 수도 있지만 이는 좋지 않다. 심한 overfit을 불러올 수 있기 때문이다 )

 Nesterov가 Overshooting도 덜 하다.




AdaGrad라는 방법도 있다. 

훈련도중 계산되는 gradients를 활용하는 방법이다. Velocity term 대신에 grad squared term을 이용한다. 그리고 학습 도중에 계산되는 gradient에 제곱을 해서 계속 더해준다. 업데이트를 할 때는 update term을 앞서 계산한 gradient 제곱근 항으로 나눠준다. 

Small dimension에서는 gradient의 제곱 값 합이 작다. 따라서 이 작은 값으로 나눠지므로 가속도가 붙는다. 

학습이 계속 진행되면 학습 횟수 t가 계속 늘어나는 것이다. AdaGrad는 step을 진행할수록 값이 점점 작아진다.(업데이트 속도가 느려지는 것) Convex할 때는 minimum에 서서히 속도를 줄여서 수렴하면 좋다. 
하지만 Non convex에서는 saddle point에 걸려 멈출 수 있어서 문제가 된다. 

NN을 학습시킬 때 AdaGrad를 잘 사용하지 않는다.




앞선 이 문제를 해결한 것이 RMSProp이다. (AdaGrad의 변형)
누적된 gradient 제곱항에 decay_rate를 곱해준다 & 현재 gradient의 제곱은 (1-decay) 를 곱해준다. ( 보통 0.9 / 0.99 )

이를 통해 step의 속도를 가속/감속 시킬 수 있다. ( 속도가 줄어드는 문제 해결 ) 




더 발전된 최적화 방법인 AdamOptimizer 이다.

First moment와 second moment를 이용해서 이전의 정보를 유지시킨다. 




빨간색(first)은 gradient의 가중 합이다. 그리고 파란색(second)은 AdaGrad나 RMSProp처럼 gradients의 제곱을 이용하는 방법이다. 

First는 velocity를 담당한다. 이는 마치 "RMSProp + Momentum"으로 보인다. 

초기 스텝에서는 second moment를 0으로 초기화한다. 이 때문에 초기 Step이 엄청 커져 버려서 잘못될 수도 있다. 그레서 Adam은 이를 해결하기 위해 보정하는 항을 추가한다. 
(1e-7,8은 나누는 값이 0이 되는 것은 방지한다.)




현재 Step에 맞는 적절한 unbiased term을 계산해준다. 위의 식이 실제와 같은 것이다. 

Adam은 엄청 좋다! ( beta1 = 0.9, beta2=0.999, learning_rate= e-3, e-4 정도로 하면 잘 됨 ) 

Momentum처럼 overshoot하긴 하지만 심하지 않은 정도이다. 그리고 RMSProp같은 특징도 있어서 각 차원의 상황을 따로 고려해서 Step을 이동한다. 




learning rate 를 설정할 때, 다양한 방법이 있다.  Decay learning rate 같은 경우는 처음에 learning rate를 높게 설정하고 학습이 진행될 수록 점점 낮추는 것이다. 




ResNet 논문인데, step decay learning rate 전략을 이용해서 loss 를 나타낸 것이다. 
평평해지다가 내려가는 구간은 Learning rate를 낮추는 구간이다. 
( step decay learning rate는 Adam 보다는 SGD Momentum을 사용할 때 자주 쓴다 )

보통 학습초기에는 learning rate decay가 없다고 생각하고 learning rate를 잘 선택하는 것이 중요하다. ( decay없이 하다가 필요한 구간이 어디인지 고려해보는 것이 좋다 ) 




지금까지는 1차 미분으로 optimization을 했었다.



2차 근사의 정보를 추가적으로 활용하는 방법이 있다. 이를 이용하면 minima에 더 잘 근접할 수 있다. 이를 “Newton Step” 이라고 한다.
Hessian matrix를 계산한다. 2차 미분값들로 된 행렬이다. 이 hessian matrix의 역행렬을 이용하게 되면 실제 손실함수의 2차 근사를 이용해 minima로 곧장 이동할 수 있을 것이다. 




기존과는 다르게 Learning rate 가 존재하지 않는다. 하지만 2차 근사도 완벽하지 않기 때문에 결국에는 필요하다. 하지만 NN에서는 사용 불가하다. Hessian matrix는 NXN matrix이다. ( N : network의 파라미터 수 ) 

그래서 실제로는 hessian을 근사시켜서 사용하는 방법을 택한다. ( L-BFGS )




그래도 DNN에서 실제로 별로 쓰지 않는다.

정리하자면




Adam이 가장 좋은 선택이고, full batch이고 Stochastic, parameter이 적다면 L-BFGS도 좋은 선택이 될 수 있다. 

위의 모든 것은 Training error를 줄이고, 손실함수를 최소화시키기 위한 방법이었다. 

Training error보다는 train / test error간의 격차를 줄이는 것이 원하는 것이다. 




최적화를 끝마친 상황에서 “ 한 번도 보지 못한 데이터 “ 에서의 성능을 올리기 위해서는 어떻게 해야할까? 




가장 빠르고 쉬운건 모델 앙상블이다. 10개의 모델을 독립적으로 학습시키고, 결과는 10개 모델 결과의 평균을 이용한다. 




Learning rate를 엄청 낮췄다가 높혔다가를 반복한다. 이런 방식으로 손실 함수에 다양한 지역에 수렴할 수 있도록 만들어 준다. 

갭도 중요하지만 validation의 성능을 높이는 것이 중요하다 .


< Regularization >


단일 모델의 성능을 올리는 것이 우리가 원하는 것이다

모델에 어떤 것을 추가하여 training data에 fit하는 것을 막아준다. 




하지만 L2는 NN과 잘 어울리지 않는다.




그래서 사용하는 Regularization이 바로 dropout이다!
Forward pass 과정에서 일부 뉴런을 0으로 만드는 것이다. 오로지 뉴런의 일부만 사용하고 있다.
Forward pass iteration 마다 그 모양은 계속 바뀐다. 
( 현재의 activations의 일부를 0으로 만들어 다음 레이어의 일부가 0과 곱해지게 하는 것이다 )




특징들 간의 “상호작용”을 방지하는 것이 특징이다. 이후에 모델이 고양이라고 예측할 때 다양한 features를 골고루 이용할 수 있도록 한다. 따라서 Dropout이 Overfitting을 어느정도 막아준다. 
단일 모델로 앙상블 효과를 가질 수 있다. Dropout은 아주 거대한 앙상블 모델을 동시에 학습 시키는 것과 같다. 





z는 random이다. Test time에 임의의 값을 부여하는 것은 좋지 않다. 




Dropout = 0.5로 학습시킨다고 생각해보자. 4가지 경우의 수가 존재하고, 그 값들을 4개의 마스크에 대해 평균화 시켜준다.

이 부분에서 train / test 간 기대값이 서로 상이하다. test가 train의 절반밖에 되지 않는다. 
이를 해결하기 위해 dropout probability를 네트워크의 출력에 곱한다. 그럼 이제 기댓값이 같아졌다. 




일부 노드를 무작위로 0으로 만들어주고, test time에서는 그저 값 하나만 곱해주면 된다 (probability)




Test time에는 기존의 연산을 가져가고 train time에서 p를 나눠준다. Test time에서 가능한 효육적으로 작동하기 바라기 때문이다. 

Dropout을 사용하게 되면 전체 학습시간은 늘어나지만 모델이 수렴한 후에는 더 좋은 일반화 능력을 얻을 수 있다. 

정리하자면 

(1) train time에는 네트워크에 무작위성을 추가해 training data에 너무 fit하지 않게 한다.
(2) test time에서는 randomness를 평균화 시켜서 generalization 효과를 주는 것이다. 

BN도 비슷한 역할을 할 수 있다. 그래서 BN을 할 때 dropout을 사용하지 않는다. 충분히 regularization이 되기 때문이다. 




Train time에 이미지를 무작위로 변환시켜 볼 수 있다. 레이블을 그대로 놔둔채로 진행한다.
이미지 반전을 시킨다.




잘라내고 반전시켜서 학습을 한다. 
이미지의 밝기를 낮추기도 한다. (Color jittering)

Train time에 입력 데이터에 임의의 변환(Data augmentation)을 시켜주게 되면 일종의 regularization 효과를 얻을 수 있다. Train time에는 stochasticity가 추가되고 test time에는 marginalize out 되기 때문이다. 




Dropout과 유사하게 dropconnect라는 방법이 있는데, 이는 activation이 아닌 weight matrix를 임의적으로 0으로 만들어주는 방법이다. 




Fractional Max Pooling은 pooling이 될 지역을 임의로 설정하여 샘플링하는 것이다. 




Stochastic Depth

Train time에서 일부 레이어를 제외하고 학습을 하고, test time에는 전체 네트워크를 다 사용한다. 

대개는 BN만으로도 충분하지만 overfitting이 발생한다 싶으면 dropout을 추가하기도 한다. 


< Transfer Learning >


원하는 양 보다 더 적은 데이터만을 가지고 있을 때 사용할 수 있는 방법. 

Overfittingd이 일어날 수 있는 상황 중 하나가 충분한 데이터가 없을 때이다. 

Transfer learning은 “ CNN은 엄청 많은 데이터가 필요함 “이라는 미신을 깨부순다. 




가장 마지막 FC Layer는 최종 Feature와 class scores간의 연결인데 이를 초기화시킨다. 그리고 차원을(ex.클래스 수만큼으로) 줄이고, 마지막 레이어만 가지고 우리 데이터를 학습시킨다. 

데이터가 조금 많다고 생각되면 전체를 fine tuning 해볼 수도 있다.







데이터셋이 크지 않은 경우라면 task와 유사한 데이터셋으로 학습된 pretrained model을 다운로드 받는다. 그리고 모델의 일부를 초기화시키고, 데이터로 모델을 fine tune하는 것이다. 




728x90
반응형