3 분 소요

“핸즈온 머신러닝”의 “11장 심층 신경망 훈련하기” 파트를 읽고 공부한 내용을 정리해보았다. 그레디언트 소실과 폭주 문제 해결 방법인 배치 정규화와 그레디언트 클리핑에 대해 다뤄볼 것이다.

11.1.3 배치 정규화

  • 배치 정규화: 그레디언트 소실과 폭주 문제 해결 방법 중 하나이다.

    • 장점

      • 수렴성 활성화 함수 사용 가능 (하이퍼볼릭 탄젠트나 로지스틱 활성화 함수)

      • 훨씬 큰 학습률을 사용하여 학습 과정의 속도를 크게 높일 수 있다.

      • 규제와 같은 역할을 하여 다른 규제 기법의 필요성을 줄여준다.

    • 단점

      • 모델의 복잡도를 키운다.

      • 훈련 실행 속도가 느리다. => but 훈련이 끝난 후에 이전 층과 배치 정규화 층을 합쳐 실행 속도 저하를 피할 수 있다. 수렴이 빨라 상쇄 가능!

  • 각 층에서 활성화 함수 통과 전이나 후에 1. 입력을 정규화한 다음, 2. 스케일을 조정하고 3. 이동시킨다.

    • 파라미터 => 하나는 스케일 조정, 하나는 이동시킨다.

    • 결과적으로 4개의 파라미터를 추가한다.

      • 입력의 평균 벡터 μ

      • 입력의 표준편차 벡터 σ

      • 층의 출력 스케일 벡터 γ

      • 층의 출력 이동 벡터 β

        image

    • 지수 이동 평균을 사용해 추정

      • μ, σ
    • 역전파를 통해 학습

      • γ, β
  • 구현: BatchNormalization 층을 은닉층의 활성화 함수 전이나 후에 추가하면 된다.


케라스로 배치 정규화 구현하기

  • 아래 코드는 은닉층 2개를 가진 작은 예제라 배치 정규화가 큰 도움이 되지 않을 수 있다. 깊은 네트워크에서는 엄청난 차이를 만들 수 있다.
import keras
model = keras.models.Sequential([
    keras.layers.Flatten(input_shape=[28, 28]),
    keras.layers.BatchNormalization(),
    keras.layers.Dense(300, activation='elu', kernel_initializer='he_normal'),
    keras.layers.BatchNormalization(),
    keras.layers.Dense(100, activation='elu', kernel_initializer='he_normal'),
    keras.layers.BatchNormalization(),
    keras.layers.Dense(10, activation='softmax')
])
model.summary()
Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten_1 (Flatten)         (None, 784)               0         
                                                                 
 batch_normalization_3 (Batc  (None, 784)              3136      
 hNormalization)                                                 
                                                                 
 dense_3 (Dense)             (None, 300)               235500    
                                                                 
 batch_normalization_4 (Batc  (None, 300)              1200      
 hNormalization)                                                 
                                                                 
 dense_4 (Dense)             (None, 100)               30100     
                                                                 
 batch_normalization_5 (Batc  (None, 100)              400       
 hNormalization)                                                 
                                                                 
 dense_5 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 271,346
Trainable params: 268,978
Non-trainable params: 2,368
_________________________________________________________________
  • 첫 번째 배치 정규화 층은 4x784=3136개의 파라미터로 구성되었고, 두 번째 정규화 층은 4x300=1200개의 파라미터로 구성되었다. 4는 배치 정규화에서 추가된 파라미터이다.

  • 배치 정규화 파라미터의 전체 개수 = 3136+1200+400


첫 번째 배치 정규화 층의 파라미터를 살펴보자

# 첫 번째 배치 정규화 층의 파라미터를 살펴보기
[(var.name, var.trainable) for var in model.layers[1].variables]
[('batch_normalization_3/gamma:0', True),
 ('batch_normalization_3/beta:0', True),
 ('batch_normalization_3/moving_mean:0', False),
 ('batch_normalization_3/moving_variance:0', False)]
  • γ, β는 역전파로 훈련되고, μ, σ는 역전파로 훈련되지 않는다.

  • 배치 정규화 층 훈련 시 매 반복마다 2개의 연산이 함께 생성되며, 이동 평균을 업데이트한다.


