A A
[DL] Batch Normalization - 배치 μ •κ·œν™”

Batch Normalization - 배치 μ •κ·œν™”

Batch Normalization (배치 μ •κ·œν™”)의 κ°œλ…μ€ 2015년에 μ œμ•ˆλœ λ°©λ²•μž…λ‹ˆλ‹€.
  • 일단, Batch Normalization(배치 μ •κ·œν™”)κ°€ μ£Όλͺ©λ°›λŠ” μ΄μœ λŠ” λ‹€μŒμ˜ μ΄μœ λ“€κ³Ό κ°™μŠ΅λ‹ˆλ‹€.
    • Training(ν•™μŠ΅)을 빨리 ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 즉, Training(ν•™μŠ΅) 속도λ₯Ό κ°œμ„ ν•˜λŠ” νš¨κ³Όκ°€ μžˆμŠ΅λ‹ˆλ‹€.
    • μ΄ˆκΉƒκ°’μ— 크게 μ˜μ‘΄ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” νŠΉμ§•μ΄ μžˆμŠ΅λ‹ˆλ‹€.
    • 그리고 Overiftting을 μ–΅μ œν•˜λŠ” νŠΉμ§•μ΄ μžˆμŠ΅λ‹ˆλ‹€. 즉, Dropoutλ“±μ˜ ν•„μš”μ„±μ΄ κ°μ†Œν•©λ‹ˆλ‹€.
  • Batch Normalization(배치 μ •κ·œν™”)의 κΈ°λ³Έ μ•„μ΄λ””μ–΄λŠ” μ•žμ—μ„œ λ§ν–ˆλ“―μ΄ 각 Layer(μΈ΅)μ—μ„œμ˜ Activation Value(ν™œμ„±ν™” κ°’)이 μ λ‹Ήνžˆ 뢄포가 λ˜λ„λ‘ μ‘°μ •ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. ν•œλ²ˆ μ˜ˆμ‹œλ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.

Batch Normalization(배치 μ •κ·œν™”)λ₯Ό μ‚¬μš©ν•œ Neural Network(신경망)의 μ˜ˆμ‹œ

  • Batch Normalization(배치 μ •κ·œν™”)λŠ” κ·Έ 이름과 같이 ν•™μŠ΅μ‹œ Mini-Batchλ₯Ό λ‹¨μœ„λ‘œ μ •κ·œν™”λ₯Ό ν•©λ‹ˆλ‹€.
λ―Έλ‹ˆ 배치(mini-batch)λŠ” 데이터셋을 μž‘μ€ 크기의 μΌλΆ€λ‘œ λ‚˜λˆ„μ–΄ λ„€νŠΈμ›Œν¬λ₯Ό ν•™μŠ΅μ‹œν‚€λŠ” λ°©λ²•μž…λ‹ˆλ‹€.
전체 데이터셋을 ν•œ λ²ˆμ— λͺ¨λ‘ μ‚¬μš©ν•˜λŠ” 것이 μ•„λ‹ˆλΌ 데이터λ₯Ό μž‘μ€ 배치둜 λ‚˜λˆ„μ–΄ 각 λ°°μΉ˜μ— λŒ€ν•΄ 순차적으둜 ν•™μŠ΅μ„ μ§„ν–‰ν•©λ‹ˆλ‹€.
  • κ΅¬μ²΄μ μœΌλ‘œλŠ” Mean(평균)이 0, Variance(λΆ„μ‚°)이 1이 λ˜λ„λ‘ μ •κ·œν™”ν•©λ‹ˆλ‹€. μˆ˜μ‹μœΌλ‘œλŠ” μ•„λž˜μ˜ 식과 κ°™μŠ΅λ‹ˆλ‹€.

    • μœ„ μˆ˜μ‹μ€ Mini-Batch B =  κ°œμ˜ μž…λ ₯ λ°μ΄ν„°μ˜ 집합에 λŒ€ν—€ 평균 μB와 λΆ„μ‚° σB​²μ„ κ΅¬ν•©λ‹ˆλ‹€.
    • 그리고 μž…λ ₯ 데이터λ₯Ό Mean(평균)이 0, Variance(λΆ„μ‚°)이 1이 되게 Normalization(μ •κ·œν™”) ν•˜κ³ , ε은 0으둜 λ‚˜λˆ„λŠ” μ‚¬νƒœλ₯Ό μ˜ˆλ°©ν•˜λŠ” 역할을 ν•©λ‹ˆλ‹€.
    • 또 Batch Normalization(배치 μ •κ·œν™”) Layer λ§ˆλ‹€ 이 μ •κ·œν™”λœ 데이터에 κ³ μœ ν•œ ν™•λŒ€ scale와 이동 shift λ³€ν™˜μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.
    • μˆ˜μ‹μœΌλ‘œλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

  • γ : ν™•λŒ€,  β : 이동을 λ‹΄λ‹Ήν•©λ‹ˆλ‹€.
  • 두 값은 μ²˜μŒμ—λŠ” γ=1, β=0 (1λ°° ν™•λŒ€, 이동 μ—†μŒ=원본 κ·ΈλŒ€λ‘œ)μ—μ„œ μ‹œμž‘ν•΄μ„œ ν•™μŠ΅ν•˜λ©° μ ν•©ν•œ κ°’μœΌλ‘œ μ‘°μ •ν•΄κ°‘λ‹ˆλ‹€.
  • 이것이 Batch Normalization(배치 μ •κ·œν™”)의 μ•Œκ³ λ¦¬μ¦˜μž…λ‹ˆλ‹€. μ„€λͺ…ν•œ λ‚΄μš©μ„ μ•„λž˜μ˜ κ·Έλž˜ν”„λ‘œ λ‚˜νƒ€λ‚Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

