파이썬 딥러닝 - 05. EarlyStopping

2020. 1. 12. 17:58Tech :Deep Learning

OverFitting 되는 모델의 경우, epoch이 커질 수록 Loss가 줄다가 다시 늘게 되는 아래와 같은 경우가 생긴다. 150번정도에 EarlyStopping이 되면 overfitting이 되지 않을 수 있는데 더 이상 개선의 여지가 없을 때 학습을 종료시키는 콜백함수이다. 

콜백함수란? 어떤 함수를 수행 시 그 함수에서 내가 지정한 함수를 호출하는 것. 여기서는 fit() 함수에서 EarlyStopping() 콜백함수가 학습 과정 중 매번 호출된다. 

from tensorflow.python.keras.callbacks import EarlyStopping
early_stopping = EarlyStopping()
hist = model.fit(x_train,y_train,epochs=1000,batch_size=10,validation_data=(x_val,y_val),callbacks=[early_stopping])

위와 같이 epoch을 1000으로 지정했더라도 학습과정 중 EarlyStopping 콜백함수를 호출하여 해당 조건이 되면 학습을 조기종료 시키는데 EarlyStopping 콜백함수에서 설정할 수 있는 인자는 다음과 같다.

tensorflow.keras.callbacks.EarlyStopping(monitor='val_loss',min_delta=0,patience=0,verbose=0,mode='auto')

- monitor : 관찰하고자 하는 항목으로 'val_loss'나 'val_acc'를 주로 사용

- min_delta : 개선되고 있다고 판단하기 위한 최소 변화량. 변화량이 min_delta보다 적은 경우 개선이 없다고 판단.

- patience : 개선이 없다고 바로 종료하지 않고 개선이 없는 epoch를 얼마나 기다려 줄 것인가를 지정. 만약 10이라고 하면 개선이 없는 epoch를 10번째 지속될 경우 학습을 종료

- verbose : 얼마나 자세하게 정보를 표현할 것인가를 지정 (0,1,2)

- mode : 관찰 항목에 대해 개선이 없다고 판단하기 위한 기준을 지정. 예를 들어, 관찰 항목이 'val_loss'인 경우 감소되는 것이 멈출 때 종료되어야 하므로 'min'으로 설정된다. auto는 관찰하는 이름에 따라 자동으로 지정, min은 관찰하고 있는 항목이 감소되는 것을 멈출 때 종료, max는 관찰하고 있는 항목이 증가되는 것을 멈출 때 종료.

MNIST 데이터에 대해 학습 중 earlystopping을 적용한 예제 코드 )

# 0. 사용할 패키지 불러오기
from tensorflow.python.keras.utils import np_utils
from tensorflow.python.keras.datasets import mnist
from tensorflow.python.keras.models import Sequential
from tensorflow.python.keras.layers import Dense,Activation
import numpy as np

np.random.seed(3)

# 1. 데이터셋 준비하기

# Training set과 Test set 불러오기
(x_train,y_train),(x_test,y_test) = mnist.load_data()
print("x_train : ",x_train.shape)
print("y_train : ",y_train.shape)
print("x_test : ",x_test.shape)
print("y_test : ",y_test.shape)

# Training set과 Validation set 분리
x_val = x_train[50000:]
y_val = y_train[50000:]
x_train = x_train[:50000]
y_train = y_train[:50000]

# Dataset Preprocessing
x_train = x_train.reshape(50000,784).astype('float32') / 255.0
x_val = x_val.reshape(10000,784).astype('float32') / 255.0
x_test = x_test.reshape(10000,784).astype('float32') / 255.0

# Training set과 Validation set 고르기
train_rand_idxs = np.random.choice(50000,700)
val_rand_idxs = np.random.choice(10000,300)
x_train = x_train[train_rand_idxs]
y_train = y_train[train_rand_idxs]
x_val = x_val[val_rand_idxs]
y_val = y_val[val_rand_idxs]

# Label data one-hot encoding
y_train = np_utils.to_categorical(y_train)
y_val = np_utils.to_categorical(y_val)
y_test = np_utils.to_categorical(y_test)

# 2. 모델 구성하기
model = Sequential()
model.add(Dense(units=2,input_dim=28*28,activation='relu'))
model.add(Dense(units=10,activation='softmax'))

# 3. 모델 학습과정 설정하기
model.compile(loss='categorical_crossentropy',optimizer = 'sgd',metrics=['accuracy'])

# 4. 모델 학습시키기
from tensorflow.python.keras.callbacks import EarlyStopping
early_stopping = EarlyStopping()
hist = model.fit(x_train,y_train,epochs=1000, batch_size=10, validation_data=(x_val,y_val),callbacks=[early_stopping])

# 5. 학습 과정 살펴보기
%matplotlib inline
import matplotlib.pyplot as plt

fig, loss_ax = plt.subplots()

acc_ax = loss_ax.twinx()

loss_ax.plot(hist.history['loss'],'y',label='train loss')
loss_ax.plot(hist.history['val_loss'],'r',label='val loss')
acc_ax.plot(hist.history['acc'],'b',label='train acc')
acc_ax.plot(hist.history['val_acc'],'g',label='val acc')

loss_ax.set_xlabel('epoch')
loss_ax.set_ylabel('loss')
acc_ax.set_ylabel('accuracy')

loss_ax.legend(loc='upper left')
acc_ax.legend(loc='lower left')
plt.show()

# 6. 모델 평가하기
loss_and_metrics = model.evaluate(x_test,y_test,batch_size=32)

print('##### Test Result #####')
print('loss : ',str(loss_and_metrics[0]))
print('Accuracy : ',str(loss_and_metrics[1]))

val_loss 값이 감소되다가 증가하자마자 학습이 종료되어서 실상은 더 학습될 수 있는데 accuracy가 42%밖에 안된 시점에 early stopping된 것을 볼 수 있다. 이럴 경우 patience 인자를 증가해서 성급한 조기종료가 되지 않도록 해야한다.

EarlyStopping()
EarlyStopping(patience = 20)