[CS231n] 6. Training Neural Networks (1)

업데이트:

Reference


이 포스팅은 CS231n의 6강을 요약한 글입니다 😊

이번 시간에는 아래의 내용들을 배웁니다.

  • Activation Functions
  • Data Preprocessing
  • Weight Initialization
  • Batch Normalization
  • Babysitting the Learning Process
  • Hyperparameter Optimization

1. Activation Functions

지난 시간에는 CNN에 대해 배웠습니다. Conv Neural Network를 보면 노드의 출력값을 곧바로 다음 layer로 전달하지 않고 Activation function이라고 불리는 비선형 함수에 통과시키곤 했는데요, 이는 뉴럴 네트워크의 층을 깊게 만들기 위해서입니다.

FC layer나 Conv layer 모두 선형연산이기 때문에 여러층의 layer를 쌓는다고 해도 사실상 의미가 없습니다.

y = c(ax + b)를 보면 y = ax + b라는 식과 y = cx라는 두 개의 layer를 쌓은 거지만, 사실상 하나의 layer나 다름없음

따라서 뉴럴 네트워크에서는 네트워크를 보다 복잡하게 하기 위해 activation function을 사용하여 비선형 연산을 하곤 합니다.

다음은 다양한 activation function입니다. 하나씩 차차 알아보도록 합시다 😀

(1) Sigmoid function

첫번째 함수로는 가장 대표적인 Activation function인 sigmoid 함수입니다.

sigmoid function은 입력값을 0과 1사이의 값으로 바꿔주며, input이 크면 출력은 1에 가깝고 input이 작으면 출력은 0에 가깝습니다. 또한, 0부근은 선형 함수와 비슷합니다.

sigmoid는 뉴런의 firing rate를 saturation하는 것으로 볼 수 있기 때문에 relu(생물학적으로 가장 비슷함)와 마찬가지로 유명합니다.

Problem

다만, sigmoid function에는 문제가 많습니다.

  1. Saturation이 되어 gradient가 사라집니다.

    • Sigmoid function을 computation graph로 보면, back-propagation의 과정에서 chain-rule이 적용됩니다. 근데 x는 -10, 10처럼 매우 작거나 큰 값에서는 gradient는 0이 되어 소실됩니다.
  2. sigmoid의 출력값은 zero-centered하지 않습니다.

    • 만약 뉴런의 입력이 항상 양수라면 gradient는 항상 양수거나 음수가 됩니다.(늘 같은 방향으로 움직임)
    • 즉, 파라미터를 업데이트 할 때 항상 증가하거나 감소하는 방향으로만 학습됩니다.

    • 만약의 위의 예제에서 파란색 선이 최적의 가중치 vector(w)라고 할때, gradient는 이 방향으로 학습을 할 수 없게 됩니다.(1 or 3사분면에서만 학습이 됨)

    • 그렇기 때문에 빨간색 화살표처럼 여러번의 gradient 업데이트를 수행하여 학습을 해야합니다. (빨간색 화살표는 gradient가 이동가능한 방향)

  3. exp()계산으로 인해 computation 이 복잡해집니다.

(2) tanh function

다음은 sigmoid의 zero-centered 문제를 개선한 tanh함수입니다. 이 함수는 sigmoid보다는 낫지만 saturation문제를 해결하지 못했다는 단점이 있습니다.

(3) RELU function

RELU는 $f(x) = max(0,x)$ 함수로 CNN에서도 많이 쓰입니다.

이 함수는 늘 element-wise 연산을 수행하며, 양수에서는 saturation되지 않습니다. 또한, exp()처럼 연산이 복잡하지 않습니다. 실제로 연산 속도가 sigmoid나 tanh보다 6배나 빠릅니다.

Problem

다만 sigmoid의 문제점이었던 zero-centered의 문제를 해결하지 않았고, 음수의 경우에는 여전히 saturation이 발생합니다.

  • dead RELU문제

    입력 중 절반이 죽어버리는 dead RELU문제가 생깁니다.

  • dead RELU는 다음과 같은 경우에 자주 생깁니다.

    (1) 초기화를 잘못 시킨 경우 : 어떤 데이터를 입력해도 activate가 되지 않아 backprop 역시 안 생깁니다.

    (2) learning rate가 지나치게 큰 경우 : 이 경우에는 적절한 RELU로 시작했다고 하더라도 언제든지 dead RELU 상태로 갈 수 있게 됩니다.

  • 실제로도 RELU를 사용하는 경우 중 10~20%가 이 문제가 생깁니다.

(4) Leaky ReLU / PReLU

ReLU를 변형시킨 이 버전은 dying problem도 없으며, saturation도 되지 않습니다.

(5) ELU (Exponential Linear Units)

ELU는 Leaky Relu나 PRelu와 마찬가지로 zero-mean에 가까운 출력을 가진다는 이점이 있습니다.

다만, ELU는 음수에서 기울기를 가지는 대신에 saturation이 될 수 있습니다. ELU 논문에서는 이런 saturation이 noise에 더 강인함을 준다고 주장합니다.

