본문 바로가기
딥러닝

[딥러닝] Overfitting: EarlyStopping, Dropout 설정

by eyoo 2022. 6. 13.

에포크 횟수가 적정선을 넘어가면 더 이상 모델이 향상되지 않는다.

 

하지만 에포크 값은 사용자가 설정해줘야 하는 하이퍼 파라미터이므로 적정한 에포크 값을 찾기란 쉽지않다.

 

그래서 모델을 학습시킬때 callbacks 파라미터에 EarlyStopping을 적용하여

모델이 더 이상 성능이 향상되지 않을때 학습을 멈추게 할수있다.

 

먼저 callbacks.EarlyStopping으로 성능이 일정 수준에서 머무르면 자동으로 훈련을 멈추도록 설정한다.

 

early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss',patience=10)

# monitor 파라미터는 어떤 지표를 보고 멈출지 정한다. (벨리데이션 오차를 사용한다.)

# patience 파라미터는 성능이 일정 수준에서 멈춘 후, 성능향상이 있을때까지 몇개의 에포크를 기다릴지 정한다.

 

 

그 후 학습할때 callbacks파라미터로 위의 변수를 넣어줘서 EarlyStopping을 적용시킨다.

 

in:

epoch_history = model.fit(X_train, y_train, epochs = 1000000,validation_split= 0.2, callbacks = [early_stop])

out:

Epoch 141/1000000
8/8 [==============================] - 0s 6ms/step - loss: 8.2739 - mse: 8.2739 - mae: 2.1060 - val_loss: 6.8722 - val_mse: 6.8722 - val_mae: 1.9900
Epoch 142/1000000
8/8 [==============================] - 0s 5ms/step - loss: 8.1972 - mse: 8.1972 - mae: 2.0558 - val_loss: 6.9543 - val_mse: 6.9543 - val_mae: 2.0148

# 백만번의 에포클르 설정했지만 EarlyStopping으로 142번에서 멈췄다.

# 콜백은 코드 실행을 프레임워크에 맡기는것이다.

 

 

에포크 값을 지나치게 많이 넣으면 학습 데이터에 과도하게 적응하는 overfitting (오버피팅)현상이 발생할수있는데

 

이때, 로스와 정확도는 일정해지는 구간이 생기는데 train 로스와 train 정확도는 비정상적으로 낮아지거나 높아진다. 

 

그러면 학습 데이터는 정확하게 구분하지만 신규 데이터는 잘 구분하지 못하게 된다.

 

다른 데이터 셋을 모델링해서 학습 시켰다.

 

in:

epoch_history = model.fit(training_images,training_labels, epochs= 30, validation_split=0.2)

out:

...
Epoch 29/30
1500/1500 [==============================] - 5s 3ms/step - loss: 0.1423 - accuracy: 0.9470 - val_loss: 0.3771 - val_accuracy: 0.8928
Epoch 30/30
1500/1500 [==============================] - 5s 3ms/step - loss: 0.1383 - accuracy: 0.9489 - val_loss: 0.3677 - val_accuracy: 0.8947

# val_loss 보다 더 낮아지는 loss값을 볼수있다.

 

 

이를 시각화 해보자.

 

in:

plt.plot(epoch_history.history['loss'])
plt.plot(epoch_history.history['val_loss'])
plt.legend(['train loss','validation loss'])
plt.show()

plt.plot(epoch_history.history['accuracy'])
plt.plot(epoch_history.history['val_accuracy'])
plt.legend(['train accuracy','validation accuracy'])
plt.show()

out:

# 벨리데이션 값들보다 비정상적으로 성능이 향상되는것 처럼 보이게 나온다.

 

 

텐서플로우의 콜백 클래스를 상속해서 정해진 수치에 도달하면 학습을 멈추게하자.

 

class myCallback(tf.keras.callbacks.Callback):
  def on_epoch_end(self, epoch, logs={}):
    if logs.get('val_accuracy')>0.87:
      print('\n벨리데이션 정확도가 87%가 넘으므로 학습을 멈추게 합니다.')
      self.model.stop_training = True
my_callback = myCallback()

# 텐서플로우에서 제공하는 on_epoch_end 함수안에 에포크가 끝날때마다 하고싶은 작업을 입력해주면 된다.

 

 

 

다시 모델링하여 callbacks위의 콜백클래스로 정하고 학습시킨다.

 

in:

epoch_history = model.fit(training_images, training_labels, epochs = 30,validation_split= 0.2, callbacks = [my_callback])

out:

Epoch 1/30
1500/1500 [==============================] - 4s 3ms/step - loss: 0.5172 - accuracy: 0.8176 - val_loss: 0.4281 - val_accuracy: 0.8512
Epoch 2/30
1500/1500 [==============================] - 4s 3ms/step - loss: 0.3886 - accuracy: 0.8607 - val_loss: 0.3852 - val_accuracy: 0.8611
Epoch 3/30
1489/1500 [============================>.] - ETA: 0s - loss: 0.3468 - accuracy: 0.8739
벨리데이션 정확도가 87%가 넘으므로 학습을 멈추게 합니다.
1500/1500 [==============================] - 4s 3ms/step - loss: 0.3471 - accuracy: 0.8739 - val_loss: 0.3491 - val_accuracy: 0.8724

# 정확도 87%가 넘어가는 순간 멈추게 된다.

# callbacks에 EarlyStopping과 함께 사용할수 있다.

 

 

모델링할때 Dropout을 설정하여 오버피팅을 감소시킬수도 있다.

 

model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(128,'relu',input_shape=(784,)))

model.add(tf.keras.layers.Dropout(0.2))

model.add(tf.keras.layers.Dense(10,'softmax'))
model.compile('adam','sparse_categorical_crossentropy',metrics= ['accuracy'])

# 학습할때 20% 정도를 랜덤으로 끊어내라는 의미

# 과도한 학습 으로 인한 오버피팅을 줄일수 있다.

 

 

 

 

 

댓글