Batch Normalization(배치 μ •κ·œν™”)의 계산 κ·Έλž˜ν”„


Batch Normalization (배치 μ •κ·œν™”)의 효과

ν•œλ²ˆ Batch Normalization(배치 μ •κ·œν™”) 계측을 μ‚¬μš©ν•œ μ‹€ν—˜μ„ ν•œλ²ˆ Mnist Dataset을 μ‚¬μš©ν•˜μ—¬ Batch Normalization Layerλ₯Ό μ‚¬μš©ν• λ•Œ, μ‚¬μš©ν•˜μ§€ μ•Šμ„λ•Œμ˜ ν•™μŠ΅ 진도가 μ–΄λ–»κ²Œ λ‹¬λΌμ§€λŠ”μ§€λ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.
# coding: utf-8
import sys
import os
import numpy as np
import matplotlib.pyplot as plt
sys.path.append(os.pardir)  # λΆ€λͺ¨ λ””λ ‰ν„°λ¦¬μ˜ νŒŒμΌμ„ κ°€μ Έμ˜¬ 수 μžˆλ„λ‘ μ„€μ •
from dataset.mnist import load_mnist  # MNIST 데이터셋을 λΆˆλŸ¬μ˜€λŠ” ν•¨μˆ˜
from common.multi_layer_net_extend import MultiLayerNetExtend  # λ‹€μΈ΅ 신경망 λͺ¨λΈ 클래슀
from common.optimizer import SGD, Adam  # μ΅œμ ν™” μ•Œκ³ λ¦¬μ¦˜ 클래슀

(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)

# ν•™μŠ΅ 데이터λ₯Ό μ€„μž„
x_train = x_train[:1000]
t_train = t_train[:1000]

max_epochs = 20
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.01

