[CS231n] Lecture 7 | Training Neural Networks II

Hanna·2022년 6월 7일
0

CV

목록 보기
5/5
post-thumbnail

복습


약 10년 전에는 sigmoid가 아주 유명했지만, gradient Vanishing 문제가 발생함에 따라서 대부분 ReLU를 사용하고 있습니다.

또한 가중치 초기화에 대해 배웠습니다. 가중치 초기화가 너무 작으면 activation이 사라지고, 너무 크게 되면 결국엔 explode 되어 학습이 안 되게 됩니다.

그리고 데이터 전처리에 대해서 배웠습니다. 왜 normalization이 필요한가에 대해서 좀 더 자세히 말한다면, 손실함수가 아주 약간의 가중치 변화에도 민감하기 때문에, 동일한 함수를 쓰더라도 학습이 어렵기 때문입니다. 반면 zero-center, unit variance인 경우 손실함수가 덜 민감해지기 때문에 최적화가 싶고 학습이 더 잘되는 효과가 있기 때문입니다.


이론상으로는 성능이 특정 하이퍼파라미터에 의해 크게 좌우가 될 때 파라미터를 좀 더 넓은 범위에서 탐색할 수 있기 때문엔 RandomSearch가 좋다고 합니다. 처음에는 하이퍼파라미터를 좀 더 넓은 범위에서 찾고, iteration을 작게 줘서 학습을 시킨 후, 그 결과가 좋은 범위로 좁히는 것입니다. 그리고 iteratin이 조금 더 돌면서 더 작은 범위를 다시 탐색을 하게 됩니다. 이 과정을 적절한 하이퍼파라미터를 찾을 때까지 반복을 하는데, 중요한 점은 처음에는 최대한 넓은 범위를 설정해줘야 한다는 것입니다.

Optimization


NN에서 가장 중요한 것은 최적화 문제입니다. 우리의 목적은 가장 붉은 지점을 찾는 것, 즉 가장 낮은 loss를 가진 가중치를 찾는 것입니다. 가장 간단한 optimization 알고리즘은 SGD로, 미니 배치 안에서의 데이터에서 loss를 계산하고, gradient의 반대 방향을 이용해서 파라미터의 벡터를 업데이터합니다. 반대 방향인 이유는 손실 함수가 내려가는 방향이기 때문입니다. 이 단계를 계속 반복하면 결국엔 붉은 색 지점으로 수렴할 것이고 loss가 낮을 것입니다

SGD의 문제 점 중 하나는 손실 함수가 아주 느리게 변한다는 것입니다. loss는 수직 방향의 가중치 변화에 더 민감하게 반응을 하기 때문에, 수평 축의 변화에는 loss가 아주 천천히 줄어든다는 것입니다. 손실함수가 이런 식으로 생긴 환경에서는 SGD를 수행하면, gradient 방향이 고르지 못하기 때문에, gradient를 계산하게 되면 line을 넘나들면서 업데이트를 하게 되고, loss 영향에 덜 주는 수평방향 차원의 가중치는 아주 느리게 업데이트를 하고, 수직 방향 차원을 가로지르면서 지그재그하게 업데이트 한다는 점입니다.

SGD의 또다른 문제는 local minima와 saddle points와 관련된 문제로서, 중간에 local minima에서는 gradeint가 0이기 때문에 SGD가 멈춰버리는 현상이 생깁니다. 지난 몇년간 알려진 사실은 very large NN에서 local minima보단 saddle point에 더 취약하다는 것, saddle point 뿐만 아니라 saddle point 근처에서도 문제가 발생하다는 것입니다.

또다른 SGD의 문제점은 아주 많은 training set에서 미니배치의 데이터들만 가지고 실제 loss를 추정하기만 할 때, 매번 정확한 gradient를 얻을 수가 없다는 것입니다. 대신 gradient의 부정확한 추정값만을 구할 뿐입니다. 따라서, 손실 함수 공간을 비틀거리면서 돌아다니게 되고, minima까지 도달하는데 시간이 더 오래 걸린다는 것입니다.