ELU는 Leaky ReLU와 ReLU사이라고 생각하시면 좋을 것 같습니다 :)

(6) Maxout “Neuron”

GAN을 만든 이언 굿 펠로우가 제시한 방식입니다.

이 함수는 Leaky ReLU와 ReLU의 일반화된 방식이라고 생각하면 좋을 것 같고, 선형이기 때문에 saturation되지 않으며 gradient또한 kill되지 않습니다.


⭐ Summary

  • RELU를 사용하면 좋지만, learning rate를 잘 조절해야합니다.
  • Leaky ReLU / Maxout / ELU를 사용하는 것도 좋지만, 이는 아직 실험하는 단계입니다.
  • tanh 역시 괜찮지만, 보통은 Relu시리즈가 더 잘 작동합니다.
  • sigmoid는 사용하지 않는 편이 좋습니다

2. Data Preprocessing

가장 대표적인 전처리 과정은 zero-mean으로 만든 후 normalize하는 겁니다.

  • zero-mean : 모든 입력이 양수이거나 음수인 경우에는 gradient 역시 항상 양수이거나 음수여서 학습이 잘 안되곤 합니다. 따라서 이 경우를 피하기 위해서 평균을 0으로 만듭니다.
  • normalization : 데이터의 모든 차원을 동일한 범위 안에 넣어 데이터들이 전부 동등하게 기여를 할 수 있게 됩니다.

스케일이 다양한 여러 ML 문제의 경우에는 normalization이 중요하지만, 이미지는 그렇지 않기 때문에 실제로 이미지의 경우에는 zero-centering정도만 하고, normalization을 하지는 않습니다.

3. Weight Initialization

모든 가중치가 0이라면?

  • 만약에 모든 weight vector를 0으로 초기화하면 모든 뉴런은 같은 연산을 수행할 것이고, 출력과 gradient도 서로 같아집니다. 즉, 모든 가중치가 같은 값으로 업데이트 되기 때문에 학습이 이상하게 됩니다.

1) Small random number로 초기화

  • gaussian with zero mean and 1e-2 standard deviation

  • 매우 작은 수로 가중치를 초기화하면, 작은 네트워크에서는 괜찮지만 네트워크가 깊어질수록 문제가 생깁니다.

  • 위의 layer에서 사용한 tanh activation function은 zero-centered이므로 평균이 항상 0 근방에 있습니다.

  • 초기 layer에서는 가우시안 분포를 잘 따르지만, layer가 깊어질 수록 이 분포가 무너집니다. 가중치값이 너무나도 작은 값이라서 W를 곱하면 곱할 수록 출력값이 급격히 줄어듦.

  • backward를 하는 경우에도 forward와 유사합니다. 가중치를 업데이트 하는 과정에서 Wx를 W에 대해 미분하면 x가 되는데, x는 매우 작은 값이므로 이를 upstream gradient와 곱하면 결과값(최종 gradient)이 매우 작아져 gradient update가 잘 안될 것입니다.

2) 가중치의 편차를 0.01이 아니라 1로 초기화

가중치가 크면 tanh의 출력은 saturation되어 gradient는 0이 되고 가중치가 update되지 않습니다. (출력이 항상 -1이거나 1일 것)

3) Xavier initialization

Glorot가 2010년에 발표한 논문으로, 실제로 가장 널리 쓰이는 방식입니다.

다만, 이 방식은 Relu를 쓰면 잘 안됩니다. ReLU를 쓰면 relu가 출력의 분산을 반토막 내서 절반을 매번 0으로 만들기 때문입니다.

이 문제를 해결하기 위한 논문도 있습니다. 이 논문에서는 scaling할 때 추가적으로 2를 더 나눠줌으로써 뉴런의 절반이 날라가는 걸 예방합니다.

Proper initialization…

  • Understanding the difficulty of training deep feedforward neural networks by Glorot and Bengio, 2010 -
  • Exact solutions to the nonlinear dynamics of learning in deep linear neural networks by Saxe et al, 2013
  • Random walk initialization for training very deep feedforward networks by Sussillo and Abbott, 2014
  • Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification by He et al., 2015
  • Data-dependent Initializations of Convolutional Neural Networks by Krähenbühl et al., 2015 All you need is a good init, Mishkin and Matas, 2015

4. Batch Normalization

Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift

Sergey Ioffe, Christian Szegedy, 2015

  • BN는 실제로 굉장히 자주 사용하는 방식이기 때문에 이 논문을 읽는 것을 추천합니다 !

unit Gaussian activation을 사용하기 위한 또 다른 아이디어로는 Batch Normalization이 있습니다.

어떤 layer로부터 나온 batch단위 만큼의 activation이 있을 때, 이 값을 unit gaussian으로 만들어주기 위해 현재 batch에서 계산한 mean과 variance로 normalize를 시키는 방법입니다.

이렇게 하면, 가중치를 잘 초기화하지 않아도 학습시에 모든 layer가 unit gaussian이 됩니다.

batch당 N개의 학습데이터가 있고 각 데이터가 D차원이라고 할 때,

  1. 각 차원별로(feature element별로) 평균을 각각 구해줍니다.
  2. 이후 한 batch내에 이를 전부 계산해서 normalize합니다.

그리고 이 과정을 FC / Conv Layer 직후에 하도록 해서 deep network에서 bad scaling effect(계속해서 가중치가 곱해지는 것)가 발생하는 것을 막습니다.

Batch Normalization은 입력의 스케일을 살짝 조정해주는 역할을 하기 때문에 FC나 Conv어디에든 적용할 수 있습니다.

Conv Layer에서는 BN을 약간 다르게 해줍니다. Conv layer에서는 차원마다 독립적으로 normalization을 하지 않고, Activatoin map 내의 같은 channel에 있는 요소들을 한번에 normalize합니다.

즉, Conv layer에서는 Activation map의 channel마다 평균과 분산을 하나씩만 구합니다.

Normalization

이와 같이 우리는 FC layer를 거칠 때마다 normalization을 해줘서 tanh의 입력이 unit gaussian이 되도록 만들어주었습니다. 즉, tanh의 입력이 linear한 부분에만 있도록 해서 saturation이 일어나지 않도록 만들어주었습니다.

근데 사실 중요한 것은 saturation이 전혀 일어나지 않는 것이 아니라, “얼마나” saturation이 일어날지를 조정해주는 것입니다. 따라서 이를 위해 BN을 원상복구할 수 있게하는 파라미터를 구합니다.

다음은 BN하기 전으로 원상복구를 하는 식입니다. 이 식을 이용하면 네트워크가 데이터를 tanh에 얼마나 saturation시킬지를 학습하기 때문에 유연성을 얻을 수 있습니다.

BN은 gradient flow를 보다 원활하게 해주며, 이를 쓰면 learning rate의 값이 커도 괜찮습니다 :)

또한, BN은 regularization의 역할도 해줍니다. 따라서 nomalization을 하면 layer의 출력이 오직 하나의 샘플에 대한 deterministic한 값이 아니게 되고 batch내의 모든 데이터가 한 데 모이게 됩니다.

5. Babysitting the Learning Process

Step 1 : Preparing the data

Step 2 : choose the architecture

  • regularization을 하지 않은 채로 작은 데이터에 대해 학습을 시켜봤습니다. overfit이 되고, Loss가 매우 줄어듭니다.

  • 이번에는 전체 데이터를 사용해서 regularization을 사용하면서 다양한 learning rate로 실험을 해봤습니다.만약 learning rate가 너무 작다면, gradient 업데이트가 충분히 일어나지 않게 되고 cost가 잘 안변합니다.

  • 이때 주의깊게 볼 점은 loss는 그대로인데 accuracy가 20%나 올라간다는 점입니다.

    이는 확률 값들은 아직까지 멀리 퍼져있어서 loss는 비슷하지만, 확률 자체가 조금씩 옳은 방향으로 학습을 하기 때문입니다. Accuracy는 보통 가장 큰 값만을 취하기 때문에 accuracy가 크게 뛸 수 있습니다.

learning rate를 1e6으로 하니까 gradient가 발산합니다.

6. Hyperparameter Optimization

1) Cross-validation strategy

Cross-validation 는 training set으로 학습시키고 validation set으로 평가하는 방식입니다.

  1. coarse stage : 먼저 처음에는 epoch를 몇번 돌려서 넓은 범위에서 값을 골라냅니다. NaN이 안뜨면서 Loss가 계속 줄어들도록 parameter를 조정합니다.

  2. fine stage : 더 좁은 범위에서 cost의 변화를 확인합니다.

다음의 예제에서는 10e-4부근에서 계속해서 좋은 learning rate들이 나오고 있습니다. 이는 lr가 잘 학습되지 않고 있다고도 볼 수 있습니다. (경계에 걸려 있음)

즉, 최적의 값이 내가 설정한 범위의 중앙쯤에 위치하도록 분포를 설정해주는 것도 중요합니다.

보통은 grid search보다 random search를 통해 하이퍼 파라미터를 찾는 것이 더 성능이 좋습니다.

⭐ Summary

  • Activation Functions (use ReLU)
  • Data Preprocessing (images: subtract mean)
  • Weight Initialization (use Xavier init)
  • Batch Normalization (use)
  • Babysitting the Learning process
  • Hyperparameter Optimization (random sample hyperparams, in log space when appropriate)

오늘은 활성 함수를 비롯하여 Neural Network의 여러 기법들을 배웠습니다. 이 내용들은 딥러닝에 있어 자주 등장하는 개념들이니 꼭 집고 넘어가시길 바랍니다 :)

그럼 저희는 7강에서 뵙겠습니다. 궁금한 점이 있으시다면 댓글 남겨주세요 😊

댓글남기기