관리 메뉴

Bull

[DL] 데이터 정규화 요약 및 검증 본문

Artificial Intelligence/Deep Learning

[DL] 데이터 정규화 요약 및 검증

Bull_ 2024. 10. 20. 21:04

정규화는 예시로 설명하자면 0~255인 이미지 데이터를 0~1로 정규화하는 걸 말함.  활성화 함수에서 Internal Covariate Shift문제가 일어나지 않도록 기울기 안정성을 위해 진행.

 

쉽게 요약하자면,

  • 배치 정규화: 모든 샘플의 같은 채널끼리 (R끼리) 한 번에 정규화.
    • 모든 이미지의 채널만 모아서 기준을 만듬
  • 레이어 정규화: 각 샘플(이미지) 전체를 한 번에 정규화 (R, G, B 채널을 모두 포함).
    • 개별 이미지끼리 기준으로 만듬
  • 인스턴스 정규화: 각 샘플 내에서 채널별로 따로 정규화 (R, G, B 채널 각각 독립적으로).
    • 개별 이미지의 각 채널기준으로 각각 만듬
  • 그룹 정규화: 각 샘플의 채널을 그룹으로 나누어 그룹별로 정규화 (R과 G는 한 그룹, B는 다른 그룹 등).
    • 개별 이미지의 채널(R,G) 기준 따로, B만 따로 기준을 각각만듬.
      (RGB라 그렇지 심층 CNN에 갈수록 채널이 깊어짐)

1. Batch Normalization (배치 정규화):

  • 배치 내 모든 데이터에 대해 각 채널별로 정규화를 수행합니다.
  • 예를 들어, R 채널끼리, G 채널끼리, B 채널끼리 모든 배치 내 이미지를 대상으로 평균과 분산을 구해 정규화합니다.
  • 즉, 배치 내 모든 샘플에서 각 채널의 전체 값을 한 번에 정규화합니다.
  • 결과적으로, 배치에 속한 샘플들이 서로 다른 이미지일지라도 R 채널은 R 채널끼리, G 채널은 G 채널끼리 평균과 분산을 공유합니다.

2. Layer Normalization (레이어 정규화):

  • 각 이미지(샘플)에 대해 모든 채널(R, G, B 포함)을 한 번에 정규화합니다.
  • 즉, 하나의 이미지에서 R, G, B 채널의 값들을 한꺼번에 묶어 평균과 분산을 계산합니다.
  • 각 샘플마다 개별적인 정규화가 이루어지며, 배치에 포함된 다른 이미지들과는 정규화 과정이 공유되지 않습니다.
  • 결과적으로 샘플 하나하나가 독립적으로 정규화됩니다.

3. Instance Normalization (인스턴스 정규화):

  • 각 이미지(샘플) 내에서 각 채널별로 따로 정규화합니다.
  • 예를 들어, 하나의 이미지에서 R 채널만 별도로 정규화하고, 같은 이미지의 G 채널, B 채널도 각각 따로 정규화합니다.
  • 샘플별이지만 채널마다 독립적으로 정규화가 진행됩니다.
  • 주로 스타일 변환(Style Transfer) 같은 작업에 사용되며, 배치나 샘플 간 통계적 특성을 고려하지 않습니다.

4. Group Normalization (그룹 정규화):

  • 인스턴스의 채널을 그룹으로 묶어서 그 그룹 내에서만 정규화를 수행합니다.
  • 예를 들어, R과 G 채널을 한 그룹으로 묶고 이 그룹 내에서 정규화, B 채널은 별도의 그룹으로 나누어 정규화합니다.
  • 인스턴스의 채널들을 그룹으로 나누어 그룹별로 정규화를 하여, 배치 크기에 덜 민감하게 동작합니다.
  • 소규모 배치나 다양한 상황에서 유용합니다.

 

내가 말한 게 맞는 지 검증해볼까?

import numpy as np

# 전체 데이터 채널끼리
# Example data: 2 samples, 3 channels, 2x2 feature map
data = np.array([[[[1.0, 2.0], [3.0, 4.0]],  # Sample 1, Channel 1 (R)
                  [[5.0, 6.0], [7.0, 8.0]],  # Sample 1, Channel 2 (G)
                  [[9.0, 10.0], [11.0, 12.0]]], # Sample 1, Channel 3 (B)
                 
                 [[[13.0, 14.0], [15.0, 16.0]],  # Sample 2, Channel 1 (R)
                  [[17.0, 18.0], [19.0, 20.0]],  # Sample 2, Channel 2 (G)
                  [[21.0, 22.0], [23.0, 24.0]]]]) # Sample 2, Channel 3 (B)