위의 문제점들을 해결하기 위한 손쉬운 방법은 momentum을 추가하여, gradient 속도만 고려하는 것이 아니라 속도까지 함께 고려하는 것입니다. gradient=0 인곳에서도 속도를 가지고 있기 때문에 계속해서 움직일 수가 있다는 것입니다. momentum이 지그재그로 움직이는 상황 역시 상쇄를 시켜 수평 방향의 움직임을 가속화시켜 주는 역할을 하게 됩니다. 이를 통해 loss에 민감한 수직 방향에 변동은 줄어주고, 수평방향의 움직임은 점차 가속화 될 것입니다

기본 SGD의 momentum은 "현재 지점"에서의 gradient를 계산한 뒤 velocity와 섞어 주지만 Nestreov momentum은 우선 velocity의 방향으로 움직이고, 그 지점에서 gradient를 계산합니다. 그리고 다시 원점으로 돌아가서 둘을 합치는 것입니다. Nestreov는 convex optimization 문제에서는 뛰어난 성능을 보이지만 NN과 같은 non-convex problem에서는 성능이 보장되지 않다는 것입니다.
흥미로운 질문 중에, 학생이 좁고 깊은 minima의 경우는 건너 뛰기도 하느냐라는 질문이 있었습니다. 좁고 깊은 minima는 overfitting을 야기시키므로, 좋은 minima가 아니라고 합니다. 여기서 좋은 minima는 training data의 변화에 좀 더 강한 아주 평평한 minima라는 것입니다. 평평한 miniima가 좋은 이유는 좀 더 일반화를 잘 할 수 있으며, test data에도 더 좋은 결과를 얻을 수 있기 때문입니다.
최적화 방법 중에는 AdaGrad도 있습니다. AdaGrad는 훈련 중에 계산되는 gradient를 활용하는 방법으로 velocity term 대신 grad squared term을 이용하여, 학습 도중에 계산되는 gradient에 제곱을 해서 계속 더해주는 역할을 합니다. 그리고 나서 update를 할 때 update term을 앞서 계산한 gradient 제곱 항으로 나눠줍니다.

AdaGrad의 문제점은 하나가 있습니다. 학습이 계속 진행되면서 학습 횟수가 늘어나고, 값이 점점 작아진다는 것입니다. AdaGrad의 경우 convex case에서는 minima에 접근할 수록 속도가 점점 작아져서 수렴할 수는 있지만, 반대로 non-comvex case, 예를 들면 saddle point에 걸렸을 때는 멈춰버릴 수가 있습니다. 이를 개선한 것이 RMSProp입니다

RMSProp은 AdaGrad의 gradient 제곱 항을 그대로 사용하지만, 이 값들은 그저 누적만 시키는 것이 아니라 기존의 누적 값에 decay rate(보통 0.9 또는 0.99)를 곱해줍니다. RMSProp은 gradient 제곱을 계속 나눠준다는 점에서는 AdaGrad와 유사하지만 이를 통해 step의 속도를 가속, 감속 시킬 수가 있습니다.

Adam은 RMSProp과 momentum을 더하는 것 처럼 보입니다. 즉, 두 종류의 유용한 ㅏ특징을 모두 이용합니다. 하지만 문제점이 있습니다. 초기에 second moment를 0으로 초기화하기 때문에, update를 하고 난 후에도 second moment는 여전히 0에 가깝고, update step에서 second moment로 나누게 되는데 나눠주는 값이 크기 때문에 쵝 step이 커진다는 것입니다. 중요한 것은 이 커진 step이 실제로 손실함수가 가파르기 때문이 아니라는 것입니다. 이 값은 second moment를 0으로 초기화 시켰기 때문에 발생하는 인공적인 현상입니다. 그래서 이를 해결하기 위해 보정하는 항을 추가해줍니다.
Adam은 다양한 문제들에서 정말 잘 작동하고, beta1=0.9, beta2=0.999로 설정하고 learning rate를 1e-3이나 1e-4 정도로만 설정해놓으면 거의 모든 아키텍처에서 잘 작동합니다

동일한 환경에서 SGD, Momentum, RMSProp, Adam을 비교하면 Adam이 momentum 스러우면서도 RMSProp 스러운 것을 알 수 있습니다.

Learning rate


