My Data Story

[딥러닝] 인공 신경망 - 모델 저장과 복원, 콜백, 텐서보드 본문

Deep Learning

[딥러닝] 인공 신경망 - 모델 저장과 복원, 콜백, 텐서보드

Hwasss 2021. 9. 5. 00:04
728x90

◈  '인공 신경망' 목차 

1. 퍼셉트론

2. 다층 퍼셉트론

3. 케라스 API 소개

4. 시퀀셜 API 구현

5. 함수형 API 구현

6. 서브클래싱 API 구현

7. 모델 저장과 복원, 콜백, 텐서보드

    시퀀셜 API와 함수형 API를 통해 구현한 모델을 저장하고 복원하는 방법에 대해 살펴보고

     특정 시점에 원하는 조건의 모델을 저장하도록 설정하는 콜백 구현 방법에 대해 살펴보고

     모델 훈련 후 모델에 대한 summary 를 시각화하여 분석할 수 있는 텐서보드 구현 방법에 대해 알아보자.

8. 신경망 하이퍼파라미터 튜닝하기


1. 모델 저장과 복원 

시퀀셜 API와 함수형 API를 사용하면 훈련된 케라스 모델을 저장하는 것은 매우 쉽다.

 

케라스는 HDF5 포맷을 사용하여 모든 층의 하이퍼파라미터와 더불어, 모델 구조와 층의 모든 모델 파라미터(연결 가중치와 편향)를 저장한다. 또한 하이퍼파라미터와 현재 상태를 포함하여 옵티마이저도 저장한다.

 

model = keras.models.Sequenetial([...])
model.compile([...])
model.fit([...])

model.save('my_keras_model.h5')

 

일반적으로 하나의 파이썬 스크립트에서 훈련하고 저장한 다음, 하나 이상의 스크립트(웹 또는 서비스)에서 모델을 로드하고 예측을 만드는데 활용한다. 모델 로드는 다음과 같다. 

 

model = keras.models.load_model('my_keras_model.h5')

 

위 방식은 시퀀셜 API와 함수형 API에서 사용 가능하지만, 모델 서브 클래싱에서는 사용할 수 없다. 

모델 서브 클래싱에는 save_weights() 와 load_weights() 가 없기 때문이다. 

대신, 파이썬의 피클(pickle) 모듈을 사용하여 모델 객체를 직렬화할 수 있다.

 

 

2. 콜백 사용하기

fit() 메서드의 callbacks 매개 변수를 사용하여 케라스가 훈련의 시작이나 끝에 호출할 객체 리스트를 지정할 수 있다.

또는 에포크의 시작이나 끝, 각 배치 처리 전후에 호출할 수도 있다. 

2.1 ModelCheckPoint 콜백

ModelCheckPoint는 훈련하는 동안 일정한 간격으로 모델의 체크 포인트를 저장한다. 

기본적으로 매 에포크의 끝에서 호출된다. 

[...] #모델 만들고 컴파일 하기
checkpoint_cb = keras.callbacks.ModelCheckpoint('my_keras_model.h5')
history = model.fit(X_train, y_train, epochs=10, callbacks=[checkpoint_cb])

 

훈련하는 동안 검증 세트를 사용하면 ModelCheckpoint 만들 때 save_best_only=True로 지정할 수 있다.

이렇게 하면 최상의 검증 세트 점수에서만 모델을 저장한다. 

오랜 훈련 시간으로 훈련 세트에 과대적합될 걱정하지 않아도 된다. 

훈련이 끝난 후 마지막에 저장된 모델을 복원하면 된다. 

그 모델이 검증 세트에서 최상의 점수를 낸 모델이다. 

 

2.2 EarlyStopping 콜백

조기 종료를 구현하는 방법 중 EarlyStopping 콜백을 사용하는 방법이 있다.

일정 에포크(patience 매개 변수로 지정한다.) 동안 검증 세트에 대한 점수가 향상되지 않으면 훈련을 멈춘다. 

선택적으로 최상의 모델을 복원할 수 있다. 

 

컴퓨터가 문제를 일으키는 경우를 대비하여 체크 포인트 저장 콜백과

시간과 컴퓨팅 자원을 낭비하지 않기 위해 진전이 없는 경우 훈련을 일찍 멈추는 콜백을 함께 사용할 수 있다.

 

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

history = model.fit(X_train, y_train,
                    epochs=100,
                    validation_data=(X_valid, y_valid),
                    callbacks=[checkpoint_cb, early_stopping_cb])

 

EarlyStopping 콜백이 훈련이 끝난 후 최상의 가중치를 복원하기 때문에 저장된 모델을 따로 복원할 필요는 없다.

 

2.3 사용자 정의 콜백

더 많은 제어를 원한다면 사용자 정의 콜백을 만들 수 있다. 

 

다음 예는 훈련하는 동안 검증 손실과 훈련 손실의 비율을 측정하여 과대 적합을 감지한다. 

 

