Deep Learning/혼공 머신 러닝 - 딥러닝

[DL] 신경망 모델 훈련

KimTory 2022. 1. 4. 23:45

[용어 정리]

 

① Drop Out : 은닉층에 있는 뉴런의 출력을 랜덤하게 꺼내서 과대 적합을 막는 기법입니다.

→ 드롭 아웃은 훈련 중에 적용 되며, 평가나 예측에서는 사용 되지 않으며 텐서플로는 이를 자동으로 처리함

0.5 → 뉴런의 50%

② Call Back : 모델을 훈련하는 도중에 어떤 작업을 수행할 수 있도록 도와주는 일련의 도구

→ Tensorflow 사용 시, 모델을 훈련 시키는 동안 어떠한 이번테들이 발생하면 개발자가 원하는 동작을 수행할 수 있는

    방법을 제공하며, 이를 Callback 동작이라고도 한다.

 

④ 

조기 종료 : 학습 중, 과대 적합이 일어나기 전 또는 일어나면 훈련을 계속 진행하지 않고 멈추는 기법

→ 원리 :

케라스 에서는

EarlyStopping 이라는 콜백함수를 사용하여 필요 또는 적절한 시점에 학습을 조기 종료함

 

[TensorFlow 함수]

 

① Dropout : 드롭 아웃 층이며 매개변수로 비율(드롭아웃 할)이 존재함

② save_weights: 모든 층의 가중치와 절편을 파일에 저장 (저장 포맷도 별도로 설정 가능함)

③ load_weights : 모든 층의 가중치와 절편을 파일에 읽는다.

④ load_model : model.save()로 저장된 모델을 로드

 

 


[손실 곡선]

from tensorflow import keras
from sklearn.model_selection import train_test_split

(train_input, train_target), (test_input, test_target) = \
    keras.datasets.fashion_mnist.load_data()

// 정규화 (0,1) 
train_scaled = train_input / 255.0 
// 검증 데이터 분리 / 20%
train_scaled, val_scaled, train_target, val_target = train_test_split(
    train_scaled, train_target, test_size=0.2, random_state=42)
    
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
    
model = model_fn()
model.summary()
 
// result ------
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten (Flatten)           (None, 784)               0         
                                                                 
 dense (Dense)               (None, 100)               78500     
                                                                 
 dense_1 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0
// -------------
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')

history = model.fit(train_scaled, train_target, epochs=5, verbose=0)

print(history.history.keys())

// result

dict_keys(['loss', 'accuracy'])

// ------

import matplotlib.pyplot as plt

plt.plot(history.history['loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

손실 / 에폭 → 손실 감소

plt.plot(history.history['accuracy'])
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.show()

정확도 / 에폭 → 정확도 상승

▶ model.compile 함수의 매개 변수 중, metrics="accuracy"를 추가 하였기에 history 속성에 포함됨

 

→ epochs 횟수 증가

model = model_fn()
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')

// verbose default는 1이며, default 사용 시 에폭마다 진행 막대와 손실 지표가 출력됨
// 0 설정 시 훈련 과정을 표시하지 않음
history = model.fit(train_scaled, train_target, epochs=20, verbose=0)


[검증 손실]

model = model_fn()
model.compile(loss='sparse_categorical_crossentropy', metrics='accuracy')

history = model.fit(traun_scaled, train_target, epochs=20, verbose=0,
					validataion_data=(val_scaled, val_target))
                    
print(history.history.keys())
// result ------
// history는 다이렉션 형태로 데이터를 가지고 있음
dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])

// -------------


// train loss
plt.plot(history.history['loss'])
// validation loss
plt.plot(history.history['val_loss'])

plt.xabel("epochs")
plt.xabel("loss")
plt.legend(["train", "val"])

plt.show()

▶ 5번째 epochs 그래프를 보면 검증 손실 그래프가 감소 후, 다시 손실이 상승하는 구간임

 

[옵티마이저]

model = model_fn()
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', 
              metrics='accuracy')
              
history = model.fit(train_scaled, train_target, epochs = 20, verbose=0,
					validation_data(val_scaled, val_target))
                    
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()

옵티마이저 이후 손실 그래프

▶ 과대적합이 발생한 부분이 감소한 걸 확인할 수 있다. 

 


[Drop Out]

→ 드롭아웃을 샘플 처리 시 사용하면 어떠한 뉴런이 드롭 아웃되고 그 수를 정하는 건 하이퍼 파라미터에 해당된다.

model = model_fn(keras.layers.Dropout(0.3))

model.summary()

// result ---------

Model: "sequential_4"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 flatten_4 (Flatten)         (None, 784)               0         
                                                                 
 dense_8 (Dense)             (None, 100)               78500     
                                                                 
 dropout (Dropout)           (None, 100)               0         
                                                                 
 dense_9 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 79,510
Trainable params: 79,510
Non-trainable params: 0

// --------------

// 옵티마이저 적용
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', 
              metrics='accuracy')
// 검증 데이터 셋
history = model.fit(train_scaled, train_target, epochs=20, verbose=0, 
                    validation_data=(val_scaled, val_target))

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

 


[모델 저장과 복원]

model = model_fn(keras.layers.Dropout(0.3))
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', 
              metrics='accuracy')

history = model.fit(train_scaled, train_target, epochs=10, verbose=0, 
                    validation_data=(val_scaled, val_target))
                    
                    
# 가중치 저장 매개 변수의 포맷이 .h5 일 경우, HDF5 포맷으로 저장됨                    
# save_weights 함수는 훈련된 모델의 파라미터를 저장함
model.save_weights('model-weights.h5')

# 모델 구조 + 파라미터를 함께 저장 (저장 포맷은 동일)
model.save('model-whole.h5')

 


[Callback]

model = model_fn(keras.layers.Dropout(0.3))
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', 
              metrics='accuracy')

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

model.fit(train_scaled, train_target, epochs=20, verbose=0, 
          validation_data=(val_scaled, val_target),
          callbacks=[checkpoint_cb])
          
          
model = keras.models.load_model('best-model.h5')

// 
model.evaluate(val_scaled, val_target)          

// reulst-----------

loss: 0.3149 - accuracy: 0.8888
[0.31489625573158264, 0.8888333439826965]

// ------------------


model = model_fn(keras.layers.Dropout(0.3))
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', 
              metrics='accuracy')

checkpoint_cb = keras.callbacks.ModelCheckpoint('best-model.h5', 
                                                save_best_only=True)
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)
// result → 8 (0부터 시작하므로 9번째 epoch 과정에서 학습 중지됨)

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

# 위 구문에서 compile 함수를 먼저 호출 하여서
# evaluate 함수 호출 시, 정확도 + 손실 결과가 같이 출력됨
model.evaluate(val_scaled, val_target)

// result --------------

loss: 0.3310 - accuracy: 0.8803
[0.3309899568557739, 0.8803333044052124]

// -----------------------

▶ 결론 

-. 8번 epoch에서 학습이 중지 되었으며, 6번 epoch에서 가장 낮은 손실을 기록 하였다.