juuuding

[CS231n] Lecture 6. Training Neural Networks, Part 1 본문

인공지능/cs231n

[CS231n] Lecture 6. Training Neural Networks, Part 1

jiuuu 2024. 1. 25. 15:40

 지금까지 Mini-batch SGD(Stochastic Gradient Descent) 즉 데이터의 일부를 샘플링하여 순방향 전파로 loss 값을 구한 후 역전파로 경사를 계산하고, 이것을 이용하여 parameters을 update하는 방법을 사용해왔다. 이제 여기서 사용하는 nerual network를 훈련시키는 방법에 대해 알아볼 것이다. 

 

 Overview

 

1. One time setup

 - activation functions (활성화 함수)

 - preprocessing (전처리)

 - weight initialization (가중치 초기화)

 - regularization (정규화)

 - gradient checking (경사 확인)

 

2. Training dynamics

 - babysitting the learning process

 - parameter updates

 - hyperparameter optimization

 

3. Evaluation

 - model ensembles

 

 

 

 1. One time setup

 

[Activation Functions]

 fully connected 혹은 convolutional layer을 activation funtion에 입력하여 결과를 얻게 된다. 여기서 어떤 activation function을 고를 것인지 잘 선택해야하는데, 아래의 activation functions들의 장단점을 살펴본 후 최적의 activation function을 골라보도록 하자. 

 

activation functions

 

① sigmoid

 

 

 수를 0과 1사이의 범위로 놓는 방법이다. 예전에 인기가 많았던 활성화 함수지만 지금은 3가지 문제 때문에 잘 사용하지 않는다. 첫번째 문제는 saturated neurons이 gradient를 "kill"하는 것이다. 아래의 그래프에서 x가 각각 -10, 0, 10일 때 어떤 일이 발샐하는지 알아보자.

 

 

 x가 0일 때를 제외하고 10과 -10에서는 gradient가 0이 되는데, 이렇게 되면 backpropgation을 할 때 upstream gradient 값에 0에 가까운 수를 넣으면서 gradient들이 굉장히 작아지게 된다. 그러므로 gradient를 "kill" 하게 된다고 표현하는 것이다.

 sigmoid 함수의 두번째 문제는 결과가 zero-centered 하지 않다는 것이다. 결과 값이 zero-centered 하지 않은 것이 어떤 문제를 초래하는지 알아보기 위해 다음의 neuron(x)에 입력되는 값을 모두 양의 값으로 가정하자. 그렇게 되면 모든 local gradient의 값이 양의 값을 가지므로 gradient는 모두 + 혹은 모두 - 가 된다. 

 

 

 gradient 값이 모두 + 나 -가 되면 항상 같은 방향으로 gradient가 움직여 비효율적인 gradient update를 한다는 의미가 된다. 따라서 우리는 input x 가 zero centered가 되길 원해야한다. 

 세번째 문제는 sigmoid 함수의 수식에 사용되는 exp()가 compute expensive하다는 것이다. 이 문제는 앞의 두 문제에 비하면 minor하지만 어느 정도 단점이기에 결론적으로 sigmoid 함수를 activation function으로 잘 사용하지 않는다. 

 

② tanh(x)

 이 함수는 sigmoid와 비교하여 zero centered 문제는 해결되었지만 여전히 "kill gradients" 문제는 남아있다. 

 

 

③ ReLU (Rectified Linear Unit)

 ReLU는 앞의 함수들과 비교하여 x가 양의 값인 영역에서 saturate되지 않고, exponential을 사용하는 sigmoid에 비해 계산이 간단하고, sigmoid나 tanh에 비해 6배 정도 빨리 수렴하며 sigmoid보다 더 plausible하다는 장점이 있다. 따라서 앞의 함수들보다 꽤 흔히 사용되는데, 여전히 다음과 같은 몇가지 문제가 남아있다. zero-centered 하지 못하다는 문제와 x가 음의 값일 때 "kill gradient"한다는 것이다. 

 

 

 

 만약 weight를 잘못 초기화한다면 input data가 dead ReLU가 되어 wieght update가 되지 않는 상황이 발생한다. 또는 learing rate이 굉장히 큰 값을 가질 때 처음에는 괜찮다가 어느 지점에서 문제를 일으킬 가능성도 있다.

 이렇듯 ReLU는 input 값이 음의 값일 때 문제를 일으키기 때문에 사람들은 ReLU를 사용할 때 0.01과 같은 양의 값 bias를 사용하여 ReLU neuron을 초기화 하는 것을 좋아한다. 

 

④ Leaky ReLU

 이 함수의 장점은 ReLU와 비슷하며 추가로 input x가 음의 값일 때도 "kill gradient"하지 않는다는 장점이 있다.

 

 

