배치 정규화: 딥러닝 기초 시리즈 7

배치 정규화(Batch Normalization)는 딥 러닝에서 널리 사용되는 기술 중 하나입니다.

이 기술은 2015년 Sergey Ioffe와 Christian Szegedy에 의해 처음 소개되었으며, 딥 러닝 모델의 훈련을 더 빠르고 안정적으로 만들기 위한 목적으로 개발되었습니다.

이 문서에서는 배치 정규화의 이론적 배경과 원리에 대해 깊이 이해하고, 파이썬 코드로 구현해 보겠습니다.


목차

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."

참고 문헌 및 참고자료: 밑바닥부터 시작하는 딥러닝


배치 정규화의 기본 아이디어

배치 정규화의 기본 아이디어

딥 러닝 모델을 훈련할 때, 각 층의 입력 분포가 변화하는 현상을 “내부 공변량 변화(Internal Covariate Shift)”라고 합니다. 이 현상은 모델을 훈련하기 어렵게 만들며, 특히 깊은 모델에서는 이 문제가 더욱 심각할 수 있습니다.

배치 정규화는 이 문제를 해결하기 위해 각 층의 활성화 출력값을 정규화하는 과정을 포함합니다. 즉, 출력값의 평균을 0으로, 표준편차를 1로 만듭니다. 이 과정은 미니배치 단위로 수행되며, 이러한 정규화를 통해 각 층의 입력 분포가 안정화되어 훈련이 더 빠르고 안정적으로 이루어집니다.

배치 정규화 공식

1. 평균 계산하기

\mu = \frac{1}{m} \sum_{i=1}^{m} x_i

2. 분산 계산하기

\sigma^2 = \frac{1}{m} \sum_{i=1}^{m} (x_i-\mu)^2

3. 정규화

\hat{x_i} = \frac{x_i - \mu}{\sqrt{\sigma^2+\epsilon}}

4. 스케일 및 쉬프트

y_i = \gamma \hat{x_i}+\beta
스케일 (\gamma): 정규화된 데이터의 분포를 조절하는 데 사용됩니다. 즉, 분포의 표준편차를 조절하게 됩니다.

시프트 (\beta): 정규화된 데이터에 일정한 값을 더해주어 평행 이동을 수행합니다. 이를 통해 분포의 중심(평균)을 조절하게 됩니다.

이 두 파라미터는 각 층에서의 활성화 출력이 너무 크게 변화하지 않도록 도와주어, 딥 러닝 모델의 훈련을 더욱 안정화시킵니다.

배치 정규화 – 스케일 \gamma 과 시프트 \beta 학습 과정

1. 순전파: 신경망의 각 레이어에서 순전파를 수행하면서 배치 정규화를 적용합니다.

평균 \mu , 분산 \sigma^2, 정규화된 출력 \hat{x_i} 등이 계산됩니다.

2. 손실 함수 계산: 출력과 실제 레이블(원 핫 인코딩)로 손실함수 계산합니다.

3. 역전파: 손실 함수에 대한 그레디언트를 계산합니다. 신경망의 가중치와 편향과 함께, 스케일과 시프트의 손실 함수에대한 미분을 구합니다.

\frac{\partial L}{\partial \gamma} = \sum \text{dout} (\frac{x - \mu}{\sqrt{\text{var} + \epsilon}}), \ \frac{\partial L}{\partial \beta} = \sum \text{dout}

여기서 \text{var}=\sigma^2  입니다.

4. 파라미터 업데이트 하기 (*미니 배치 경사 하강법이나, *확률적 경사 하강법을 이용합니다.) \gamma = \gamma - \eta \frac{\partial L}{\partial \gamma}   \beta = \beta - \eta \frac{\partial L}{\partial \beta }

*경사 하강법 (Gradient Descent, GD)
데이터 사용: 전체 데이터 세트를 사용하여 그래디언트를 계산합니다.
계산 비용: 그래디언트를 계산할 때 모든 데이터 포인트를 사용하기 때문에 계산 비용이 높을 수 있습니다.
정확성: 전체 데이터를 기반으로 그래디언트를 계산하므로, 그래디언트의 방향이 최적화 문제의 실제 경사를 정확하게 반영합니다.
수렴 속도: 계산 비용이 높지만, 안정적으로 수렴합니다.
적용 분야: 작은 데이터셋에 적합합니다.

