-
Batch Normalization은 왜 사용하는 것일까?머신러닝 및 딥러닝 2021. 1. 17. 16:03
1. training을 빠르게 해준다.
처음 그대로 입력을 넣으면 height의 경우는 분포의 범위가 상당히 조그마하기 때문에 age에 비해 상당히 가파른 것을 알 수 있다. 이 경우 가장 optimal한 point로 가기위해서는 상당히 미세하게 조정해야 하는 것을 알 수 있다. 하지만 height와 age의 평균이 0 이고 분산이 1인 분포로 만들게 되면 age와 hegiht의 분포가 비슷해지기 때문에 더 큰 lr을 가지고도 학습을 진행해도 optimal값에 들어가는데 지장이 없어서 이 경우 더 빠르게 수렴한 다라는것을 직관적으로 알 수 있다.
2. 초기 가중치의 중요도를 낮춘다.
앞서 설명했던 예시 처럼 데이터의 분포가 비슷하니 optimal 한 값에 더욱 잘 찾아가고 이 말은 학습이 더 원활하게 되기 때문에 초기 가중치가 어떻게 정의되었든 학습이 Batch Normalizaion으로 잘 되기 때문에 초기 가중치의 중요도를 낮출 수 있다.
3. 모델을 정규화 해준다.(조금)
더 강력한 정규화, 일반화를 원한다면 Dropout과 같이 사용하면 된다. Dropout은 어떤 노드는 즉, 어떤 히든 유닛은 0으로 만들기 때문에 즉, 노이즈를 사용하기 때문에 일반화, 정규화의 효과가 있다. 이와 비슷하게 Batch Normalization도 히든 유닛 Z를 Z_tilda로. 만드는 과정에서 약간의 노이즈가 생긴다고 말할 수 있을 것이다. 하지만 단독 큰 미니배치를 사용한다면 잡음이 줄어든다. 왜냐하면 더 많은 샘플들을 보아서 평균과 분산을 구하기 때문에 노이즈이 줄어 들어 일반화 효과가 줄어든다. 따라서 배치 정규화를 일반화를 위해서 사용한다는것은 조금 비약이다. 배치 정규화는 그것을 목적으로 만들어 지는 것이 아니기 때문이다.
이것의 메인 용도는 은닉층의 활성함수를 정규화 해서 학습의 속도를 올리는 용도이다.
배치정규화는 활성화 함수를 쓰고 난 다음에 사용되는 편이 더 많다.
위의 설명이 알아보기 복잡할 거 같아서 설명을 쓰자면 어떤 Neural Network에 한층(l)이 z1부터 zn까지로 이루어져있다고 했을 때 이 은닉 유닛의 평균은 모든 은닉유닛을 더한 값을 은닉유닛갯수로 나눈 값이다. 해당 은닉유닛의 분산은 각 은닉유닛을 평균으로 뺀값을 제곱하여 다 더한다음 은닉유닛의 갯수로 나눠준게 분산이 된다.
여기서 normalize 된 은닉유닛의 값은 은닉유닛에서 평균을 빼준다음 표준편차로 나눠준값에 해당하는데 표준편차가 0이 될 수도 있으니까 이를 방지하게위해 아주작은값 입실론을 넣어준다. 그렇게 되면 평균은 0 이고 분산은 1인 분포를 가진 z_norm 이 완성되는데 여기서 평균이 0이고 분산이 1인 분포를 가진 z_norm은 그렇게 좋지 않은 선택일 수도 있다. 직관적으로 얘기하자면 은닉층은 고른 분포를 가지는 것이 좋기 때문이다.
그래서 학습을 통하여 얻을 수 있는 감마를 z_norm에 곱해주고 B를 더해주어 z_tilda를 만든다. 만약 감마가 분산에 입실론을 더한 값의 루트를 씌워준 값이고 B가 평균이라면 z_tilda는 정규화 하지않은 그냥 은닉값 z 와 같은 결과가 된다.
여기서 배치 정규화는 입력층에만 정규화를 하는것이 아니라 신경망 안 깊이 있는 은닉층의 값들까지도 정규화 해줄수 있다는 점이다.
정리하자면 입력이 표준화된 평균과 분산을 갖되, 평균과 분산은 학습 알고리즘에서 설정할 수 있는 두변수 감마와 베타에 조절된다는 것이다.
그렇다면 심층 신경망에서는 어떻게 계산될 수 있을까?
물론 실제로 batch_norm을 scratch 부터 구현할 필요는 당연히 없다. 텐서플로우나 파이토치에는 이미 이것이 다 구현되어있어서 한줄로 쓰면된다. 여기서 예시로 든 케이스로 보면 batch_normaliztion을 weight와 bias를 해준 z와 z를 activation function 값에 넣어준 a의 사이에 실행하도록 구현해놓았다. 따라서 연산순서를 보면 입력 x가 들어왔을때 W[1], b[1]을 x에 연산해주고 그 결과값 z[1] 에 ㄷ하여 batch normalization 해주는 것을 볼 수 있다. 여기서도 파라미터 베타와 감마가 쓰인다. 여기서 베타는 Adam 이나 RMSprop에서 사용되는 베타의 값과 전혀 관련이 없다. 그냥 batch normalization에서 학습되어지는 파라미터 중 하나이다.
실제로는 batch normalization 은 훈련 집합의 mini-batch에 적용이 된다. 따라서 미니배치 안에서 z1의 평균과 분산을 계산한 뒤에 평균을 빼고 표준편차로 나눠 배치 정규화를 진행한다. 물론 정규화된 값은 베타와 감마값을 통하여 조정된다. 이 과정을 통해 첫번째 미니 배치에서 z_tilda 1을 얻게 된다.그리고 여기에 활성화 함수를 적용하여 a[1]을 얻게 되는 것이다. 그리고 이 a[1]을 입력으로 다시 z[2]가 구해지는 형식이다. 그리고 이 값이 최종적으로 다 구해지면 경사하강법등을 통해서 loss값을 계산하고 다음에 다시 새로운 batch 가 들어온다. 그리고 두번째 미니배치 단계에서 부터는 당연히 두번쨰 미니배치에 있는 데이터만을 이용하여 진행한다. 즉, 두번쨰 미니배치만 이용해서 평균과 분산을 계산하는 것이다. 그렇게 계속 진행한다.
또한 파라미터를 보면 총 4가지를 썼는데 여기서 bias는 batch_normalization을 해주게 되면 사실상 0 이 된다. 왜냐하면 batch normalization 에서 평균을 빼주고 때문이다. 즉, 배치정규화가 어떤층의 은닉유닛의 값들인 z 의 평균을 0으로 만들기 때문에 b의 변수가 필요 없게 된다. 대신 배치정규화 베타가 그 역할을 대신차지 하게 된다. 미니배치에서는 평균을 뺴주면서 사라지기 때문에 bias 값은 아무런 영향을 끼치지 않는 값이 된다. 또한 z^[l]의 모양이 (n^[l],1)라고 할 때, 베타와 감마의 모양도 (n^[l],1)이 된다. 왜냐하면 베타와 감마의 값은 각 원소에 연산해주는 값이기 떄문이다 .
최종적으로 경사하강되는 것을 살펴보면
t는 1부터 마지막 미니배치 까지를 나타낸다. 그래서 X^{t}를 순전파 하고 여기서 각 은닉층을 배치정규화를 통해 z를 z_tilda로 바꿔준다. 그 후 역전파를 진행할때 dW, d베타, d감마 에 대해서 업데이트를 시켜주면 된다. 이런 경사 하강법 말고 Adam 이나 Momentum과 같은 방법으로도 잘 작동한다.
만약 고양이 분류기를 만들기 위해. 어떤 신경망을 학습한다고 가정해보자 이때 training 할 고양이 데이터로는 위에 보이듯이 까만색 고양이만 주었다고 할 때, 오른쪽 그림과 같이 다른 색의 고양이가 들어오면 분류기는 아마 결과를 잘 내놓지 못할 것이다. 이렇게 데이터의 분포가 바뀌는 것을 "covariance shift" 공변량 변화이라고 한다. 즉 데이터의 분포가 바뀐다면 데이터를 레이블로. 대응하는 관측함수가 바뀌지 않더라도 학습 알고리즘을 다시 학습해야한다는 것이다.(여기서 관측함수는 고양이를 찾는것이라고 생각하면 되겠다.)
그렇다면 공변량 변화가 신경망에 어떻게 적용될 수 있을까?
예시 신경망에서 3번째층의 노드 즉, 히든 유닛들을 살펴보자. 이 히든 유닛들은 입력으로 첫번째층과 두번째 층에서 연산된 결과를 입력으로 받게 된다. 그렇게 된다면 첫번째의 weight 와 bias 두번째의 weight와 bias에서 영향을 받게 될 수 밖에 없다. 이것을 앞서 보았던 covariance shift 문제를 겪고 있는게 된다. 따라서 이것의 분포를 batch normalization을 해줌으로서 해당 분포의 범위를 제안하여 이 후의 학습이 원활하게 되고 각층이 원활하게 학습이 될 수 있다.
테스트
그렇다면 테스트 과정에서의 배치 정규화는 어떤 식으로 해야할까? 테스트과정은 배치로 예측을 하는게 아닌 하나의 경우에 대한 예측만 본다. 따라서 접근이 조금 다르다고 할 수 있다. 이때는 각각 독리된 평균과 분산의 추정치를 사용하면 된다.
테스트때의 batchnormalize는 위에 그림을 통해 설명하자면 X^{1}을 첫번째 미니배치 , X{i}를 i번째 미니배치라고 했을때 우리는 L층의 첫번째 미니배치 평균을 M^{1}[L]이라고 쓸 수 있다. 또한 분산도 Sigma^{1}{L} 이라고 쓸 수 있다. 이값을 지수가중평균을 사용하여 구한다. 이 값을 사용하여 테스트 때는 M과 sigma을 사용한다. 람다와 베타는 각 층의 학습된 값을 사용한다.
M과 Sigma를 구할때 마지막 training 단계에서 얻은 얻은 M과 Sigma값을 사용하여 추정하는 경우도 있지만 주로 가장 처음에 말한 지수평균방법을 사용한다.
'머신러닝 및 딥러닝' 카테고리의 다른 글
서브워드 토크나이저 (0) 2021.01.23 Pytorch에서는 왜 항상 optimizer.zero_grad()를 해줄까? (0) 2021.01.17 Hyperparameter 튜닝은 어떻게 하는걸까? (0) 2021.01.17 Dropout 이란 무엇인가 (2) 2021.01.16 CycleGAN 이란? (0) 2021.01.16