class PrintValTrainRatioCallback(keras.callbacks.Callback) : 
   def on_epoch_end(self, epoch, logs) :
       print('\n val/train: {:.2f}'.format(logs['val_loss'] / logs['loss'])

 

예상할 수 있겠지만 on_train_begin(), on_train_end(), on_epoch_begin(), on_epoch_end(), on_batch_end() 등 원하는 시점의 모델을 저장하도록 사용자 정의 콜백을 만들 수 있다.

 

 

3. 텐서보드

텐서보드는 매우 좋은 인터렉티브 시각화 도구이다. 

 

훈련하는 동안 학습 곡선을 그리거나 여러 실행간의 학습 곡선을 비교하고 계산 그래프 시각화와 훈련 통계 분석을 수행할 수 있다. 

또한 모델이 생성한 이미지를 확인하거나 3D에 투영된 복잡한 다차원 데이터를 시각화하고 자동으로 클러스터링을 해주는 등 많은 기능을 제공한다. 

 

텐서보드는 텐서플로 설치할 때 자동으로 설치되므로 이미 시스템에 준비되어 있다. 

 

텐서보드를 사용하려면 프로그램을 수정하여 이벤트 파일이라는 특별한 이진 로그 파일에 시각화하려는 데이터를 출력해야 한다. 

각각의 이진 데이터 레코드를 서머리라고 부른다. 

 

텐서보드 서버는 로그 디렉터리를 모니터링하고 자동으로 변경 사항을 읽어 그래프를 업데이트한다. 

일반적으로 텐서보드 서버가 루트 로그 디렉터리를 가리키고 프로그램을 실행할 때마다 다른 서브 디렉터리에 이벤트를 기록한다.

이렇게 하면 복잡하지 않게 하나의 텐서보드 서버가 여러 번 실행한 프로그램의 결과를 시각화하고 비교할 수 있다. 

 

step1

우선 텐서보드 로그를 위해 사용할 루트 로그 디렉터리를 정의한다.

 

import os 
root_logdir = os.path.join(os.curdir, 'my_logs')

def get_run_logdir() : 
    import time
    run_id = time.strftime('run_%Y_%m_%d_%H_%M_%S')
    return os.path.join(root_logdir, run_id)
    
run_logdif = get_run_logdir() #예를 들어, './my_logs/run_2021_09_06_23_40'

 

step2

케라스는 TensorBoard()를 지원한다.

 

[...] #모델 구성과 컴파일
tensorboard_cb = keras.callbacks.TensorBoard(run_logdir)
history = model.fit(X_train, y_train,
                    epochs=30,
                    validation_data=(X_valid, y_valid),
                    callbacks=[tensorboard_cb])

 

위 코드를 실행하면, TensorBoard() 콜백이 로그 디렉터리를 생성한다. 훈련하는 동안 이벤트 파일을 만들고 서머리를 기록한다.

일부 하이퍼파라미터를 바꾼 후 프로그램을 두 번째 실행하고 나면 실행 시간 이름의  디렉터리 구조가 또 생성된다.  

즉 실행마다 하나의 디렉터리가 생성된다. 

 

디렉터리 아래 훈련 로그를 위한 서브 디렉터리와 검증 로그를 위한 서브 디렉터리가 포함된다. 

둘 다 이벤트 파일을 담고 있다. 

훈련 로그는 프로파일링 트레이스 파일도 포함된다. 

텐서보드가 이 파일을 사용해 전체 디바이스에 걸쳐 모델의 각 부분에서 시간이 얼마나 소요되었는 지 보여주므로 성능 병목 지점을 찾는데 큰 도움이 된다.

 

step3

이제 텐서보드 서버를 시작할 차례이다. 

 

방법1

터미널 명령을 실행

virtualenv 안에서 텐서플로를 설치했다면 이 환경을 먼저 활성화해야 한다. 

그 다음 프로젝트 루트 디렉터리에서 또는 로그 디렉터리를 지정한 상위 디렉터리에서 다음 명령을 실행한다.

 

$ tensorboard --logdir=./my_logs --port=6006

 

■ 방법2

주피터 안에서 바로 텐서보드를 사용할 수도 있다.

 

%load_ext tensorboard
%tensorboard --logdir=./my_logs --port=6006

 

어떤 방법이던 텐서보드 웹 인터페이스를 보게 될 것이다. 

 

 

 

※ tf.summary 내용 기록하기

텐서플로는 tf.summary 패키지로 저수준 API를 제공한다. 

다음 코드는 create_filte_writer() 함수를 사용해 SummaryWriter를 만들고 with 블럭 안에서 텐서 보드를 사용해 시각화할 수 있는 스칼라, 히스토그램, 이미지, 오디오, 텍스트를 기록한다. 

 

test_logdir = get_run_logdir()

writer = tf.summary.create_filte_writer(test_logdir)

with writer.as_default() :
     for step in range(1, 1000+1) : 
         tf.summary.scalar('my_scalar', np.sin(step/10), step=step)
         
         data = (np.random.randn(100)+2) * step/100
         tf.summary.histogram('my_histogram', data, buckets=50, step=step)
         
         images = np.random.rand(2,32,32,3) #32X32 RGB 이미지
         tf.summary.image('my_images', images*step/1000, step=step)
         
         texts = ['This step is' + str(step), 'Its square is' + str(step**2)]
         tf.summary.texts('my_text', texts, step=step)
         
         sine_wave = tf.math.sin(tf.range(12000)/4800*2*np.pi*step)
         audio = tf.reshape(tf.cast(sine_wave, tf.float32), [1,-1,1])
         tf.summary.audio('my_audio', audio, sample_rate=48000, step=step)