*확률적 경사 하강법 (Stochastic Gradient Descent, SGD)
데이터 사용: 무작위로 선택한 하나의 데이터 포인트를 사용하여 그래디언트를 계산합니다.
계산 비용: 한 번의 그래디언트 계산 비용이 매우 낮습니다.
정확성: 그래디언트는 노이즈가 있을 수 있고, 실제 경사를 정확하게 반영하지 못할 수 있습니다.
수렴 속도: 계산 비용은 낮지만, 노이즈 때문에 수렴이 불안정할 수 있습니다.
적용 분야: 큰 데이터셋에 적합합니다.

*미니배치 경사 하강법 (Mini-batch Gradient Descent)
미니배치 경사 하강법은 GD와 SGD의 중간 형태입니다.
미니배치라고 불리는 작은 데이터 서브셋을 사용하여 그래디언트를 계산합니다.
이 방법은 대규모 데이터셋에 대한 GD의 정확성과 SGD의 계산 효율성을 어느 정도 조화롭게 가져갑니다.

배치 정규화 전체과정 예시

간단하게 기본적인 경사하강법을 사용하였습니다.

우선 클래스를 생성하고, 초기 값들을 지정해 줍니다. 필요한 변수값은

\text{평균: } \mu \text{분산: } \sigma^2

 \text{정규화: } \hat{x_i}  \text{스케일: } \gamma  \text{쉬프트: } \beta  \text{손실값에 대한 스케일 미분: } \frac{\partial L}{\partial \gamma}  \text{손실값에 대한 쉬프트 미분: } \frac{\partial L}{\partial \beta}

이제 순전파에 대한 메서드를 만들어 주겠습니다

Python
import numpy as np

class BatchNorm:
    def __init__(self, n_features, learning_rate=0.01, epsilon=1e-5):
        self.epsilon = epsilon              # 안정화를 위한 작은 값
        self.learning_rate = learning_rate  # 학습률
        self.gamma = np.ones(n_features)    # 스케일 파라미터 gamma 초기화 (초기값: 1)
        self.beta = np.zeros(n_features)    # 쉬프트 파라미터 beta 초기화 (초기값: 0)
    
    def forward(self, X):  # 배치 정규화의 순전파
        self.X = X
        self.mean = np.mean(X, axis=0)      # 배치 정규화를 위한 평균 계산
        self.var = np.var(X, axis=0)        # 배치 정규화를 위한 분산 계산 (=sigma^2)
        self.norm = (X - self.mean) / np.sqrt(self.var + self.epsilon) # 정규화 수행
        self.out = self.gamma * self.norm + self.beta # 스케일과 쉬프트를 적용한 출력 계산
        return self.out
        
    # 역전파로, 최종적으로 필요한 gamma와 beta 값을 구합니다.
    def backward(self, d_out): 
        N, D = self.X.shape
        # 출력에 대한 그레디언트 계산
        self.d_norm = d_out * self.gamma  
        # 분산에 대한 그레디언트 계산
        d_var = np.sum(self.d_norm * (self.X - self.mean) * -0.5 * np.power(self.var + self.epsilon, -1.5), axis=0)
        # 평균에 대한 그레디언트 계산
        d_mean = np.sum(self.d_norm * -1 / np.sqrt(self.var + self.epsilon), axis=0) + d_var * np.sum(-2 * (self.X - self.mean), axis=0) / N  
        # 입력에 대한 그레디언트 계산
        d_X = self.d_norm / np.sqrt(self.var + self.epsilon) + d_var * 2 * (self.X - self.mean) / N + d_mean / N  
        # gamma에 대한 그레디언트 계산
        self.d_gamma = np.sum(d_out * self.norm, axis=0) 
        # beta에 대한 그레디언트 계산 
        self.d_beta = np.sum(d_out, axis=0)  
        
        #gamma 및 beta 업데이트
        self.gamma -= self.learning_rate * self.d_gamma
        self.beta -= self.learning_rate * self.d_beta
        
        return d_X
    
# 배치 정규화 클래스로부터 객체 생성
bn = BatchNorm(n_features=100, learning_rate=0.002)

# 더미 데이터 (x값)
x = np.random.randint(1, 256, size=(1000, 100))

# 더미 그레디언트 (역전파로 들어오는 값)
dout = np.random.normal(0, 1, (1000, 100))