TIP

  • 일반적으로 활성화 함수 이후보다 활성화 함수 이전에 배치 정규화 층을 추가하는 것이 좋다. 그러나 두 가지 방법 모두 해보고 데이터셋에 더 잘 맞는 방법을 채택하자.

  • 활성화 함수 이전에 배치 정규화층을 추가하려면 활성화함수를 별도의 층으로 추가해야한다.

  • 배치 정규화 층은 입력마다 이동 파라미터를 포함하기 때문에 이전 층에서 편향을 뺼 수 있다.

model = keras.models.Sequential([
    keras.layers.Flatten(input_shape=[28, 28]),
    keras.layers.BatchNormalization(),
    keras.layers.Dense(300, kernel_initializer='he_normal', use_bias=False),
    keras.layers.BatchNormalization(),
    keras.layers.Activation('elu'),
    keras.layers.Dense(100, kernel_initializer='he_normal', use_bias=False),
    keras.layers.BatchNormalization(),
    keras.layers.Activation('elu'),
    keras.layers.Dense(10, activation='softmax')
])


TIP

  • BatchNormalization의 하이퍼파라미터

    • 가끔 momentum 매개변수를 변경해야할 수 있다.

      • BatchNormalization층이 지수 이동 평균을 업데이트할 때 momentum 하이퍼파라미터를 사용한다.
    • axis 하이퍼파라미터: 이 매개변수는 정규화할 축을 결정한다. 기본값은 -1이다.

  • 심층 신경망에서 널리 사용하는 층이라 신경망 그림에서 빠져있을 수 있다.

  • 하지만 새로운 Fixup 가중치 초기화 기법을 사용하여 배치 정규화 없이 매우 깊은 심층 신경망을 훈련해 복잡한 이미지 분류 작업에서 최고의 성능을 달성한 사례가 있었다. => but 뒷받침할 추가 연구가 나온 뒤에 배치 정규화를 제거하는 것이 좋다.

11.1.4 그레이디언트 클리핑

  • 그레디언트 폭주 문제를 완화하는 인기있는 방법 중 하나이다.

  • 역전파될 때 일정 임계값을 넘어서지 못하게 그레디언트를 잘라내는 방법이다.

  • 순환 신경망에서 배치 정규화를 적용하기 어렵기 때문에 그레디언트 클리핑을 사용한다.

  • 구현: 옵티마이저를 만들 때 clipvalue와 clipnorm 매개변수를 지정하면 된다.

  • 클리핑 매개변수 지정하기

    • 텐서보드를 사용해 그레디언트의 크기를 추적하며 폭주 시에 클리핑할 수 있다.

    • 검증 세트에서 어떤 방식이 좋은 성과를 내는지 확인할 수 있다.

import keras
optimizer = keras.optimizers.SGD(clipvalue=1.0)
model.compile(loss='mse', optimizer=optimizer)

코드 설명

  • 위의 옵티마이저는 그레디언트 벡터의 모든 원소를 -1과 1 사이로 클리핑한다.

    • 임계값은 하이퍼파라미터로 튜닝할 수 있다.
  • 그레이디언트 벡터의 방향을 바꿀 수 있다.

    • ex) [0.9, 100] (클리핑 후)=> [0.9, 1]
  • 클리핑이 그레디언트 벡터의 방향을 바꾸지 못하도록 하려면 clipvalue 대신 clipnorm을 지정하면 된다

    • norm이 지정한 임계값보다 크면 전체 그레디언트를 클리핑한다.

    • ex) [0.9, 100] (clipnorm=1, 클리핑 후)=> [0.00899964, 0.9999595]

    • 방향은 그대로 유지되지만 첫 번째 원소는 거의 무시된다.



지금까지 그레디언트 소실, 폭주 문제를 해결하는 방법인 ReLU 활성화함수, 배치 정규화, 그레디언트 클리핑에 대해 알아보았다. 다음 포스트에서는 전이학습에 대해 다뤄볼 것이다.

댓글남기기