6강 리뷰
1) Activation Functions
- Sigmoid
- tanh
- ReLU
- leaky ReLU
- ELU
- Maxout
2) Data Preprocessing
3) Weight Initialization
- Xavier initialization
4) Batch Normalization
5) Babysitting Learning Process
- sanity check
6) Hyperparameter Optimization
- Cross Validation
Training Neural Network - 2
이번 강의에서 배울 내용은
- Facier Optimization : 많이 사용되는 강력한 최적화 알고리즘(손실함수를 최적화)
- Regularization : 네트워크의 Train/Test error 간의 격차를 줄이기 위해 사용, 즉 과적합시에 이 값을 조정함(손실함수에 Regulaization term을 더해 함수를 일반화시킨다)
- Transfer Learning : 미리 학습된 모델을 불러와 데이터만 사용하여 학습시키는 방법
Fancier optimization
Neural Network에서 가장 중요한 것이 최적화(optimization)이다. 네트워크의 가중치에 대한 손실함수를 정의해놓으면 이 손실함수는 가중치가 얼마나 좋은지 나쁜지를 알려준다.
위의 사진에서 오른쪽 그림의 X/Y축은 두 개의 가중치를, 각 색은 loss 값을 의미한다. 가장 붉은 색인 지점이 가장 낮은 loss를 뜻하고 이에 대한 가중치를 찾는 것이 최적화의 목적이다.
Stochastic Gradient Descent
가장 간단한 최적화 알고리즘은 SGD이다. minibatch안의 데이터에서 loss를 계산하고 gradient의 반대 방향을 이용해서 파라미터 벡터를 업데이트한다.
반대 방향인 이유는 손실 함수는 줄어드는 것이 올바른 방향이기 때문이다.
업데이터를 반복하다보면 결국 빨간색 지역으로 수렴하게 될 것이고, loss가 낮아질 것이다.
하지만 이 SGD에는 몇 가지 문제가 있다. 손실함수의 가중치 w1과 w2가 있다고 가정해보자.
w1는 수평축으로 가중치가 변하고, w2는 수직축으로 가중치가 변한다면, 수평 축의 가중치는 변해도 loss가 아주 천천히 줄어들고, 수직 방향의 가중치 변화에 더 민감하다면 전체 loss는 매우 느리게 줄어든다.
위의 그림은 SGD로 학습이 되는 과정을 보여준다.
loss에 영향을 덜 주는 수평방향 차원의 가중치는 업데이트가 매우 느리게 진행되고, 수직방향 차원의 가중치는 비교적 빠르게 되므로 지그재그가 된다.
우리가 보는 것은 2차원이지만, 훨씬 더 고차원 공간에서는 훨씬 더 빈번하게 발생한다.
SGD의 또 다른 문제는 local minima와 saddle point와 관련된 문제다.
이런 상황에서 SGD는 멈춰버린다. gradient가 0이 되기 때문이다. SGD는 gradient의 반대방향으로 이동하는 데, 0이 되면 이동이 안된다. 이런 경우가 local minima(locally falt) 에 해당한다.
local minima는 아니지만, 증가하다가 감소하는 지역(saddle point)이 있다. 이 곳에서도 gradient는 0이 된다. 따라서 이런 상황에서도 학습이 멈추게 된다.
saddle point 근처에서도 계산해보면 거의 0에 가깝기 때문에 업데이트가 아주 느리게 진행될 것이다.
우리는 1차원의 예제만 보고 있지만 고차원 공간을 따져볼 때는 local minima보다 saddle point가 더 많아질 것이다. 1억개의 차원이라고 하면 사실 거의 모든 곳에서 발생한다고 봐도 무방하다.
또 다른 문제가 있다. Stochastic gradient 는 확률적인 기울기란 뜻이다.
손실 함수를 계산할 때는 엄청 많은 training set 각각의 loss를 전부 계산해야 한다. 이는 매우 어렵고 복잡하다. 그래서 실제로는 전체 training set가 아닌 minibatch의 데이터들만 가지고 실제 loss를 추정한다.
이는 매번 정확한 gradient를 얻을 수 없다는 것을 의미한다. 그렇다는 것은 정확한 gradient를 얻고, 적절한 loss를 찾기 위해서는 오래 걸릴 수 밖에 없다.
확률적 계산을 빼고 GD만 사용하면 되냐고 생각할 수 있겠지만, 이때도 같은 문제가 발생한다.
noise 즉, gradient가 이리저리 돌아다니는 현상은 minibatch를 사용할 때만 발생하는 것이 아니라 full batch를 사용할 시에도 발생한다.
SGD + Momentum
이런 문제들을 해결 할 수 있는 간단한 방법은 SGD에 momentum term을 추가하는 것이다.
왼쪽은 classic 버전의 SGD 이다. 오로지 gradient 방향으로만 움직인다.
오른쪽은 SGD + momentum이다. gradient를 계산할 때 velocity를 이용하여 두 가지를 같이 고려한다.
momentum의 비율을 나타내는 하이퍼파라미터인 rho를 추가하였다.
velocity의 영향력을 rho의 비율로 맞춰주는데 보통 0.9와 같은 높은 값으로 맞춰준다.
velocity에 일정 비율 rho를 곱해주고 현재 gradient를 더한다. 이를 통해 이제는 gradient vector 그대로의 방향이 아닌 velocity vector의 방향으로 나아가게 된다.
이를 통해 많은 것을 해결할 수 있다.
예를 들어 공이 경사면을 굴러온다고 해보자. 공이 떨어지면 속도는 점점 빨라진다. 이 공은 local minima에 도달해도 여전히 velocity를 가지고, saddle point에서도 여전히 velocity를 가지기 때문에 gradient가 0이어도 움직일 수가 있다.
noise 문제도 해결할 수 있다. 위의 그림에서 검은색이 일반 SGD이고 파란색이 momentum SGD이다. momentum을 추가해서 velocity가 생기니 noise가 평균화되는 것을 볼 수 있다.
업데이트가 빠르게 되지 않는 경우 즉, 지그재그로 움직이는 상황이었던 반면 momentum이 이 변동을 서로 상쇄시킬 수 있다. 이를 통해 loss에 민감한 수짓 방향의 변동은 줄여주고, 수평방향의 움직임을 가속화시킨다.
velocity의 초기값은 항상 0 이다. 이는 하이퍼파라미터가 아니라 그저 0으로 두는 것이다.
좀 더 직관적으로 보면 velocity는 이전 gradient들의 weighted sum이다.
그리고 더 최근의 gradient에 가중치가 더 크게 부여된다. 매 스텝마다 이전 velocity에 rho=0.9 or 0.99를 곱하고 현재 gradient를 더해준다. 시간이 지날수록 이전의 gradient들은 영향력이 감소된다.
momentum의 변형으로 nesterov momentum이라는 것이 있다. 계산하는 순서를 조금 바꾼 형태이다.
현재 지점에서의 gradient를 계산한 뒤 velocity를 섞는 기본 SGD momentum에 비해
nesterov는 우선 velocity 방향으로 움직인 후, 그 지점에서의 gradient를 계산하고, 다시 원점으로 돌아가서 둘을 합친다.
nesterov momentum의 식은 다음과 같다.
velocity를 업데이트하기 위해서 이전의 velocity와 (x + pv)에서의 gradient를 계산한다.
그 후 앞서 계산한 velocity를 이용하여 업데이트한다.
기존에는 loss와 gradient를 같은 점(xt)에서 구했다. 그러나 nesterov는 이 규칙을 조금 비틀었다.
하지만 공식을 조금 변형하여 변수들을 적절히 잘 바꿔주면 loss와 gradient를 같은 점에서 계산할 수 있다.
위의 공식을 보면, 첫번째 수식은 기존의 momentum과 동일하다. (xt+pvt)와 같이 velocity와 계산한 gradient를 일정 비율로 섞어준다.
두번째 수식에서 아래 식을 보면 현재 점(xt)와 velocity(vt+1)를 더한다.
거기에 (현재 velocity - 이전 velocity) * rho 를 더해준다. 이는 현재/이전의 velocity간의 에러보정 term 이다.
momentum 방법은 velocity의 영향으로 인해 minima를 그냥 지나친다. 하지만 스스로 경로를 수정하여 결국 수렴한다.
Nesterov 방법은 추가된 수식 때문에 momentum과 조금 다르게 움직인다. 일반 momentum에 비해 overshooting이 덜하다.
Nesterov momentum은 convex optimization에서는 뛰어난 성능을 보이지만 neural network와 같이 non-convex optimization에서는 성능이 보장되지 않는다.
Q. momentum의 경우 만일 minima가 엄청 좁고 깊은 곳이라면 오히려 지나치는 현상이 있을 수 있지 않나?
=> 사실 좁고 깊은 minima는 좋은 모델이 아니다. 이는 더 심한 overfit을 불러오기 때문이다. 우리가 원하는 minima는 아주 평평한 minima, 즉 더 일반화를 잘하고 강인한 모델이다.
AdaGrad
이는 훈련 도중 계산되는 gradient를 활용하는 방법이다. 학습 도중 계산되는 gradient를 제곱해서 더해준다. 업데이트할 때 update term 앞에 다시 제곱항으로 나누어주어 step_size를 줄여준다.
small dimension에서는 gradient의 제곱 값의 합은 작다. 이 작은 값이 나눠지므로 속도가 빨라진다.
반대로 large dimension에서는 gradient가 크다. 따라서 큰 값이 나눠지므로 속도가 줄어든다.
AdaGrad에는 문제가 하나 있다. update 동안 gradient의 제곱이 계속 더해지므로 grad_squared는 서서히 상승한다. 그렇게 되면 나눠지는 값이 점점 커지기 때문에 step_size가 점차 작아지게 된다.
손실함수가 convex(볼록)한 경우에 step size가 점점 작아지는 것은 좋은 특징이다.
하지만 non-convex인 경우 saddle point에 걸리면 학습이 멈춰질 수 있다.
RMSProp
RMSProp는 AdaGrad의 변형으로 앞서 언급한 step_size의 감소를 개선시켰다.
RMSProp에서는 gradient 제곱 항은 그대로 사용하고 기존의 누적 값에 decay_rate를 곱해주고, 현재의 gradient의 제곱에 (1-decay rate)를 곱해서 더해준다.
이 값은 momentum 수식과 유사하나 gradient 제곱을 계속 누적한다는 것이 차이점이다.
RMSProp에서 쓰는 decay rate는 보통 0.9 or 0.99를 사용한다.
dacay rate를 사용함으로써 점차 속도가 줄어드는 것을 해결하였다.
momentum의 경우 overshoot한 뒤에 다시 돌아오는 형태지만, RMSProp는 각 차원마다의 상황에 맞도록 적절하게 귀적을 수정시킨다.
일반적으로 Neural Network를 학습시킬 때 AdaGrad는 잘 사용하지 않는다.
Adam
momentum 과 AdaGrad/RMSProp 방식을 조합한 방법이다.
Adam은 first moment 와 second moment를 이용해서 이전의 정보를 유지시킨다.
first moment는 gradient의 가중 합이다. second moment는 AdaGrad나 RMSProp처럼 gradient의 제곱을 이용한다.
Adam으로 업데이트하게 되면 first moment는 velocity를 담당한다. second moment는 sqrt 씌워져 나눠진다.
이 수식에서 10e-7은 앞에서도 등장하는 것과 같이 second moment가 0일 경우 나눗셈이 오류가 난다. 이를 방지하게 위해 약간의 값을 더해주는 것이다.
이 알고리즘에도 문제가 하나 존재한다.
초기 step에서 second moment를 0으로 초기화한다. 1회 업데이트하고 나면 beta2는 decay_rate로 0.0 or 0.99이다. 그래서 second moment는 여전히 0에 가깝다.
0에 가까운 값을 나눠주기 때문에 초기 step은 엄청 커지게 된다.
이 때 중요한 것은 이 커진 step이 손실함수가 가파르기 때문이 아니라 0으로 초기화시켜서 발생하는 인공적인 현상이다.
Adam의 문제를 해결하기 위해 보정하는 항(bias correction)을 추가한다.
first/second moment를 계산한 후 현재 step에 맞는 적절한 unbias term을 계산해준다.
Adam은 실제로 엄청 많이 사용되고 기본 알고리즘으로 사용되고 있다.
특히 beta_1 = 0.9, beta_2 = 0.999로 설정하고 learning rate = 1e-3 or 1e-4로 설정해주면 거의 모든 architecture에서 잘 동작한다.
그림과 같이 momentum과 RMS 를 섞어놓은 듯한 모습을 보인다. 약간의 overshoot와 RMS와 같이 각 차원의 상황에 따라 고려해서 step을 이동한다.
Q. Adam이 해결하지 못한 문제는 무엇인가? => 손실함수가 타원형일 경우 adam을 이용하면 각 차원마다 적절하게 속도를 높히고 줄이면서 step을 조절할 것이다. 하지만 이타원이 축 방향으로 정렬되지 않고 기울어져 있다면 다루기 힘들어질 것이다.이는 다른 알고리즘도 마찬가지다.
지난 강의에서 봤듯이 learning rate는 중요하지만 잘 고르는 것은 어렵다. lr이 지나치게 높으면 솟구치고, 너무 낮으면 수렴하는데 오래걸린다.
lr을 잘 고르기 위한 방법으로 Learning rate decay 전략을 사용할 수 있다.
각각의 learning rate의 특성을 적절히 이용하는 것이다.
처음에는 lr을 높게 설정한 다음 학습이 진행될수록 lr을 점점 낮추는 것이다.
혹은 exponential decay 처럼 꾸준히 lr을 낮추는 방법도 있다.
이와 같이 loss가 평평해지다가 다시 내려가고를 반복할 수도 있다.
ResNet 논문에서는 step decay learning rate 전략을 사용한다.
평평하다가 갑자기 내려가는 구간에서 learning rate를 낮춘다. 수렴을 잘하고 있는 상황에서 gradient는 점점 작아진다. 이 경우는 learning rate가 높아서 발생하기 때문에, learning rate를 낮춰서 지속적으로 loss가 내려갈 수 있도록 만든다.
learning rate decay는 부가적인 하이퍼파라미터다. 일반적으로 학습 초기부터 이것을 고려하지는 않는다. cross-validation 할 때 lr과 decay 모두를 생각하면 너무 복잡해진다.
그래서 일단은 decay없이 learning rate만을 사용해서 학습시켜본다. loss curve를 보다가 decay가 필요한 곳이 어딘지 관찰한다.
사실 이 방법은 Adam 보다는 SGD momentum에서 더 자주 쓴다.
위의 optimization 알고리즘들은 1차 미분을 활용한 방법이었다.
빨간 점에서의 gradient를 계산하고, gradient 정보를 이용해서 손실함수를 선형함수로 근사시킨다. 이는 1차 테일러 근사에 해당한다.
2차 근사 정보를 활용하는 방법도 있다.
이는 2차 테일러 근사 함수가 될 것이고, 2차 근사를 활용하면 minima에 더 잘 근접할 수 있다. 이것이 2nd-order optimization의 기본 아이디어다.
위의 예시를 다차원으로 확장시킨 것이 Newton step이다. 2차 미분값들로 된 행렬인 Hessian matrix를 계산하고 Hessian matrix의 역행렬을 이용하면 실제 손실함수의 2차 근사를 이용해 minima로 바로 이동할 수 있다.
이론적으로 newton method에서는 learning rate는 필요없고 매 step마다 항상 minima를 향해 이동한다. 하지만 실제로는 2차 근사도 사실상 완벽하지 않기 때문에 learning rate가 필요하다.
우리는 minima로 이동하는 것이 목적이지 minima의 방향으로 이동하는 것이 목적이 아니기 때문이다.
불행하게도 newton method는 deep learning에는 사용할 수 없다. Hessian matrix는 N x N(N: network의 파라미터 수) 행렬이므로 N이 1억이면 1억의 제곱만큼 존재한다. 이를 메모리에 저장할 방법도 없고 역행렬 계산도 불가능하다.
그래서 실제로는 quasi-Newton methods(BGFS) 를 사용한다.
Hessian matrix를 그대로 사용하지 않고 근사시킨다. low-rank approximation(낮은 단계로의 근사)하는 방법이다.
L-BFGS(limited memory BFGS)도 Hassian을 근사시켜서 사용하는 방법이다. 그러나 L-BFGS는 2차 근사가 stochastic case에서 잘 동작하지 않고, non-convex에도 적합하지 않기 때문에 DNN에서 잘 사용하지 않는다.
하지만 full batch update가 가능하고 stochasticity가 적은 경우 L-BFGS가 좋은 선택이 될 수 있다.
Regularization
결론적으로 optimization 알고리즘들은 training error을 줄이고 손실함수를 최소화시키기 위한 역할을 수행한다.
하지만 우리는 train error가 아닌 한번도 보지 못한 데이터에 대한 성능이 더 중요할 것이다. 즉, train/test error의 격차를 줄여야 한다.
ensemble
한번도 보지 못한 데이터에 대한 성능을 올리기 위한 방법으로 가장 빠르고 쉬운 길은 model ensemble이다.
machine learning 에서는 종종 사용하는 기법이다. 모델을 하나만 학습시키지 않고 10개의 모델을 독립적으로 독립적으로 학습시킨다. 결과는 10개 모델 결과의 평균을 이용한다.
모델이 늘어날수록 overfitting은 줄어들고 성능은 조금씩 향상된다.
좀 더 창의적인 방법으로는 학습 도중 중간 모델들을 저장(snapshots)하고 ensemble을 사용하고, test time에는 여러 snapshot에서 나온 예측값들을 평균내서 사용하는 방법이 있다. 이 기법을 사용하면 모델을 한 번만 train시켜도 좋은 성능을 얻는다.
모델마다 다양한 learning rate, model size, regularization 을 사용하여 ensemble할 수 있다.
Polyak average
또 다른 방법으로는 학습하는 동안에 파라미터의 exponentially decaying average를 계속 계산한다. 이를 통해 학습중인 네트워크의 smooth ensemble 효과를 얻을 수 있다.
step마다 파라미터를 그대로 쓰지 않고 smoothly decaying average를 사용하는 방법이다.
성능이 조금 향상될 수 있다. 시도해볼만한 방법이지만 실제로는 자주 사용하지는 않는다.
위의 방법들은 ensemble 성능을 향상시키는 것들이었고, 단일 모델의 성능을 향상시키기 위해서는 어떻게 해야 할까?
Regularization
단일 모델의 성능을 올리는 방법은 Regularization 이다. regularization은 training data에서 overfitting 되는 것을 막아준다. 또 한번도 보지 못한 데이터에서의 성능을 향상시키는 방법이다.
앞서 봤듯이 loss에 추가적인 항을 삽입하는 방법이 있다. 손실함수에서 기존의 항(앞 항)은 training data에 fit하려 하고, 다른 하나(뒷 항)는 regularization term이다.
L2 regularization은 NN에 어울리지 않는다. 때문에 조금 다른 방법인 dropout을 사용한다.
forward pass과정에서 임의로 일부 뉴런을 0으로 만든다. dropout은 forward pass iteration마다 모양이 계속 바뀐다. conv layer에서 일부 채널 자체를 dropout시킬수도 있다.
dropout은 FC, conv layer 등 다양하게 쓰인다.
1
2
3
keras.layers.Dense(1024, activation="relu")
keras.layers.Dense(10,activation="softmax")
keras.layers.Dropout(0.25)
이와 같이 맨 마지막 단에 추가한다.
dropout을 적용하면 특징들 간의 상호작용을 방지하기 때문에 성능이 좋아지고, 네트워크가 일부 feature에만 의존하지 못하게 만들어 다양한 feature을 고루 이용할 수 있도록 만든다.
그렇기 때문에 overfitting도 방지시켜준다.
최근 연구에서는 dropout이 앙상블 효과를 가져올 수 있다고 한다. dropout을 적용하게 되면 뉴런의 일부만 사용하는 또다른 네트워크를 학습할 수 있게 되는 것이다. 서로 파라미터를 공유하는 서브네트워크 앙상블을 동시에 학습시키는 것으로 볼 수 있다.
dropout을 사용하게 되면 test time에는 Neural Network의 동작 방식이 변하게 된다. 기존 NN은 가중치 w와 입력 x에 대한 함수 f가 있다. dropou을 사용하면 NN에 random dropoutmask라는 임의의 입력값 z가 추가된다.
하지만, test time에는 임의의 값을 넣는 것은 좋지 않다. 분류하는 문제에서 결과가 매번 다르게 나온다면 좋지 않기 때문이다. 따라서 test할 때는 적분을 통해 randomness를 없앤다.
하지만 실제로는 이 적분을 다루기는 매우 어렵다. 그래서 z를 여러번 샘플링하여 적분을 근사시킨다.
문제는, 이 방법도 마찬가지로 임의성을 없애지 못한다는 것이다.
그래서 dropout을 진행할 때 일종의 locally cheap한 방법을 사용하여 이 적분식을 근사화시킨다.
예를 들어 출력이 a이고 입력 x,y 가 있고, 가중치 w1,w2가 있는 뉴런이 있다고 하자. test 에서 a는 w1x + w2y 이다.
이 네트워크에 dropout(p = 0.5)를 적용해서 train을 진행해보자.
train time에서의 기댓값은 다음과 같이 계산할 수 있다.
dropout mask에는 4가지 경우의 수((w1,w2),(w1,0),(0,w2),(0,0))가 존재하고, 그 값을 4개의 마스크에 대해 평균화시킨다.
1
2
a의 기댓값 : E(a) = 1/4(w1*x+w2*y) + 1/4(w1*x+0*y) + 1/4(0*x+w2*y) + 1/4(0*x+0*y)
= 1/2(w1*x+w2*y)
이 부분에서 train/test 간의 기댓값이 서로 상이하다. train의 기댓값은 test의 절반밖에 안된다.
따라서 이 둘의 기댓값을 같게 만들기 위해 네트워크 출력에 dropout 확률 p를 곱해준다.
이 방법은 이전의 적분식을 쉽게 근사화할 수 있는 방법이기에 많이 사용된다.
dropout에 대해 요약하자면 forward pass에 dropou을 추가시키는 것은 간단하다. 일부 노드를 무작위로 0으로 만들어줄 2줄이면 충분하다.
그리고 test time에서는 그저 p 만 곱해주면 된다.
- inverted dropout
dropout을 역으로 게산하는 방법은 상당히 간단하고 효율적이다.
test time에서는 계산 효율이 중요하므로 곱하기 연산 하나를 추가하는 것은 좋지 않다.
따라서 test 시에는 그대로 사용하고 train time에서 p를 나눠준다.
Q. dropout을 사용하면 train ime에서 gradient에는 어떤 일이 일어날까? => dropout이 0으로 만들지 않는 노드에서만 backpropagation이 발생하고, 각 스텝마다 업데이트되는 파라미터의 수가 줄어든다. 따라서 dropou을 사용하면 전체 학습시간은 늘어나지만 모델이 수렴한 후에는 더 좋은 성능을 얻을 수 있다.
dropout은 일반적인 regularization의 한 예다.
regularization의 과정은 1. train time에는 네트워크에 임의성을 추가해 training data에 overfit하지 않도록 한다. 2. test time에서는 임의성을 근사화시켜 일반화한다.
batch normalization도 이와 비슷한 동작을 한다.
train time에서 BN은 하나의 데이터를 mini batch로 샘플링하여 매번 서로 다른 데이터들과 만나게 한다. 샘플링된 데이터에 대해서 이 데이터를 얼마나 어떻게 정규화시킬 것인지에 대한 확률성(stochasticity)이 존재했다.(γ,β)
반면 test time에서는 정규화를 전체 데이터 단위로 수행함으로써 확률성을 평균화시킨다. 이 특성을 통해 regularization 역할을 수행한다.
따라서 BN을 사용할 때는 dropout을 사용하지 않는다.
Data Augmentation
regularization 역할을 수행하는 또 다른 전략이다.
기본적인 학습은 데이터와 레이블을 통해 매 스텝마다 CNN을 업데이트했다.
하지만 그 대신 레이블은 그대로 놔둔 채 이미지를 무작위로 변환시켜 학습을 시킬 수 있다.
이 방법을 통해 원본 이미지가 이닌 무작위로 변환된 이미지를 새롭게 학습할 수 있는 것이다.
이미지를 상하좌우 반전이나 다양한 사이즈로 자른다. 이 이미지가 의미하는 바는 바뀌지 않는다.
test time에서 임의성을 없애기 위해 각 모서리 4군데와 중앙에서 잘라낸 이미지, 이것들을 반전한 이미지를 사용한 성능과 원래의 성능과 비교하기도 한다.
다른 방법으로는 색 변조를 하는 방법이 있고, 더 복잡한 방법으로는 PCA의 방향대로 이미지를 샘플링하여 color offset을 학습하기도 한다.
이외에도 여러가지 방법들이 존재한다. 이와 같은 방법들을 사용하여 입력 데이터를 임의로 변환시켜 학습하면 regularization 효과를 얻어 성능을 향상시킬 수 있다.
- DropConnect
dropout과 유사한 방법으로 activation이 아닌 weight matrix를 임의적으로 0으로 만들어주는 방법이다.
dropout과 동작도 비슷하다.
- Franctional max pooling
사람들이 자주 사용하지는 않지만 괜찮은 방법이다.
보통 2x2 maxpooling 은 고정된 2x2 지역에서 연산을 수행한다.
하지만 이 방법의 경우 pooling연산을 수행할 지역을 임의로 선정한다.
train time에서는 임의의 region이 존재할 수 있다. 하지만 test에서는 임의성을 제거하기 위해 pooling region을 고정시켜 버리거나 여러개의 pooling region을 만들어 평균화시킨다.
Stochastic Depth
2016년에 나온 논문으로 깊은 네트워크가 있다고 가정해보자.
train time시에 네트워크의 레이어를 random하게 drop한다. layer 중 일부가 제거된 채로 학습하는 것이다.
test time에서는 전체 네트워크를 다 사용한다.
획기적인 방법이나 dropout과 비슷한 효과를 보인다.
Transfer Learning
모델을 빠르게 학습시킬 수 있는 방법으로 미리 학습된 모델을 불러와 사용한다.
imageNet에서 잘 학습된 features를 우리가 가진 작은 데이터셋에 적용시킨다.
일반적인 과정은
1) 가장 마지막의 FC layer은 최종 feature과 class score간의 연결이므로 이를 초기화시킨다.
2) imageNet을 학습시킬 때는 4096 x 1000 차원의 행렬이다. 하지만 우리가 사용하는 것은 4096 x 10 이므로 바꿔준다.
3) 가중치 행렬은 초기화시키고, 나머지 이전의 모든 레이어들의 가중치는 freeze시킨다.
4) 이렇게 되면 linear classifier를 학습시키는 것과 같다. 마지막 레이어만 가지고 우리 데이터를 학습시키는 것이다.
이 방법을 사용하면 아주 작은 데이터셋일지라도 아주 잘 동작하는 모델이 된다.
만일 데이터가 조금 더 많다면 전체 네트워크를 fine-tuning할 수 있다.
최종 레이어들을 학습시키고 나면, 네트워크의 일부만이 아닌 네트워크 전체의 학습을 진행할 수도 있다. 보통 기존의 learning rate보다 낮춰서 학습시킨다. 왜냐하면 기존의 가중치들이 이미 imagenet에 잘 학습되어 있고, 이 가중치들이 대게 잘 동작하기 때문이다.
transfer learning을 수행함에 있어 위의 4가지 시나리오를 예상해볼 수 있다.
- 현재의 데이터셋이 ImageNet과 유사하지만 소량의 경우:
- 기존 모델의 마지막 레이어만 학습시키는 편이 좋다.
- 데이터가 조금 더 많고, imageNet과 유사한 경우:
- 모델 전체를 fine tuning
- X-ray / CAT scans 과 같은 의료영상처럼 ImageNet과 다르며 데이터가 그나마 많은 경우:
- 더 많은 레이어를 fine tuning
요즘에는 transfer learning은 일반적인 경우로 많이 사용되고 있다.
따라서 자신의 task와 유사한 데이터셋으로 학습된 pretrained model을 확인하고 다운받는다.
그리고 이 모델의 일부를 초기화시키고 자신의 데이터로 모델을 fine tune 한다.