가중치 규제하기
오캄의 면도날 (Occam's Razor) 이론에서는 어떤 것을 설명하는 두 가지 방법이 있다면 더 정확한 설명은 최소한의 가정이 필요한 가장 "간단한" 설명일 것이다. 이는 신경망으로 학습되는 모델에도 적용된다. 훈련 데이터와 네트워크 구조가 주어졌을 때 이 데이터를 설명할 수 있는 가중치의 조합 (즉, 가능한 모델)은 많다. 간단한 모델은 복잡한 것보다 과대적합되는 경향이 작을 것이다.
여기서 "간단한 모델"은 모델 파라미터의 분포를 봤을 때 엔트로피 (entropy)가 작은 모델이다 (또는 적은 파라미터를 가진 모델). 따라서, 과대적합을 완화시키는 일반적인 방법은 가중치가 작은 값을 가지도록 네트워크의 복잡도에 제약을 가하는 것이다. 이는 가중치 값의 분포를 좀 더 균일하게 만들어 준다. 이를 "가중치 규제" (weight regularization)라고 부른다. 네트워크의 손실 함수에 큰 가중치에 해당하는 비용을 추가한다. 이 비용은 두 가지 형태가 있다.
L1 규제는 일부 가중치 파라미터를 0으로 만든다. L2 규제는 가중치 파라미터를 제한하지만 완전히 0으로 만들지는 않는다. 이것이 L2 규제를 더 많이 사용하는 이유 중 하나이다.
tf.keras에서는 가중치 규제 객체를 층의 키워드 매개변수에 전달하여 가중치에 규제를 추가한다. L2 가중치 규제를 추가한다.
l2_model = keras.models.Sequential([
keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
activation='relu', input_shape=(NUM_WORDS,)),
keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
activation='relu'),
keras.layers.Dense(1, activation='sigmoid')
])
l2_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy', 'binary_crossentropy'])
l2_model_history = l2_model.fit(train_data, train_labels,
epochs=20,
batch_size=512,
validation_data=(test_data, test_labels),
verbose=2)
l2(0.001)는 네트워크의 전체 손실에 층에 있는 가중치 행렬의 모든 값이 0.001 * weight_coefficient_value**2만큼 더해진다는 의미이다. 이런 페널티 (penalty)는 훈련할 때만 추가된다. 따라서, 테스트 단계보다 훈련 단계에서 네트워크 손실이 훨씬 더 클 것이다.
L2 규제의 효과를 확인한다.
plot_history([('baseline', baseline_history),
('l2', l2_model_history)])
결과에서 보듯이 모델 파라미터의 개수는 같지만 L2 규제를 적용한 모델이 기본 모델보다 과대적합에 훨씬 잘 견디고 있다.
드롭아웃 추가하기
드롭아웃 (dropout)은 신경망에서 가장 효과적이고 널리 사용하는 규제 기법 중 하나이다. 토론토 (Toronto) 대학의 힌튼 (Hinton)과 그의 제자들이 개발했다. 드롭아웃을 층에 적용하면 훈련하는 동안 층의 출력 특성을 랜덤하게 끈다 (즉, 0으로 만든다). 훈련하는 동안 어떤 입력 샘플에 대해 [0.2, 0.5, 1.3, 0.8, 1.1] 벡터를 출력하는 층이 있다고 가정한다. 드롭아웃을 적용하면 이 벡터에서 몇 개의 원소가 랜덤하게 0이 된다. 예를 들면, [0, 0.5, 1.3, 0, 1.1]가 된다. "드롭아웃 비율"은 0이 되는 특성의 비율이다. 보통 0.2에서 0.5 사이를 사용한다. 테스트 단계에서는 어떤 유닛도 드롭아웃하지 않는다. 훈련 단계보다 더 많은 유닛이 활성화되기 때문에 균형을 맞추기 위해 층의 출력 값을 드롭아웃 비율만큼 줄인다.
tf.keras에서는 Dropout 층을 이용해 네트워크에 드롭아웃을 추가할 수 있다. 이 층은 바로 이전 층의 출력에 드롭아웃을 적용한다.
IMDB 네트워크에 두 개의 Dropout 층을 추가하여 과대적합이 얼마나 감소하는지 알아 본다.
dpt_model = keras.models.Sequential([
keras.layers.Dense(16, activation='relu', input_shape=(NUM_WORDS,)),
keras.layers.Dropout(0.5),
keras.layers.Dense(16, activation='relu'),
keras.layers.Dropout(0.5),
keras.layers.Dense(1, activation='sigmoid')
])
dpt_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy','binary_crossentropy'])
dpt_model_history = dpt_model.fit(train_data, train_labels,
epochs=20,
batch_size=512,
validation_data=(test_data, test_labels),
verbose=2)
plot_history([('baseline', baseline_history),
('dropout', dpt_model_history)])
드롭아웃을 추가하니 기준 모델보다 확실히 향상되었다.
정리하면 신경망에서 과대적합을 방지하기 위해 가장 널리 사용하는 방법은 다음과 같다.
|
마지막으로, 여기서 다루지 않은 중요한 방법 두 가지는 데이터 증식 (data-augmentation)과 배치 정규화 (batch normalization)이다.
https://www.tensorflow.org/tutorials/keras/overfit_and_underfit?hl=ko
'DNN with Keras > TensorFlow' 카테고리의 다른 글
[TensorFlow] 모델 저장 / 복원 (2) (0) | 2022.06.15 |
---|---|
[TensorFlow] 모델 저장 / 복원 (1) (0) | 2022.06.15 |
[TensorFlow] 과대적합 / 과소적합 (1) (0) | 2022.06.15 |
[TensorFlow] 회귀 (Regression) (2) (0) | 2022.06.15 |
[TensorFlow] 회귀 (Regression) (1) (0) | 2022.06.15 |