JLOG

[Cs231n 정리] Lecture 6 : Training Neural Networks, Part1 / CS231n 6강 정리 본문

Study/cs231n

[Cs231n 정리] Lecture 6 : Training Neural Networks, Part1 / CS231n 6강 정리

정정선선 2021. 3. 3. 23:52

아래 블로그의 정리글을 참고해 작성되었습니다.

꿈 많은 사람의 이야기


 

cs231n 강의를 들으면서 공부 기록용으로 작성된 글입니다.


Neural Networks를 학습시키는 것에 대해 Part1(6강), Part2(7강)로 나누어서 수업을 진행할 것이다.

 

 

 

 

Activation Functions

 

 

Activation Function은 Wx에 대해서 input이 들어오면, 다음 노드로 보낼 때 어떻게 보낼지를 결정해주는 역할을 한다.

 

여기서 중요한 점은 Activation function은 필수적이 요소이고, 비선형 형태여야지 Network를 깊게 쌓을 수 있다는 것이다.

-Activation이 없는 경우

 

-Activation이 선형인 경우

위와 같이 똑같은 형태로 WX+B인 형태가 나옴으로 선형인 경우 Network를 깊게 쌓을 수 없다.

 

 

Activation function의 종류이다

 

 

Sigmoid

Sigmoid 함수는 3가지 문제가 존재해서 Activation function으로 사용되지 않는다.

 

Problem #1 : graident vanishing(기울기 소실)

sigmoid의 함수 그래프 모양을 보면 x=10인 부분에서 기울기가 0에 가까운 것을 알 수 있다. 또한 기울기의 최대값이 0.5로서 backpropagation을 하게 되면 모두 최대값이라도 0.5*0.5 = 0.25로 계속 gradient가 작아지게 되며 layer을 많이 쌓은 경우 기울기가 소실되게 된다.

 

Problem #2 : not zero centered

시그모이드 그래프를 보면 0을 중심으로 되어 있지 않다는 것을 확인할 수 있다. 즉, 모든 input에 대해 양수 값으로 output이 나오게 된다.

 

Sigmoid로만 쌓은 레이어를 확인해보면, 시그모이드의 기울기, output 값 모두 양수이기 때문에 dL/da에 의해 부호가 결정되고, 모두 양수거나 음수인 상태이기 때문에 대각선으로 가지 못하고 지그재그를 그리면서 가게 된다. 매우 비효율적인 모습인 것을 확인할 수 있다.

 

 

Problem #3 : compute expensive of exp()

exp의 연산의 값이 어렵고 비싸기 때문에 좋지 않다.

 

이런 3가지 이유 때문에 sigmoid는 잘 사용하지 않는다.

 

 

Tanh

sigmoid의 단점을 개선하기 위해 zero centered된 tanh를 사용했지만, gradient vanishing과 exp 연산의 문제가 있어 잘 사용하지 않는다.

 

 

Relu

가장 대중적으로 사용하는 activation function인 Relu이다. 0이하의 값을 가진 input은 0으로 내보내 주고, 그 이외의 것들은 그대로 내보내준다.

 

 

하지만, Relu에도 2가지 문제가 있다.

non zero-centered와 0 이하의 값들은 모두 버려지게 된다는 것이다.

 

즉 입력의 값이 -10, 0 이렇게 두 개가 들어온다면 gradient가 output과 gradient가 모두 0인 상태에 빠지게 된다(Dead ReLU).

 

 

dead Relu 상태를 해결하기 위해서, 0.01의 bias 값을 주는 방법을 생각해냈는데 효능은 반반이라고 한다.

 

 

Leaky ReLU

ReLU에 대한 보완으로 Leaky ReLU가 나오게 되는데 0이하의 값에 대해 작은 양수의 값을 주는 것이다. 그리고 이 것을 조금 변형한게 PReLU인데, 일종의 알파 값을 주고 학습을 통해 찾아가는 방법이다.

 

 

ELU

또한 ReLU의 변형으로 나온 ELU도 있다. ReLU의 모든 장점을 가지고 있고, zero mean과 가까운 결과가 나오지만, exp() 연산이 있다는 단점이 있다.

 

 

Maxout "Neuron"

maxout은 2개의 파라미터를 넘겨주고 max()를 이용해 더 좋은 것을 선택하는 것이지만, 연산량이 2배가 되어 잘 사용하지 않는다고 한다.

 

 

일반적으로 Relu와 Leaky Relu를 많이 사용하고, 필요에 따라 ELU, Maxout의 방법을 고려해보는 것이 좋다. 그리고 Tanh는 RNN, LSTM에서 자주 사용하지만 CNN에서는 사용하지 않는다고 한다.

그리고 sigmoid는 절대 사용하지 않는다.

 

 

Data Preprocessing

데이터 전처리는 zero-centered, normalized를 많이 사용한다.

zero centered는 앞서 본 것처럼 양수, 음수를 모두 가지는 행렬을 가질 수 있게 해서, 효율적으로 이동할 수 있다는 장점이 있고,

normalized는 표준편차로 나눠주어 데이터의 범위를 줄여 학습을 더 빨리 할 수 있고, local optimum에 빠지는 가능성을 줄여준다고 한다.

 

이미지에서는 이미 [0, 255]의 범위를 가지고 있어 normalized를 잘 사용하지 않고, zero-centered를 많이 사용한다고 한다.

 

 

그 외에도 분산에 따라 차원을 감소시켜주는 PCA, whitened data 등이 존재하는데 이미지에서 잘 사용 되지 않는다고 한다.

 

 

앞서 말했듯이 이미지의 경우는 center만 사용하는데, 이미지 픽셀 평균을 빼주거나 채널의 평균을 빼주는 방법이 있다.

 

 

Weight Initialization

weight이 어떻게 초기화 되었는지에 따라, 학습의 결과에 영향을 줌으로 중요한 영역이라고 할 수 있다.

 

만약 W=0인 경우 output layer가 모두 0이 나오게 되고 gradient도 0이 나와 정상적으로 학습이 가능하지 않다.

 

 

 

그래서 작은 random 값을 weight에 설정해주어 사용했고, 작은 네트워크에서는 잘 동작하지만 깊은 네트워크에서는 잘 동작하지 않았다.

 

 

만약 10개의 레이어에 각 500개의 뉴런, tanh를 사용한 경우

 

 

모든 가운데 값을 제외한 activation이 0이 된 것을 확인할 수 있다. tanh는 0에 가까운 부분만 기울기 값이 존재하고, 0에서 멀어질 수록 기울기가 0에 가깝게 되어 날라가게 된다.

 

 

그럼 W 값을 크도록 초기화 한 경우, tanh가 1, -1에 포화 되어 오버슈팅이 일어나게 된다.

 

 

 

적절한 weight 초기 값을 주기 위해 Xavier init을 사용하게 된다.

노드의 개수를 normalization하는 방법으로서 input의 개수가 많아지면 크게 나눠주기 때문에 값이 작아지고, input의 개수가 적으면 weight 값이 커지는 방식으로 weight를 초기화하게 된다.

즉, 입력의 분산과 출력의 분산을 동일하게 만드는 초기화 기술이다.

 

 

Gradient Vanishing 현상을 완화하기 위해 가중치를 초기화 할 때, 출력 값들이 정규 분포 형태를 갖게 하는 것이 중요하다. 정규 분포 형태를 가져야 안정적인 학습이 가능하기 때문이다.

 

 