⑤ Exponential Linear Units(ELU)

 

 ELU는 ReLU의 장점을 모두 가지며 별다른 문제가 없지만, exponential 계산이 필요하다는 점에서 약간의 계산적인 단점이 존재한다. 

 

⑥ Maxout "Neuron" 

 

 이 함수는 ReLU와 Leaky ReLU를 일반화시켜 이들이 가진 단점을 해결한 장점이 있다. 하지만 앞의 함수들과는 다르게 한 neuron 당 parameters 2배로 필요하다는 단점이 있다. 

 

※ 결론적으로 실전에서 activation funtion은 가장 일반적으로 잘 작동하는 ReLU 함수를 사용한다. 이 함수를 사용할 때는 learning rates 값 설정을 조심해야한다. 그리고 Leaky ReLU Maxout / ELU를 시도해보고 tanh도 시도해본다. 단 tanh를 사용할 때는 많은 기대를 하면 안된다. 여기서 가장 중요한 것은 sigmoid function 사용하지 말아야 한다는 것이다!! 

 

 

[Data Preprocessing]

 일반적으로 전처리는 input data를 zero mean으로 만들거나 표준화하는 것이다. activation function을 공부할 때도 보았듯이 input 값이 zero-centered가 되지 않으면 local gradient가 한가지 부호의 값을 가지므로 gradient 값이 모두 +가 되거나 -가 되어 문제가 발생한다. 

 

 

 데이터를 표준화하는 것은 모든 feature을 어떤 범위안에 놓음으로써 feature이 동등하게 contribute하도록 만드는 것이다. 

 실전에서는 또한 PCA(Principle Componenet Analysis) 나 Whitening을 볼 수 있는데, PCA는 성분 간 중복을 제거하는 것이고 Whitening은 평균이 0이면서 공분산이 단위행렬인 정규분포 형태의 데이터로 변환시키는 것이다. 여기서 공분산이 단위행렬이라는 것의 의미는 서로 다른 feature끼리의 연관성이 없는 상태로 데이터를 전처리하는 것을 말하는 것이다.

 

 

※ 결론적으로 전처리 과정에서는 data를 zero-centered data로 만들어주기만 하면 된다. data를 zero-centered로 만드는 방법은 두가지가 있다. 첫번째는 training 이미지의 모든 채널에서 구한 mean으로 "each image - mean image"를 하여 zero-centered를 해주는 것이다.(e.g. AlexNet). 두번째는 training 이미지의 각 채널마다 따로 3가지 mean을 구하여(32*32*3 이미지인 경우) "red image - red mean imge", "green image - green mean image", "blue image - blue mean image"를 각각 구해주는 것이다. 참고로 위에서 본 PCA나 whitening과 같은 표준화 과정은 흔히 사용하지 않는다. 그리고 이 전처리 과정은 training을 수행하기 전에 진행하며, test 단계에서도 전처리된 데이터를 가지고 test를 진행한다.

 

 

[Weight Initialization]

 

Q) W=0으로 초기화하면 어떤 일이 발생할까?

 - 모든 output이 같아지고 gradient가 같아지면서 모든 뉴런이 같은 것임을 얻게 된다. 

 

 1st idea) Small random numbers

평균이 0, 표준편차가 0.01인 gaussian

 

   이 경우는 small networks에서는 잘 작동하지만 deeper networks에서는 문제가 발생하게 된다. 

 

 

 

 이처럼 w를 small random number로 설정하면 모든 activation이 0이 된다. 이렇게 되면 backprop을 진행할 때 upstream gradient가 점점 zero가 되면서 w는 update되지 않는 문제가 발생한다. 

 

 위의 코드에서 w값에 0.01을 곱하는 대신 1.0을 곱하여 보자.

 

 

 1.0 이라는 비교적 큰 수를 넣으면 모든 뉴런이 saturated 하게 된다. tanh에서 saturated 되면 gradient는 zero가 되므로 weights는 update되지 않는다. 

 

 따라서 weight을 너무 작거나 크게 초기화하면 weight이 update 되지 않는 문제가 발생한다. 

 

 2nd idea) Xavier initialization 

 이 아이디어는 작은 input은 작은 수로 나누기를 하여 큰 weight를 얻게 하는 방법이다. 이 방법을 사용하면 small input에 large weight을 사용할 수 있어 결과가 좋아진다. 

 

 

 위의 결과는 activation function이 tanh일 때이다. 하지만 activation function이 ReLU일 때는 input 값이 음수인 nonlinearity 부분에서 문제가 발생한다. 

 

 

 3rd idea) addtional/2

 이 아이디어는 input의 1/2 값을 나눠주어 activation function이 ReLU일 때 발생하는 문제를 해결해주는 방법이다. 

 

 

 

* Proper initialization is an active area of research...

 

 

 

[Batch Normalization]

"batch normalization"은 activation을 gaussian range에 두는 것이다. 

 

* loffe and Szegedy, 2015

 weights를 초기화 하는 대신 training을 시작할 때 아래의 수식에 x 값을 대입하여 모든 layer에서 unit gaussian activation을 가질 수 있게 하는 것이다. 

 

 

 batch normalization은 주로 Fully Conntected or Convolutional layers 후, nonlinearity 전에 넣는다. convolutional layers에서는 한 activation마다 하나의 평균, 하나의 표준편차를 가지는데 이것을 가지고 각각 normalization을 진행한다. 

 

 

 

* batch normalization 잘 모르겠음..

 

 

 

 2. Training dynamics

 

[Babysitting the Learning Process]

 어떻게 training을 monitor하고 hyperparameters를 조절하는지에 대해 알아보자. 

 첫 단계로 데이터를 전처리 한 후 neural network의 구조를 선택한다. 지금 예시에서는 하나의 hidden layer에 50개의 뉴런이 있는 구조를 선택한다. 

 

 

 그리고나서는 loss 값이 reasonable한지 두 번 체크한다. 처음에는 regularization을 적용하지 않기 위해 0.0으로 설정한다. 그리고 두 번째 체크에서는 regularization을 높여 0.003으로 설정한다. regularization을 적용하였기 때문에 첫 번째 결과보다는 loss 값이 증가해야한다. 

 

 

 이제 training data의 small portion으로 overfit이 가능한지 확인한다.(loss 값을 0으로 만들 수 있는지 확인하기 위하여) training data의 앞에서 20번째까지의 예시들로 tiny training data를 고르고 regularization은 적용하지 않으며 simple vailla sgd를 사용한다. 

 

 

 결과로 train accuracy기 1이 나오고, loss 값이 아주 작으므로 성공적으로 overfit이 되었다. 

 두번째로 sanity checks을 진행한다. regularization을 아주 작게 설정하고 loss를 아주 작게 만들 수 있는 learning rate를 찾아주어야 한다. 

 

① lr : 0.000001 (1e-6)

 

 

 결과를 보면 loss가 거의 변화하지 않았다는 것을 알 수 있다. 이것으로 현재 설정한 Learning rate이 너무 작다는 사실을 알 수 있다. 또, 여기서 주목해야할 것은 training accuracy와 validation accuracy가 20% 정도로 아주 빠르게 올랐다는 사실이다. 이렇게 된 이유는 이것이 softmax classifier이기 때문인데, softmax는 svm과 다르게 값이 조금만 바뀌어도 결과가 크게 바뀐다. 이 사실로 알 수 있는 것은 loss가 거의 변화하지 않았지만 train/val의 정확도가 오른 것을 봐서 조금이지만 weight가 올바른 방향으로 update 되고 있다는 것이다. 그래서 이 값을 maximum correct value로 잡으면 된다. 

 

 lr : 1e6

  

 

 이 결과에서는 loss 값이 nan으로 뜨는데, 이것은 learning rate가 너무 높을 때 발생하는 경우로 볼 수 있다. 

 

③ lr : 3e-3

 

 

 loss 값이 inf가 되는 것을 보아 이 learning rate도 너무 높은 값이라는 것을 알 수 있다. 

 

 위의 실험 결과를 토대로 대략적으로 learning rate의 범위를 [1e-3...1e-5]로 잡는다.

 

 

[Hyperparameter Optimization]

 가장 최적의 hyperparameter 값을 골라보도록 하자.

 

 Cross-validation strategy

  training set에서 training을 하고 validation set에서 이것을 평가하는 방법이다. 첫번째 단계에서는 epoch를 아주 작게 잡고 param에 대한 대략적인 아이디어를 얻는다. 그 후 다음 단계에서는 epoch를 크게 잡고 어떠한 param에서 잘 작동하는지 확인한다. 결과가 잘 나올 때까지 이 단계를 반복하면 된다. 여기서 팁은 코드를 실행시켰을 때 cost가 원래 cost의 3배 이상으로 나오면 이 실행을 중단 시키는 것이다. cost > 3*original cost은 explosion을 뜻한다. 

 

 Ex)

 

1단계

 

1단계에서 좋은 accuracy 결과를 얻은 lr과 reg 값을 참고하여

다음 단계에서 범위를 조절한다.

2단계

 

Random Search vs. Grid Search

 

 

 그리드 서치는 모든 경우를 테이블로 만들어 그리드로 탐색하는 방식이고, 랜덤 서치는 hyperparam 값을 랜덤하게 넣어보고 그 중 우수한 성능을 보인 hyperparam 값을 고르는 것이다. 우리는 랜덤 서치에서 전반적으로 더 유용한 signal을 얻을 수 있다. 

 

 

 

+ (weight updates / weight magnitudes) 비율은 약 0.001 정도로 하는 것이 좋음.

 

 

 

 Summary