$l_1$, $l_2$ 규제

선형 모델의 비용 함수에 적용한 $l_1$, $l_2$ 규제처럼 신경망에서도 이를 적용할 수 있다.

# l2
layer = tf.keras.layers.Dense(100, activation='relu',
                              kernel_initializer = 'he_normal',
                              kernel_regularizer=tf.keras.regularizers.l2(0.01))

$l_1$ 규제를 적용하고 싶다면 tf.keras.regularizers.l1, 둘 다 적용하고 싶다면 tf.keras.regularizers.l1_l2를 사용한다.

파이썬의 functools.partial()을 사용하면 동일한 활성화 함수 및 초기화 전략을 사용하는 층을 간결하게 구현할 수 있다.

from functools import partial

RegularizedDense = partial(tf.keras.layers.Dense,
                           activation='relu',
                           kernel_initializer='he_normal',
                           kernel_regularizer=tf.keras.regularizers.l2(0.01))

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[28, 28]),
    RegularizedDense(100),
    RegularizedDense(100),
    RegularizedDense(10, activation='softmax')
])


DropOut

Dropout에서는 매 훈련 스텝에서 각 뉴런은 임시적으로 dropout될 확률 p를 가진다. 만약 해당 뉴런이 dropout되었다면 이번 훈련 스텝에서는 완전히 무시되는 것이다(다음에는 복귀할 수도 있다). 이때 p를 dropout 비율이라고 한다. 보통 10~50%이다. 훈련이 끝다면 더 이상 dropout은 적용되지 않는다.

Dropout을 직관적으로 이해하는 방법에는 두 가지가 있다.

  1. 만약 어떤 회사에서 직원의 출근 여부를 동전 던지기로 정한다고 하자. 그럼 어느 한 직원에게 의존하는 일 없이 모든 직원이 어느 정도의 전문성을 가지게 될 것이다. 다른 직원과 협력하는 법을 배워야 하고, 유연성도 훨씬 높아지며, 퇴사하는 직원이 생겨도 큰 문제가 되지 않을 것이다. 이를 신경망에 그대로 적용해보면, 각 뉴런은 스스로가 유용해져야 하고, 다른 뉴런에 의존할 수 없다. 즉, 입력 값의 작은 변화에 덜 민감해지며 신경망의 일반화 성능이 좋아진다.

  2. 일부 뉴런을 훈련 스텝마다 제외하므로, 산술적으로 $2^N$ 개의 고유한 신경망을 만들 수 있다. 즉, 최종적인 신경망은 많은 신경망을 앙상블한 결과로 볼 수 있다.

한 가지 주의할 점은, 훈련하는 동안 각 연결 가중치를 보존 확률(1-p)로 나누어주어야 한다는 점이다. 이는 훈련이 종료된 이후에, 각 뉴런이 훈련할 때보다 더 많은 연결에 입력되는 상황을 고려한 것이다.

keras에서는 간단하게 Dropout층을 사용하기만 하면 모든 것을 자동으로 처리해준다.

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[28, 28]),
    tf.keras.layers.Dropout(rate=0.2),
    tf.keras.layers.Dense(100, activation='relu',
                          kernel_initializer='he_normal'),
    tf.keras.layers.Dropout(rate=0.2),
    tf.keras.layers.Dense(100, activation='relu',
                          kernel_initializer='he_normal'),
    tf.keras.layers.Dropout(rate=0.2),
    tf.keras.layers.Dense(10, activation='softmax')
])

모델이 과대적합이라면 dropout 비율을 늘리고, 과소적합이라면 비율을 줄인다.

최신 신경망은 마지막 은닉 층 뒤에만 dropout을 사용하는 경우도 많다.


Monte Carlo Dropout

몬테 카를로(MC) dropout은 기존 dropout 모델에 하나도 손을 대지 않고도 성능을 크게 향상시킬 수 있다.

import numpy as np

y_probas = np.stack([model(X_test, training=True)   # model has dropout layers
                    for sample in range(100)])

y_proba = y_probas.mean(axis=0)

위 코드의 작동 원리를 간단하게 살펴보면 다음과 같다.

  1. model() 메서드는 model.predict() 메서드와 비슷하게 작동한다. training=True를 통해 dropout 층이 활성화된다.
  2. 모델을 호출할 때마다 (샘플 수, 클래스 수)의 모양을 가진 행렬이 반환된다. 즉, 100번 실행해서 행렬을 쌓았으므로 (100, 샘플 수, 클래스 수) 의 모양을 가진 3차원 배열이 y_probas에 반환된다.
  3. 2번의 3차원 배열을 첫 번째 차원(axis=0) 기준으로 평균을 내었다. 여기서 그럼 한 번 예측을 수행했을 때와 마찬가지인 (샘플 수, 클래스 수) 모양의 행렬이 반환된다.

요약하면, dropout이 포함된 모델의 여러 예측 결과를 평균 내는 것이라고 볼 수 있다.

MC dropout은 모델이 만든 확률 추정치의 신뢰성을 높인다. 즉, 모델의 자신감을 높인다.

만약 모델이 BatchNormalization과 같이 훈련하는 동안 다르게 작동하는 층을 가지고 있다면 Dropout 층을 다음과 같은 MCDropout 클래스로 바꾸어주어야 한다.

# MCDropout class
class MCDropout(tf.keras.layers.Dropout):
    def call(self, inputs, training=False):
        return super().call(inputs, training=True)


Max-norm

Max-norm 규제는 각각의 뉴런에 대해 입력의 연결 가중치 $\bf{w}$ 가 $\vert \vert \bf{w} \vert \vert_2 \leq r$ 이 되도록 제한한다. r은 max-norm 하이퍼파라미터이고, $\vert \vert \cdot \vert \vert_2$ 은 $l_2$ norm을 의미한다.

Max-norm은 손실 함수는 건드리지 않는다. 대신, 매 훈련 스텝이 끝나고 $\vert \vert \bf{w} \vert \vert_2$ 를 계산해, 필요하다면 $\bf{w}$ 의 스케일을 조정한다.

dense = tf.keras.layers.Dense(
    100, activation='relu', kernel_initializer='he_normal',
    kernel_constraint=tf.keras.constraints.max_norm(1.)
)

max_norm()에는 다양한 매개변수가 있다. bias_constraint로 편향을 규제할 수도 있고, axis를 통해 필요에 따른 가중치 행렬의 적절한 축을 지정할 수도 있다.


가이드라인

기본적인 신경망 설정은 다음과 같다.

Hyperparameters Default
kernel initialization He
Activation Function ELU(shallow NN), Swish(Deep NN)
Normalizaiton No(shallow NN), Batch(Deep NN)
Regularization Early Stopping, (if need) weight decay
Optimizer NAG or AdamW
Learning Schedule Performance or 1cycle

완전 연결층을 쌓은 단순한 모델이라면 자기 정규화를 사용할 수도 있다. 다음과 같이 구성하면 된다(입력 특성을 정규화해야 한다).

Hyperparameters Default
kernel initialization Lecun
Activation Function SELU
Normalizaiton No(self-normalization)
Regularization (if need) alpah dropout
Optimizer NAG
Learning Schedule Performance or 1cycle

물론 위 설정은 언제든 필요에 따라 변할 수 있다.


코드 보러가기



별도의 출처 표시가 있는 이미지를 제외한 모든 이미지는 강의자료에서 발췌하였음을 밝힙니다.

댓글남기기