심층신경망(규제 방법)


💡 검증 손실

에포크에 대한 과대적합과 과소적합을 파악하려면 훈련 세트에 대한 점수 뿐만 아니라

검증 세트에 대한 점수도 필요하다.

에포크마다 검증 손실을 계산하기 위해 keras 모델의 fit() 메서드에 검증 데이터를

전달할 수 있다. validation_data 매개변수에 검증에 사용할 입력과 타깃값을

tuple로 만들어 전달한다.



💡 손실 곡선

fit() 메서드로 모델을 훈련하면 훈련과정이 상세하게 출력되어 확인할 수 있었다.

근데 마지막에는 다음과 같은 메세지가 출력된다.

<keras.callbacks.History at 0x7f6d4817e050>

위 메세지는 fit() 메서드의 실행 결과를 출력한 것이다. 다시 말해 fit() 메서드가

무엇인가를 반환한다는 뜻이다. 실은 keras의 fit() 메서드는 History 클래스 객체를

반환한다. History 객체에는 훈련 과정에서 계산한 지표, 즉 손실과 정확도 값이

저장되어 있다. 이 값을 사용하면 손실과 정확도에 관한 그래프를 그릴수 있다.



💡 Dropout

이 방식은 훈련 과정에서 층에 있는 일부 뉴런을 랜덤하게 꺼서 과대 적합을 막는다.

즉, 뉴런의 출력을 0으로 만든다

드롭아웃이 과대적합을 막는 이유는, 이전 층의 일부 뉴런이 랜덤하게 꺼지면 특정

뉴런에 과대하게 의존하는 것을 줄일 수 있고 모든 입력에 대해 주의를 기울여야 한다.

일부 뉴런의 출력이 없을 수 있다는 것을 감안하면 이 신경망은 더 안정적인

예측을 만들 수 있다.


아래의 출력 값에서 볼 수 있듯이, 은닉층 뒤에 추가된 드롭아웃은 훈련되는

모델 파라미터가 없다. 또한 입력과 출력의 크기가 같다.

일부 뉴런의 출력을 0으로 만들지만 전체 출력 배열의 크기를 바꾸지는 않는다.


훈련이 끝난 뒤에 평가나 예측을 수행할 때는 드롭아웃을 적용하면 안된다.

왜냐면 훈련된 모든 뉴런을 사용해야 올바른 예측을 할 수 있기 때문이다.

다행이도 텐서플로와 케라스는 모델을 평가와 예측에 사용할 때는 자동으로

드롭아웃을 적용하지 않는다.



💡 Callback

콜백은 훈련 과정 중간에 어떤 작업을 수행할 수 있게 하는 객체로 keras.callbacks 패키지

아래에 있는 클래스들이다. fit() 메서드의 callbacks 매개변수에 리스트로 전달하여 사용한다.

ModelCheckpoint 클래스는 기본적으로 에포크마다 모델을 저장한다.

save_best_only=True 매개변수를 지정하여 가장 낮은 검증 점수를 만드는 모델을 저장할 수 있다.



💡 조기 종료 (Early Stopping)

콜백을 사용함으로 써 가장 낮은 검증 점수의 모델을 자동으로 저장해 주었다.

하지만 여전히 20번의 에포크 동안 훈련을 하는 아쉬운 부분이 있다.

사실 검증 점수가 상승하기 시작하면 그 이후에는 과대적합이 더 커지기 때문에 훈련을

계속할 필요가 없다. 즉, 이때 훈련을 중지하면 컴퓨터 자원과 시간을 아낄수 있다.

이렇게 과대적합이 시작되기 전에 훈련을 미리 중지하는 것을 Early Stopping이라고 한다.

조기 종료는 훈련 에포크 횟수를 제한하는 역할이지만 모델이 과대적합되는 것을

막아주기 때문에 규제 방법 중 하나로 생각할 수 있다.

keras에는 조기 종료를 위한 EarlyStopping 콜백을 제공한다.

콜백의 patience 매개변수는 검증 점수가 향상되지 않더라도 참을 에포크 횟수로 지정한다.



🔎 심층신경망 훈련 실습

데이터 불러오기 생략.


모델을 함수로 만들기

def model_fn(a_layer=None):
    model = keras.Sequential()
    model.add(keras.layers.Flatten(input_shape=(28,28)))
    model.add(keras.layers.Dense(100, activation='relu'))
    if a_layer:
        model.add(a_layer)
    model.add(keras.layers.Dense(10, activation='softmax'))
    return model


모델링

# Dropout 추가
model = model_fn(keras.layers.Dropout(0.3))

# 컴파일
model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics='accuracy'
)

# ModelCheckpoint
checkpoint_cb = keras.callbacks.ModelCheckpoint(
    'best-model.h5',
    save_best_only=True
)

# EarlyStopping
early_stopping_cb = keras.callbacks.EarlyStopping(
    patience=2,
    restore_best_weights = True
)

history = model.fit(
    train_scaled, train_target, epochs=20, verbose=0,
    validation_data=(val_scaled,val_target),
    callbacks=[checkpoint_cb, early_stopping_cb]
)


몇 번째 epoch에서 훈련이 중지 되었는지 확인

print(early_stopping_cb.stopped_epoch)
# 출력 : 14

patience=2로 지정해 줬다. 2번 연속 검증 점수가 향상되지 않으면 훈련을

중지시키겠다는 의미이다.

여기서 출력값이 ‘14’가 나왔다. 에포크가 0부터 시작했기 때문에 14는 15번째

에폭에서 훈련이 중지 되었다는 뜻이다.

다시 말해 14, 15번 째 에폭에서는 성능 향상이 없었다는 뜻으로 이해할 수 있다.

결과적으로 13번째 에폭에서 최상의 성능을 보여줬다는 의미로 해석할 수 있고,

아래의 손실곡선에서 시각적으로 확인할 수 있다.



손실곡선

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train','val'])
plt.show()



💡 모델 저장과 복원

기본적으로 아래의 메서드는 텐서플로의 SavedModel 포맷으로 저장하지만

파일 확장자가 .h5일 경우 HDF5 포맷으로 저장한다.


save_weights() : 훈련된 모든 파라미터를 저장

load_weights()

save() : 모델 구조와 모델 파라미터를 저장

load_model()

!ls -al *.h5 : .h5확장자로 저장된 모델 확인