import matplotlib.pyplot as plt

# 초기 그래프 확인
# 여기서는 초기 배치 정규화의 순전파 결과인 각 그래프의 최댓값으로 나누어,
# 그래프를 비교하기 편하게 하기 위해 x값의 범위를 -1부터 1까지로 스케일링합니다.

plt.figure(figsize=(15, 15))

#bn.forward(x)의 최댓값
max_bn_forward = np.max(np.abs(bn.forward(x).flatten()))

#순전파된 x값들의 히스토그램 (여기서는 초기값 gamma = 1, beta = 0 입니다.)
plt.hist(bn.forward(x).flatten()/max_bn_forward, bins=1000, label='No Lerning forward', alpha=0.5)

# 10번 학습
for i in range(6):
    norm_data = bn.forward(x)
    d_X = bn.backward(dout)
    if (i + 1) % 3 == 0:
        max_bn_forward = np.max(np.abs(bn.forward(x).flatten()))
        plt.hist(bn.forward(x).flatten()/max_bn_forward, bins=1000, label=f"Iteration {i + 1} learning", alpha=0.5)

plt.legend()
plt.ylim(0, 300)  # 그래프의 y 축 범위 설정
plt.show()
배치 정규화 학습 결과

학습전의 배치 정규화 순전파시 파란색 그래프처럼 모든 값에서 넓게 펼쳐져 있는 그래프이고, 학습하면 할수록 초록색 그래프처럼 종모양의 그래프가 됩니다.


결론

“이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.”

배치 정규화(Batch Normalization)는 딥 러닝 모델의 훈련 과정을 최적화하고 안정화시키는 데 중요한 역할을 하는 표준화 기법 중 하나로, 신경망 모델의 각 층에서 활성화 출력값을 조절하는 데 활용됩니다. 이러한 조절을 통해 다음과 같은 이점을 얻을 수 있습니다.

  1. 내부 공변량 변화(Internal Covariate Shift) 문제의 완화: 딥 러닝 네트워크에서 각 층을 통과하는 입력 분포의 변화로 인해 훈련 과정이 불안정해지는 현상을 완화합니다.
  2. 빠른 수렴과 안정성: 배치 정규화는 활성화 함수의 입력을 정규화하고, 평균을 0, 분산을 1로 조절하여 경사 하강법 최적화를 빠르고 안정적으로 만듭니다.
  3. 더 깊은 네트워크 훈련 가능: 깊은 신경망의 경우 내부 공변량 변화 문제가 더 심각하게 작용하는데, 배치 정규화를 사용하면 더 깊은 네트워크를 효과적으로 훈련시킬 수 있습니다.

다시한번 요약하자면 배치 정규화는 주요 단계로 다음과 같이 수행됩니다.

  1. 평균 및 분산 계산: 각 미니배치 내에서 입력 데이터의 평균과 분산을 계산합니다.
  2. 정규화: 입력 데이터를 평균과 분산으로 정규화합니다. 이렇게 하면 평균이 0이고 분산이 1인 분포를 얻게 됩니다.
  3. 스케일 및 쉬프트: 정규화된 데이터에 스케일 파라미터와 쉬프트 파라미터를 적용하여 최종 출력값을 계산합니다. 스케일 파라미터는 분포의 크기를 조절하고, 쉬프트 파라미터는 분포의 위치를 조절합니다.
  4. 학습: 배치 정규화의 파라미터(스케일과 쉬프트)는 역전파를 통해 학습되며, 네트워크의 다른 파라미터와 함께 최적화 과정에 참여합니다.

이러한 과정을 통해 배치 정규화는 신경망 모델의 안정성과 성능을 향상시키는 데 기여하며, 딥 러닝 모델을 효과적으로 훈련시키는 데 필수적인 기술 중 하나입니다.


함께 참고하면 좋은 글

가중치 초기화 이론: 딥러닝 기초 시리즈 6

역전파를 이용한 학습: 딥러닝 기초 시리즈 5

경사 하강법: 딥러닝 기초 시리즈 4

손실 함수: 딥러닝 기초 시리즈 3

활성화 함수: 딥러닝 기초 시리즈 2

퍼셉트론: 딥러닝 기초 시리즈 1

2 thoughts on “배치 정규화: 딥러닝 기초 시리즈 7”

Leave a Comment