# κ°€μ€‘μΉ˜ μ΄ˆκΈ°ν™” ν‘œμ€€νŽΈμ°¨ μ„€μ • 및 ν•™μŠ΅ ν•¨μˆ˜ μ •μ˜
def __train(weight_init_std):
    # 배치 μ •κ·œν™”λ₯Ό μ μš©ν•œ 신경망 λͺ¨λΈκ³Ό μ μš©ν•˜μ§€ μ•Šμ€ 신경망 λͺ¨λΈ 생성
    bn_network = MultiLayerNetExtend(input_size=784,
                                     hidden_size_list=[100, 100, 100, 100, 100],
                                     output_size=10,
                                     weight_init_std=weight_init_std,
                                     use_batchnorm=True)  # 배치 μ •κ·œν™” μ‚¬μš©
    network = MultiLayerNetExtend(input_size=784,
                                  hidden_size_list=[100, 100, 100, 100, 100],
                                  output_size=10,
                                  weight_init_std=weight_init_std)  # 배치 μ •κ·œν™” λ―Έμ‚¬μš©
    optimizer = SGD(lr=learning_rate)  # ν™•λ₯ μ  경사 ν•˜κ°•λ²•

    train_acc_list = []  # ν•™μŠ΅ 정확도 기둝 리슀트
    bn_train_acc_list = []  # 배치 μ •κ·œν™” 적용 ν•™μŠ΅ 정확도 기둝 리슀트

    iter_per_epoch = max(train_size / batch_size, 1)
    epoch_cnt = 0

    for i in range(1000000000):
        batch_mask = np.random.choice(train_size, batch_size)  # λ¬΄μž‘μœ„ 배치 μƒ˜ν”Œλ§
        x_batch = x_train[batch_mask]
        t_batch = t_train[batch_mask]

        for _network in (bn_network, network):
            grads = _network.gradient(x_batch, t_batch)  # 기울기 계산
            optimizer.update(_network.params, grads)  # κ°€μ€‘μΉ˜ μ—…λ°μ΄νŠΈ

        if i % iter_per_epoch == 0:
            train_acc = network.accuracy(x_train, t_train)  # 정확도 계산
            bn_train_acc = bn_network.accuracy(x_train, t_train)  # 배치 μ •κ·œν™” 적용 정확도 계산
            train_acc_list.append(train_acc)
            bn_train_acc_list.append(bn_train_acc)

            print("epoch:" + str(epoch_cnt) + " | " + str(train_acc) + " - "
                  + str(bn_train_acc))

            epoch_cnt += 1
            if epoch_cnt >= max_epochs:
                break

    return train_acc_list, bn_train_acc_list


# κ·Έλž˜ν”„ 그리기==========
weight_scale_list = np.logspace(0, -4, num=16)
x = np.arange(max_epochs)

for i, w in enumerate(weight_scale_list):
    print("============== " + str(i+1) + "/16" + " =============

Batch Normalization 효과: Batch Normalizationκ°€ ν•™μŠ΅ 속도λ₯Ό 높인닀.

  • 보면 Batch Normalization (배치 μ •κ·œν™”)κ°€ ν•™μŠ΅μ„ 빨리 μ§„μ „μ‹œν‚€κ³  μžˆμŠ΅λ‹ˆλ‹€.
  • 그러면 Weight μ΄ˆκΉƒκ°’μ˜ ν‘œμ€€νŽΈμ°¨λ₯Ό λ‹€μ–‘ν•˜κ²Œ λ΄κΏ”κ°€λ©΄μ„œ ν•™μŠ΅ κ²½κ³Όλ₯Ό κ΄€μ°°ν•œ κ·Έλž˜ν”„ μž…λ‹ˆλ‹€.

  • 거이 λͺ¨λ“  κ²½μš°μ—μ„œ Batch Normalization(배치 μ •κ·œν™”)λ₯Ό μ‚¬μš©ν•  λ•Œμ˜ Training(ν•™μŠ΅) 속도가 λΉ λ₯Έ κ²ƒμœΌλ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€.
  • μ‹€μ œλ‘œ Batch Normalization(배치 μ •κ·œν™”)λ₯Ό μ΄μš©ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ—λŠ” μ΄ˆκ°“κ°’μ΄ 잘 λΆ„ν¬λ˜μ–΄ μžˆμ§€ μ•ŠμœΌλ©΄ Training(ν•™μŠ΅)이 μ „ν˜€ μ§„ν–‰λ˜μ§€ μ•Šμ€ λͺ¨μŠ΅λ„ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.
Summary: Batch Normalization(배치 μ •κ·œν™”)λ₯Ό μ‚¬μš©ν•˜λ©΄ Training(ν•™μŠ΅)이 빨리자면, Weight(κ°€μ€‘μΉ˜) μ΄ˆκΉƒκ°’μ— 크게 의쑴 ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€λŠ” νŠΉμ§•μ΄ μžˆμŠ΅λ‹ˆλ‹€.