티스토리 뷰

지금까지 아이유/수지 대결을 성사시키기 위해 데이터/ 훈련 환경/ 모델까지 거의 모든 것을 준비했다.
이제 남은 건 가장 훌륭한 모델을 뽑아내는 것뿐. 거의 다 왔다. 끝이 보이기 시작한다?

오늘은 딥러닝을 하다 보면 한 번쯤은 볼 수 있는 오버 피팅(Overfitting)을 방지하고 조금이나마 억제하여 훌륭한 모델을 만들 수 있는 방법을 소개하고자 한다.


그럼 여기서 오버 피팅(Overfitting)이란 무엇인가?
간단히 말해 우리가 준비한 훈련 데이터에만 잘 작동하도록 만들어진 모델이다. 다시 말하자면 새로운 이미지를 제공하면 엉뚱하게 예측한다는 소리다.

이 현상을 막기 위해 정규화(L1, L2) / 학습률 조정 / 배치노멀라이즈 / 드롭아웃 / 앙상블 / 데이터 증량 .... 대략 이 정도 있다. 여기선 앙상블을 제외하고 살펴보자. (앙상블은 모델을 여러 개 만들어 하나의 데이터를 각각 모델에 넣어 N 개의 결과를 얻어 가장 많이 나온 결과를 선택)

 

첫 번째로 가장 쉽게 할 수 있는 건 당연하게도 '학습률 조정' 부분이다.
지금까지 이런 식으로 기본 학습률을 설정했는데 오버 피팅이 나온다면

 model.compile(optimizer=optimizers.Adam(), # -> Adam(lr=1e-5)로 변경 
                  loss='categorical_crossentropy', metrics=['accuracy'])

학습률이 너무 높아 제대로 학습이 되지 않거나 오버 피팅 될 확률이 상당히 높다. 그럴 땐 학습률을 보다 낮게 설정하여 보다 조금씩 학습하도록 설정해 주면 해결될 수도 있다.

두 번째로 가장 기본인 '드롭아웃.'
드롭아웃은 우리가 설정한 노드를 이용하여 예측할 때 노드 중 일부분을 랜덤으로 활성화하지 않는다는 것이다.
무슨 말이냐면... 밑에 코드에선 256개의 노드를 활성화하여 예측하고 결괏값을 낸다. 여기서 드롭아웃(0.3)을 한다면 30%의 노드를 랜덤으로 선택하여 이번 예측에 활용하지 않고 나머지 70%의 노드만 사용하여 예측값을 내기 때문에
너무 지엽적인 특징점에 의해 결괏값이 나오는 것을 방지, 즉 오버 피팅을 방지하게 된다.

  model = Sequential()
  model.add(Flatten(input_shape=train_data.shape[1:]))
  model.add(Dense(256, activation='relu'))
  model.add(Dropout(0.3))
  model.add(Dense(2, activation='softmax'))

위와 같이 모델에 그냥 Dropout을 넣어주고 얼마나 쉬게 할지 0~1까지 정해주면 된다. (0.5면 50%)

세 번째로 '데이터를 증량'시켜 주는 것이다.
이 방법이 가장 좋은 방법이기는 하나 아이유 수지 사진을 하나하나 중복 없이 구하는 건 상당히 고된 일이며 엄청난 시간이 든다. 하지만 좋은 소식이 하나 있으니... 우리가 사용하고 있는 Keras에서는 이미지 증량해 주는 기능이 이미 있다.

from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(
                                    rescale=1. / 255,
                                       rotation_range=40,
                                      width_shift_range=0.2,
                                      height_shift_range=0.2,
                                      shear_range=0.2,
                                      zoom_range=0.2,
                                      horizontal_flip=True,
                                      fill_mode='nearest')

어떠한 방식으로 증량 시켜주는가 하면...

Keras 이미지 증량

이런 식으로 이미지를 회전, 반전, 이동, 줌.... 등등등을 통해 하나의 이미지를 마치 다수의 이미지인 것처럼 만들어 주는 것이다. 너무나 훌륭한 기능이다.

 

마지막으로 '정규화 + 배치노멀라이즈'를 같이 보자. 

자세한 내용은 너무나 어렵기에 취미로 하는 필자는 그냥 이런 방식을 사용하면 오버 피팅을 줄일 수 있다는 사실만 알지 어떻게 작동하는지는 모른다. 원하시는 분들은 찾아보시길.... 단, 수학인데 영어인 것 같은 느낌은 본인이 감수하자..

코드로는 어떻게 작성하는가?를 보면 너무나 간단히 할 수 있도록 Keras에선 지원하고 있다.

  model = Sequential()
  model.add(Flatten(input_shape=train_data.shape[1:]))
  model.add(Dense(256, activation='relu',kernel_regularizer=keras.regularizers.l2(0.001)))
  model.add(Dropout(0.3))
  model.add(BatchNormalization())
  model.add(Dense(2, activation='softmax'))

위에 코드는 모델에 배치노멀라이즈 + L2 정규화 + 드롭아웃까지 적용한 것이다. 코드 몇 줄로 구현 가능하다는 것이 너무나 Keras에게 감사하다. (Keras에게 무한의 감사를!)

L2 정규화나 배치노멀라이즈는 일단 데이터 증량 + 학습률 변경 + 드롭아웃 까지 해본 상태에서도 오버 피팅이 좀처럼 나아지지 않는다면 해보길 추천한다.

 

그럼 이제 그래프를 비교해 볼까?

왼쪽. 오버피팅 방지x / 오른쪽. 오버피팅 방지o (배치노멀라이즈/드랍아웃/정규화)

왼쪽 그래프는 빨간색 선이 100epoch 이후에 상승(오버 피팅) 하는 걸 볼 수 있지만, 오른쪽은 상대적으로 loss가 줄어드는 것을 볼 수 있다. 어느 정도 오버 피팅이 되는 것을 방지했다고 볼 수 있다.
하지만 실험은 위에 적어놓은 Flatten() 모델만 학습한 것이다. 즉 VGG16의 모델은 오버 피팅을 위한 방지책이 없기에 위와 같이 오버 피팅이 될 수밖에 없는 것 같다. 이런 걸 염두에 두면 어느 정도 오버 피팅을 방지했다고 볼 수 있다.

오버 피팅은 반드시 방지해야 우리가 만든 모델의 성능이 우리가 원하는 것만큼 발휘할 수 있다. 간단한 코드 몇 개로 오버 피팅을 방지하길 바란다.

 

혹시 이렇게까지 했는데 오버 피팅이 발생한다면 어떻게 해야 할까? 아주 간단하지만 다음 시간에 알아보기로 하자.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함