tanh와 Xavier는 같이 사용하기에 좋지만, ReLU의 경우 출력 값이 0으로 수렴하고 평균, 표준 편차도 0으로 수렴해 Xavier를 사용하지 않는 것이 좋다.(https://gomguard.tistory.com/184)

 

그래서 fan_in size를 2로 나눠 사용했더니 성능이 더 잘나오는 것을 알 수 있었다.

 

궁금증? 왜 평균 분포를 갖게 하면 init이 잘 되는가? 그리고 relu의 경우 왜 2를 나눠주면 잘되는가? 궁금허네~~~

 

weight init 부분은 아직 활발하게 연구가 진행 되고 있는 부분이다.

 

 

Batch Normalization

batch norm을 사용하면 굳이 weight init을 안해도 된다고 한다.

Batch Norm는 기본적으로 training 과정에서 Gradient vanishing의 문제를 일어나지 않도록 한다.

 

 

Batch Normalization은 각 층의 input distribution을 평균 0, 표준편차 1로 만드는 것이다.

network 각 층의 activation 마다 input distribution이 달라지는 internal covariance shift이 달라지는 문제를 해결하기 위해 사용 된다.

 

 

보통 batch 별로 데이터를 train 시키는데, 이때 N*D의 batch input이 들어오면 이 것을 normalize한다. (평균값을 빼줘 평균을 0으로 만들고, 분산을 나누어 분산 값을 1로 만듬)

 

 

BN는 일반적으로 activation layer 전에 사용되어 잘 분포되도록 한 후, activation을 진행할 수 있도록 한다. BN의 목적이 네트워크 연산 결과가 원하는 방향의 분포대로 나오는 것이기 때문에 activation function이 적용되 분포가 달라지기 전에 적용하는 것이다.

근데, BN을 사용할 때 과연 unit gaussian이 적합한지에 대해서 판단하여야 한다.

 

 

하지만 BN이 적절한지에 대한 판단을 학습에 의하여 조절할 수 있다고 한다. 처음 normalize를 진행하고, 이 후 감마 값과 같은 하이퍼 파라미터 값들을 조정하여 batch norm을 할지 안할지 선택하는 것이다.

감마 값은 normalizing scale를 조절해주고, 베타 값은 shift를 조절해주는 파라미터 값이다.

이 값들을 학습을 통해 조절함으로서 normalize 정도를 조절할 수 있다.

 

 

먼저 mean과 variance를 구하고 normalize를 한다.

그리고 scale, shift를 얼마나 할지 학습을 통해 값을 정하게 된다.

 

그리고 BN를 하게 되면 Dropout를 사용하지 않아도 된다고 한다. 이 부분이 궁금해서 더 찾아봤는데, Batch Norm의 논문 저자는 dropout을 대체할 수 있다고 하였으나, 실제적으로 둘 다 모두 사용했을 때 성능이 좋은 경우도 있고 의견이 다양하게 존재하는 것 같다.

왜 BN를 사용했을 때 overfitting이 완화되는지에 대해서는 더 조사가 필요할 것 같다.

 

 

 

Babysitting the Learning Process

먼저 전처리 과정을 진행해준다. 이미지의 경우 zero-centered를 사용한다.

 

사용할 neural architecture를 정해준다.

 

sanity check를 통해 loss가 적절하게 나오는지 확인한다.

 

규제 값을 올렸을 때 loss가 증가하였고, network가 잘 동작하는지 확인할 수 있다.

 

 

그리고 먼저 작은 데이터 셋을 이용해서 훈련을 시켜본다.

 

 

Data 수가 작기 때문에 overfitting이 발생하고, train acc가 100%가 나오는 것을 확인할 수 있다.

overfitting이 나온다는 것은 모델이 제대로 동작하고 있다는 의미로 받아드려도 된다.

 

 

 

이제 적절한 hyper parameter 값들(regularization, learning rate)을 설정해 줄 것이다. 현재 lr = 1e-6일 때 loss가 매우 조금씩 바뀌는 것을 확인할 수 있었다. 하지만 train acc가 조금씩 높아지는 것을 보면 느리지만 train이 되는 것을 확인할 수 있다.

 

 

이번에 lr = 1e6로 설정하니 cost 값이 Nan이 되는 것을 확인할 수 있다. 이것은 값이 너무 커서 튕겨져 나간거라고 생각할 수 있다.

 

 

lr = 3e-3로 수정해도 inf로 튕겨져 나가는 것을 확인할 수 있고, 몇 번의 실험을 통해 1e-3~1e-5 값이 적절한 값이라는 것을 추측할 수 있다.

 

 

Hyperparameter Optimization

처음에는 범위를 크게 잡아 좁은 범위로 줄여나가는 방법을 사용한다.

 

 

예시를 보면 10**uniform(,)의 형태로 값을 취해주는 것을 볼 수 있다. 로그 값을 취해주면 더 안정적이기 때문이다.

(의미를 잘 모르겠는데?)

 

 

이렇게 주어진 범위에서 train을 시켜 val_acc가 낮은 learning rate를 확인한다.

자료에 의하면 val_acc = 48.2%, lr=4.296e-04, reg=6.64e-01의 값이라고 한다.

 

 

위에서 찾은 nice case와 비슷하게 영역을 설정해 다시 확인해본다.

53% 정도로 좋은 값이 나왔지만, 더 정확하게 best case를 찾기 위해 더 좁은 범위에서 실험해보는 것이 좋다고 한다.

 

 

이렇게 hyperparameter를 찾기 위한 방법으로 Grid Search와 Random Search가 있는데, Grid Search는 일정한 간격을 가지고 있어, 제일 best case를 찾지 못할 수도 있다. 그래서 Random Search 방법을 더 많이 사용한다고 한다.

 

 

이렇게 적절한 hyperparameter를 찾음으로서 좋은 train이 이루어지는 환경을 설정할 수 있따.

hyperparamter에는 network architecture, lr, decay, regularization 등이 있다고 한다

 

 

Comments