CNN_개_고양이_이진분류실습(모델링)
2024. 7. 9. 18:15ㆍDeep Learning
✅ 목표 설정
- 앞서 만든 NPZ 파일을 불러와서 사용해 보자
- CNN(합성곱 신경망)을 구현해 보자
- 신경망 성능 개선 및 전이 학습을 진행해 보자
# 드라이브 마운트
from google.colab import drive
drive.mount('/content/drive')
!pwd
%cd /content/drive/MyDrive/Colab Notebooks/Deep Learning
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# npz 파일 로딩
data = np.load('data/cats_dogs.npz')
data
# 데이터 분할
X_train = data['X_train']
X_test = data['X_test']
y_train = data['y_train']
y_test = data['y_test']
X_train.shape, X_test.shape, y_train.shape, y_test.shape
✅ CNN 모델링
- 모델 설계 및 구축
- 학습 및 평가 방법 설정
- 학습 및 시각화
- 모델 성능 평가
# 재료 import
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.optimizers import Adam
# 1. 모델 설계 및 구축
# 신경망 구현
# 뼈대 설정
model = Sequential()
# 특성 추출부 구현
model.add(Conv2D(filters=32,
kernel_size=(3,3),
padding = 'same', # padding 사용하겠다!
activation='relu',
input_shape=(224, 224, 3)))
model.add(MaxPooling2D(pool_size=(2,2)))
# ==========================================================
model.add(Conv2D(filters=64,
kernel_size=(3,3),
padding = 'same',
activation='relu'
))
model.add(MaxPooling2D(pool_size=(2,2)))
# ==========================================================
model.add(Conv2D(filters=128,
kernel_size=(3,3),
padding = 'same',
activation='relu'
))
model.add(MaxPooling2D(pool_size=(2,2)))
# ==========================================================
# 특성 추출부 구현 완료
# 전결합층 구현
model.add(Flatten())
model.add(Dense(units = 512, activation='relu'))
model.add(Dropout(0.35))
model.add(Dense(units = 256, activation='relu'))
model.add(Dropout(0.35))
model.add(Dense(units = 1, activation='sigmoid'))
# 전결합층 구현 완료
model.summary()
# 2. 학습 및 평가 방법 설정
model.compile(optimizer=Adam(learning_rate=0.001),
loss='binary_crossentropy',
metrics=['accuracy'])
# 학습 조기 중단 구현
f_early = EarlyStopping(monitor='val_loss',
patience=5)
# 3. 모델 학습
h = model.fit(X_train, y_train,
epochs=100,
batch_size=64,
validation_split=0.2,
callbacks=[f_early])
- 📌 학습 중간에 표시되는 정확도와 검증 정확도를 확인한 결과 과대적합 발생!
- 과대적합 제어 방법인 Dropout과 학습 조기 중단을 반영해도 과대적합 해소 X
- 데이터가 모자라서 학습이 부족할 수 있다. -> 데이터를 증강해 보자.
✅ 데이터 증식
- 부족한 데이터를 원본 데이터를 이용해서 증강 시켜주는 방법
- 일반적으로 딥러닝 모델은 데이터가 많을수록 성능이 좋아진다
# 이미지 증식 진행 해보기
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_gen = ImageDataGenerator(
rescale=1./255, # 데이터 스케일링, 현재는 연산을 통해 MinMax 스케일링 구현
rotation_range=15, # 0 ~ 360도 사이의 각도 지정 -> 회전각
width_shift_range=0.1, # 이미지를 좌우로 이동 10% 내외
height_shift_range=0.1, # 이미지를 상하로 이동 10% 내외
zoom_range=[0.8, 2.0], # 0.8배 또는 2배로 확대 및 축소
shear_range=0.5, # 0.5 라디안 (호도) 내외 시계 방향으로 변형(약 28.6도)
horizontal_flip=True, # 좌우 반전
vertical_flip=True, # 상하 반전
fill_mode='nearest' # 보간법 : 이미지 픽셀의 빈 공간을 채워주는 방법
)
test_gen = ImageDataGenerator(rescale=1./255)
# train / test 경로 잡아주기
train_dir = 'data/cats_and_dogs_filtered/train'
test_dir = 'data/cats_and_dogs_filtered/test'
# 이미지 증식 시작
# flow_from_directory() : 폴더의 경로 설정 및 옵션을 부여
train_generator = train_gen.flow_from_directory(
train_dir, # 폴더 경로 지정
target_size=(224, 224), # 변환할 이미지 사이즈
batch_size=64, # 한 번에 변환 시킬 이미지 갯수
class_mode='binary' # 라벨 번호 0번 부터 시작 / 폴더 알파벳 순서대로 읽어옴
)
test_generator = test_gen.flow_from_directory(
test_dir, # 폴더 경로 지정
target_size=(224, 224), # 변환할 이미지 사이즈
batch_size=10, # 한 번에 변환 시킬 이미지 갯수
class_mode='binary' # 라벨 번호 0번 부터 시작 / 폴더 알파벳 순서대로 읽어옴
)
# 라벨링 결과 확인
print(train_generator.class_indices)
print(test_generator.class_indices)
# 뼈대 설정
model2 = Sequential()
# 특성 추출부 구현
# conv2D_1 layer
# filter 갯수 32 / 패딩 사용 / 필터 사이즈 : (3,3) / 활성화 함수 relu / input_shape 지정
model2.add(Conv2D(filters = 32,
kernel_size = (3,3),
activation = 'relu',
input_shape = (224, 224, 3),
padding = 'same'))
# MaxPooling layer
# pool_size = (2,2)
model2.add(MaxPooling2D(pool_size = (2,2)))
# conv2D_2 layer
# filter 갯수 64 / 패딩 사용 / 필터 사이즈 : (3,3) / 활성화 함수 relu
model2.add(Conv2D(filters = 64,
kernel_size = (3,3),
activation = 'relu',
padding = 'same'))
# MaxPooling layer
# pool_size = (2,2)
model2.add(MaxPooling2D(pool_size = (2,2)))
# conv2D_3 layer
# filter 갯수 128 / 패딩 사용 / 필터 사이즈 : (3,3) / 활성화 함수 relu
model2.add(Conv2D(filters = 128,
kernel_size = (3,3),
activation = 'relu',
padding = 'same'))
# MaxPooling layer
# pool_size = (2,2)
model2.add(MaxPooling2D(pool_size = (2,2)))
# 전결합층 구현
# 데이터를 1차원으로 펴주는 층
model2.add(Flatten())
# 뉴런의 갯수 64 / 활성화 함수 : 렐루
model2.add(Dense(units = 64, activation = 'relu'))
# 드롭아웃 추가(비워두기)
model2.add(Dropout(0.35))
# 출력층 설정 (이진분류에 맞는 출력층 설정)
model2.add(Dense(units = 1, activation = 'sigmoid'))
model2.summary()
model2.compile(optimizer=Adam(learning_rate=0.001),
loss='binary_crossentropy',
metrics=['accuracy'])
# 학습 조기 중단 구현
# 이미지 증식을 진행 했을 때는 학습이 들쭉날쭉하게 진행이 된다.
# 학습 횟수와 기회를 늘려서 학습을 오래 시켜줄 필요가 있다.
f_early = EarlyStopping(monitor='val_accuracy',
patience=20)
epochs = 100
h2 = model2.fit_generator(generator = train_generator,
epochs=epochs,
validation_data=test_generator,
callbacks=[f_early])
✅ 전이학습
- 기존에 학습이 잘 된 모델을 이용하는 방법
- 전이학습에는 특성 추출 방식과 미세 조정 방식이 있음
# vgg16모델 import
from tensorflow.keras.applications import VGG16
vgg16 = VGG16(
include_top=False, # 불러온 모델의 MLP 분류기를 쓸건가?
weights='imagenet', # imgenet에서 사용했던 1000개 클래스에 대응하는 가중치를 사용하겠다(사전 학습 가중치 사용)
input_shape=(224, 224, 3) # 이미지 사이즈
)
vgg16.summary()
# 특성 추출부에 MLP를 결합해주자
# 우리가 실습할 부분은 미세 조정 방식
# 동결 시킬 층을 확인하기 위해 불러온 VGG16 모델의 층 이름을 확인해보자
for layer in vgg16.layers:
print(layer.name)
# 신경망 설계
# 뼈대 설정
transfer_model = Sequential()
# 미세 조정 방식 적용
# 분류기와 맞닿은 block5_conv3 층만 학습이 가능하도록 설정
for layer in vgg16.layers :
if layer.name == "lock5_conv3" :
layer.trainable = True
else :
layer.trainable = False
# 모델 구현
transfer_model.add(vgg16)
transfer_model.add(Flatten())
transfer_model.add(Dense(units = 128, activation = 'relu'))
# 출력층
transfer_model.add(Dense(units = 1, activation = 'sigmoid'))
# 모델 컴파일
transfer_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
# 모델 학습
transfer_model.fit(X_train, y_train,
epochs=10,
validation_split=0.3)
transfer_model.evaluate(X_test, y_test)
✅ 주의점
- 한번 학습 가능하도록 설정된 층은 가중치가 변경
- 만약 동결층을 바꿔서 다시 학습시키고 싶다면 처음부터 모델을 새롭게 import 해와야 한다.
'Deep Learning' 카테고리의 다른 글
OpenCV_021_얼굴검출_스켈레톤(MediaPipe) (0) | 2024.07.11 |
---|---|
Yolo7 기반 객체 탐지 및 인식 (0) | 2024.07.10 |
CNN 개_고양이_이진분류 실습(데이터 만들기) (0) | 2024.07.08 |
CNN(Convolutional Neural Network) (0) | 2024.07.05 |
모델저장 학습중단 과적합 (0) | 2024.07.01 |