우리는 또한 learning rate라는 하이퍼파라메터를 가지고 있습니다. 너무 높아서도, 너무 낮아서도 안 되는 하이퍼파라미터입니다. 그래서 우리는 learning rate decay를 사용해서 learning rate를 높게 설정한 다음에 학습이 진행될수록 점점 낮추는 것입니다.
또한 learning rate decay는 Adam보다 SGD Momentum을 사용할 때 자주 쓰며, 일반적으로 학습 초기 때부터 고려하지는 않다는 것을 생각해야합니다. 또한, learning rate와 decay 등을 cross-validate 하려고 한다면 문제는 너무 복잡해집니다. 우리는 decay 없이 학습을 시켜보고, decay가 필요한 곳이 어디인지 고려해보는 것이 좋습니다.


이전까지는 training error를 줄이기 위한 방법들을 이야기 했습니다. 하지만 우리가 실제로 중요한 것은 train/test error의 격차를 줄요 "한번도 보지 못한 데이터"에 대한 성능을 높이는 것입니다.

Model Ensembles


위의 목표를 위해 가장 쉽게 할 수 있는 방법은 모델 앙상블 입니다. 머신 러닝에서 주로 사용하는 방법으로 모델 1개만 학습시키지 말고 10개의 모델을 독립적으로 학습시키는 것입니다. 결과는 10개 모델 결과의 평균을 사용하는 것입니다. 모델의 수가 늘어날수록 overfitting은 줄어들고 성능이 약 2% 정도 향상됩니다.
다른 방법으로는 학습하는 동안 파라미터의 learning rate를 엄청 낮췄다가 높혔다가를 반복하여, 손실함수를 다양한 지역에 수렴할 수 있도록 하는 방법도 있습니다.

Regularization


앙상블을 하려면 test time에 10개의 모델을 돌려야 하는데, 그리 좋은 방법은 아닙니다. 우리는 단일 모델의 성능을 올리는 것이 중요합니다. 이를 하기 위해 하는 것이 regularization입니다. 우리가 모델에 어떤 것을 추가하게 되는데, 모델이 training data에 fit하는 것을 막아주는 역할을 합니다.

NN에서 가장 많이 사용하는 regularization은 dropout으로, forward pass 과정에서 임의로 일부 뉴런을 0으로 만든느 것입니다. Dropout이 좋은 이유는, 특징 간들의 co-adaptation을 방지한다고 볼 수 있습니다. 예를 들어 한 이미지가 고양이인지 아닌지를 학습할 때, 눈, 꼬리, 털 등에 대해 학습을 하고, 이 정보들을 취합해서 결정을 내리게 됩니다.
Dropout을 적용하면 네트워크가 어떤 일부 features에만 의존하지 못하게 합니다. 따라서 dropout이 overfitting을 막아주고, 단일 모델로 앙상블 효과를 내기도 한다고 합니다
Dropout이 Regularization에 가장 대표적인 예이긴 하지만 batch normalization 또한 이와 비슷한 동작을 할 수 있습니다. training 할 때 mini batch로 하나의 데이터가 샘플링 될 때 매번 서로 다른 데이터와 만나게 되기 때문입니다. 실제로 BN을 사용할 때는 Dropout을 사용하지 않습니다. 하지만 여전히 Dropout은 쓸모가 있습니다. 우리가 자유롭게 조절할 수 있는 파라미터가 있기 때문이죠.

Data Augmentation


이런 regularization에 부합하는 것 중 하나가 data augmentation입니다. 원본 이미지를 사용하는 것이 아니라 무작위로 변환시킨 이미지로 학습을 시킵니다. flip, crop, 반전, color jittering 등을 하여 학습을 하는 방법입니다.

이 외에 Drop Connect와 Fractional Max Pooling, Stochastic Depth가 있지만 많이 사용하지는 않습니다.

Transfer learning


Transfer learning은 간단합니다. CNN 모델이 ImageNet과 같은 아주 큰 데이터셋으로 학습을 한 번 시키고, 이 학습된 feature를 우리가 가진 작은 데이터셋에 적용하는 것입니다.

profile
매일 성장하고 있습니다

0개의 댓글