티스토리 뷰
지금까지 아이유/수지 대결을 성사시키기 위해 데이터/ 훈련 환경/ 모델까지 거의 모든 것을 준비했다.
이제 남은 건 가장 훌륭한 모델을 뽑아내는 것뿐. 거의 다 왔다. 끝이 보이기 시작한다?
오늘은 딥러닝을 하다 보면 한 번쯤은 볼 수 있는 오버 피팅(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에선 지원하고 있다.
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 정규화나 배치노멀라이즈는 일단 데이터 증량 + 학습률 변경 + 드롭아웃 까지 해본 상태에서도 오버 피팅이 좀처럼 나아지지 않는다면 해보길 추천한다.
그럼 이제 그래프를 비교해 볼까?
왼쪽 그래프는 빨간색 선이 100epoch 이후에 상승(오버 피팅) 하는 걸 볼 수 있지만, 오른쪽은 상대적으로 loss가 줄어드는 것을 볼 수 있다. 어느 정도 오버 피팅이 되는 것을 방지했다고 볼 수 있다.
하지만 실험은 위에 적어놓은 Flatten() 모델만 학습한 것이다. 즉 VGG16의 모델은 오버 피팅을 위한 방지책이 없기에 위와 같이 오버 피팅이 될 수밖에 없는 것 같다. 이런 걸 염두에 두면 어느 정도 오버 피팅을 방지했다고 볼 수 있다.
오버 피팅은 반드시 방지해야 우리가 만든 모델의 성능이 우리가 원하는 것만큼 발휘할 수 있다. 간단한 코드 몇 개로 오버 피팅을 방지하길 바란다.
혹시 이렇게까지 했는데 오버 피팅이 발생한다면 어떻게 해야 할까? 아주 간단하지만 다음 시간에 알아보기로 하자.
'Deep-learning' 카테고리의 다른 글
오차 역전파 정리(개인적 생각) (0) | 2022.09.06 |
---|---|
[실험]딥러닝은 진짜 선을 그려서 XOR을 판별할까? - 시각화 (0) | 2022.02.17 |
[Deep-learning] 5. 흙수저의 마지막 희망 Google Colab. (0) | 2020.08.15 |
[Deep-learning] 4. VGG16과 Fine tuning의 결합 (0) | 2020.08.13 |
[Deep-learning] 3. 흙수저의 이미지 분류를 위한 도구 VGG16 (Transfer learning - 전이학습) (1) | 2020.08.12 |
- Total
- Today
- Yesterday
- 도커
- c3k2
- 알고리즘
- 오블완
- DeepLearning
- 딥러닝
- docker
- Tree
- github
- V11
- 백준
- 오류
- python
- 뜯어보기
- 어탠션
- 초보자
- GNN
- 자바
- 욜로
- java
- 디텍션
- GIT
- YOLO
- 정리
- CNN
- YOLOv8
- yolov11
- 이미지
- 티스토리챌린지
- 깃
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |