-
[모두를 위한 딥러닝 시즌2][Lab 10] Relu, Weight Initialization, Dropout, Batch Normalization모두를 위한 딥러닝 시즌2 2021. 11. 10. 00:19
Problem of Sigmoid
Network에 데이터를 입력해서 나온 output과 ground-truth 값의 차(loss)를 구해서 그 loss 값의 미분 값을 Backpropagation 해서 Network를 학습시킨다. 이때 Backpropagation으로 전달되는 loss를 미분한 것을 gradient라고 한다. 이 gradient 값은 그래프의 기울기 값이라고 할 수 있는데, sigmoid 함수 그래프의 가운데 부분은 0보다 매우 크다. 반면에 극단 좌표의 gradient값은 0에 가깝다(매우 작다).
Vanishing Gradient
만약 Neural Network가 딥해서 이런 sigmoid 함수가 많다면 매우 작은 gradient 값들이 많이 곱해져서 결국 gradinet 값이 너무 작아져 결국 Network가 전달받을 gradient 값이 소실되는 상황이 발생한다.
Relu
x값이 0이하라면 gradient 값이 0인 단점이 있지만
굉장히 간단하면서도 좋은 성능 향상을 일으키기 때문에 사람들이 많이 사용한다.
이제 각각을 code로 구현해 나가보자.
먼저 data set을 load 하자.
eager 모드로 tensorflow를 실행시킨다.
mnist를 load 한 뒤, expand_dims으로 채널을 하나 더 만들어 준다.
이미지들의 값을 255로 나눠서 0 ~ 1 값으로 만들어 주는 normalize를 진행한다.
label들의 개수를 고려하여 One hot incoding을 한다.
이렇게 하면 데이터와 label을 전처리해주는 과정이 끝이 난다.
그다음엔 network를 짜야한다.
network를 짤 때 어떤 함수들을 사용할 것인지 생각해보아야 한다.
앞에 세 가지 함수들을 사용해서 model을 짠다.
model을 생성할 때 keras model을 상속받아와야 한다.
그리고 random 한 weight 값을 설정해준다.
dense와 relu 함수를 이용하기 위해서 이미지를 flatten()을 사용해서 바꿔준다.
마지막으로 10개의 output으로 내놓는다.
이 함수를 호출했을 때를 위해 call함수를 짜준다.
이제 loss함수들을 정의하자.
- loss를 구하는 함수
- 정확도를 구하는 함수
- gradient를 구하는 함수
그다음엔 하이퍼파라미터들을 설정하는 것이 필요하다.
아까 load 한 mnist에서 각 data 값들을 가져온다.
그리고 각각 파라미터들의 값들을 설정한다.
한 번에 많은 양의 이미지들을 network에 넣는 것이 아니라 data set을 잘 섞어서 batch size만큼 이미지를 준다.
학습하고 있을 때 미리 메모리에 batch size만큼 올려놔서 더 빠르게 진행하도록 해준다.
이 과정을 반복한다.
하이퍼파라미터들을 다 설정했다면 model을 진행한다.
최종적으로 Eager mode로 전체 학습을 진행한다.
Xavier Initialization
loss 그래프에서 loss가 최저인 지점을 찾는 것이 network의 목표다.
그런데 실제 loss 그래프는 굉장히 복잡하다.
그래서 local minimum에 빠지거나 saddle point에 도달하게 되는 위험이 있다.
이때 출발점을 잘 잡는다면 그런 위험 없이 global minimum에 잘 도착할 것이다.
이전까지 평균은 0, 분산은 1인 weight initialization을 사용했었다.
반면 Xavier Initialization은 평균은 0이고 분산은 2/Channel_in + Channel_out이다.
Relu 함수에 특화된 초기화 방법인 He initialization은 평균은 0, 분산은 4/Channel_in + Channel_out이다.
Code 상에서 Xavier Initialization을 사용하고 싶다면 다른 건 다 동일하게 하되,
weight_int 부분만 RandomNormal()이 아닌 glorot_uniform()을 사용하면 된다.
아니면 he_uniform()을 사용해서 He initialization 방법을 사용할 수 있다.
weight 초기화 방법을 바꾼 것만으로도 약 10%의 성능 향상을 볼 수 있다.
Dropout
Under-fitting되거나 Over-fitting이 되지 않도록 하는 regularization
학습할 땐 일부의 node만을 사용하고 test 때는 node를 모두 사용하는 방식으로 regularization 할 수 있다.
network를 짤 때 필요한 함수들에 dropout 함수도 추가한다.
rate는 몇 % 의 node를 끌 것인지 나타낸다.
rate=0.5이므로 node의 50%를 사용하지 않는다. loss 함수들을 정의할 때 training 옵션 값이 True라면 Dropout을 사용한다는 것이고
training 옵션 값이 False라면 Dropout을 사용하지 않겠다는 뜻이다.
test를 진행할 때는 training=False로 지정해준다.
Betch Normalization
데이터의 distribution이 처음엔 잘 분포되어 있었는데 여러 layer들을 거치면서 점점 변형이 된다.
이 Internal Covariate Shift를 막기 위해서 Betch Normalization이 필요하다.
Code 상에서는 dropout() 대신 BetchNormalization()을 써주면 된다.
'모두를 위한 딥러닝 시즌2' 카테고리의 다른 글
[모두를 위한 딥러닝 시즌2][Lab 11](2) mnist cnn keras sequential/functional/subclassing/ensemble/keras eager (0) 2021.11.16 [모두를 위한 딥러닝 시즌2][Lab 11] Convolution Neural Networks (0) 2021.11.15 [모두를 위한 딥러닝 시즌2][Lab 9] Neural Nets for XOR (0) 2021.11.09 [모두를 위한 딥러닝 시즌2][Lab 8] 딥러닝의 기본 개념: 시작과 XOR 문제 (0) 2021.11.02 [모두를 위한 딥러닝 시즌2][Lab 7] application and tips (0) 2021.11.02