# Batch Normalization: mean and variance across N, H, W (across batches)
batch_mean = np.mean(data, axis=(0, 2, 3), keepdims=True)  # Mean over N, H, W
batch_var = np.var(data, axis=(0, 2, 3), keepdims=True)    # Variance over N, H, W
batch_norm = (data - batch_mean) / np.sqrt(batch_var + 1e-5)  # Normalize

print("Batch Normalization result:")
print(batch_norm)

# 각 데이터 샘플별
# Layer Normalization: mean and variance across C, H, W (per sample)
layer_mean = np.mean(data, axis=(1, 2, 3), keepdims=True)  # Mean over C, H, W
layer_var = np.var(data, axis=(1, 2, 3), keepdims=True)    # Variance over C, H, W
layer_norm = (data - layer_mean) / np.sqrt(layer_var + 1e-5)  # Normalize

print("Layer Normalization result:")
print(layer_norm)
Batch Normalization result:
[[[[-1.22884772 -1.06500135]
   [-0.90115499 -0.73730863]]

  [[-1.22884772 -1.06500135]
   [-0.90115499 -0.73730863]]

  [[-1.22884772 -1.06500135]
   [-0.90115499 -0.73730863]]]


 [[[ 0.73730863  0.90115499]
   [ 1.06500135  1.22884772]]

  [[ 0.73730863  0.90115499]
   [ 1.06500135  1.22884772]]

  [[ 0.73730863  0.90115499]
   [ 1.06500135  1.22884772]]]]
Layer Normalization result:
[[[[-1.59325435 -1.30357174]
   [-1.01388913 -0.72420652]]

  [[-0.43452391 -0.1448413 ]
   [ 0.1448413   0.43452391]]

  [[ 0.72420652  1.01388913]
   [ 1.30357174  1.59325435]]]


 [[[-1.59325435 -1.30357174]
   [-1.01388913 -0.72420652]]

  [[-0.43452391 -0.1448413 ]
   [ 0.1448413   0.43452391]]

  [[ 0.72420652  1.01388913]
   [ 1.30357174  1.59325435]]]]
import torch
import torch.nn as nn

# 데이터 생성: 2개의 샘플, 3개의 채널, 2x2 크기의 이미지
data = torch.tensor([[[[1.0, 2.0], [3.0, 4.0]],
                      [[5.0, 6.0], [7.0, 8.0]],
                      [[9.0, 10.0], [11.0, 12.0]]],
                     
                     [[[13.0, 14.0], [15.0, 16.0]],
                      [[17.0, 18.0], [19.0, 20.0]],
                      [[21.0, 22.0], [23.0, 24.0]]]])

# Batch Normalization
batch_norm_layer = nn.BatchNorm2d(3)  # 채널이 3개
batch_norm_result = batch_norm_layer(data)

# Layer Normalization
layer_norm_layer = nn.LayerNorm([3, 2, 2])  # 3개의 채널, 2x2 크기
layer_norm_result = layer_norm_layer(data)

print("Batch Normalization result:")
print(batch_norm_result)

print("Layer Normalization result:")
print(layer_norm_result)
Batch Normalization result:
tensor([[[[-1.2288, -1.0650],
          [-0.9012, -0.7373]],

         [[-1.2288, -1.0650],
          [-0.9012, -0.7373]],

         [[-1.2288, -1.0650],
          [-0.9012, -0.7373]]],


        [[[ 0.7373,  0.9012],
          [ 1.0650,  1.2288]],

         [[ 0.7373,  0.9012],
          [ 1.0650,  1.2288]],

         [[ 0.7373,  0.9012],
          [ 1.0650,  1.2288]]]], grad_fn=<NativeBatchNormBackward0>)
Layer Normalization result:
tensor([[[[-1.5933, -1.3036],
          [-1.0139, -0.7242]],

         [[-0.4345, -0.1448],
          [ 0.1448,  0.4345]],

         [[ 0.7242,  1.0139],
          [ 1.3036,  1.5933]]],


        [[[-1.5933, -1.3036],
          [-1.0139, -0.7242]],

         [[-0.4345, -0.1448],
          [ 0.1448,  0.4345]],

         [[ 0.7242,  1.0139],
          [ 1.3036,  1.5933]]]], grad_fn=<NativeLayerNormBackward0>)