앞글에서는 전이 학습을 넣지 않은 학습이었지만 이 글에서는 전이 학습으로 모델 성능을 극대화해보도록 하겠습니다.
앞 글에서 전이 학습은 '기존의 학습 결과를 가져와서 유사한 프로젝트에 사용하는 방법'이라고 했습니다.
전이학습을 위해서 이미지넷(ImageNet) 데이터셋에서 정보를 추출해오겠습니다.
이미지넷(ImageNet) 데이터셋
1000가지 종류로 나뉜 120만 개가 넘는 이미지를 놓고 어떤 물체인지 맞히는 '이미지넷 이미지 인식 대회(ILSVRC)'에 사용되는 데이터셋으로 MNIST와 같이 가장 유명한 데이터셋
뇌 사진만 필요한데 관련없는 이미지넷의 데이터를 가져오는 이유는 '형태'를 구분하는 기본적인 학습이 되어 있기 때문입니다.
딥러닝은 학습이 시작되면 어떤 픽셀의 조합이 '선'이고 '면'인지 파악해야합니다. 아무런 정보 없이 바로 학습을 한다면 시간이 오래 걸리겠죠. 전이 학습이 이부분을 해결해 주는 것입니다. 방대한 데이터로 학습한 가중치 정보를 가져와 그대로 모델에 적용한 뒤 프로젝트를 진행하면 됩니다. 오 꽤 효율적인 방법입니다.
그림으로 표현해 보겠습니다.
실습에서 가져올 데이터는 '이미지넷', 사전에 학습된 모델은 'VGGNet'의 VGG16입니다.
VGGNet
옥스포드 대학의 연구 팀 VGG에 의해 개발된 모델
2014년 이미지넷 이미지 인식 대회에서 2위를 한 모델
VGG16을 불러오겠습니다.
#VGG16 모델 불러오기
transfer_model = VGG16(weights='imagenet', include_top=False, input_shape=(150, 150, 3))
transfer_model.trainable = False
transfer_model.summary()
include_top: 마지막 층, 분류하는 층 불러오기를 정하는 옵션
만들고 있는 프로젝트에 연결하기 때문에 False로 둡니다.
새로 학습하지 않도록 transfer_model.trainable을 False로 해줍니다.
로컬 네트워크를 만들어 줍니다.
finetune_model = models.Sequential()
finetune_model.add(transfer_model)
finetune_model.add(Flatten())
finetune_model.add(Dense(64))
finetune_model.add(Activation('relu'))
finetune_model.add(Dropout(0.5))
finetune_model.add(Dense(1))
finetune_model.add(Activation('sigmoid'))
finetune_model.summary()
전체 코드는 다음과 같고 실행을 하면
from tensorflow.keras.layers import Dense, Activation, Dropout, Flatten
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications import VGG16
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras import Input, models, layers, optimizers, metrics
import numpy as np
import matplotlib.pyplot as plt
#데이터 불러오기
!git clone https://github.com/taehojo/data-ch20.git
# 학습셋의 변형
train_datagen = ImageDataGenerator(rescale=1./255, #이미지의 크기
horizontal_flip=True, # 수평 대칭 이미지 50%
width_shift_range=0.1, # 전체 크기의 15%에서 좌우 이동.
height_shift_range=0.1, # 위, 아래로 이동
)
train_generator = train_datagen.flow_from_directory(
'./data-ch20/train',
target_size=(150, 150),
batch_size=5,
class_mode='binary')
# 테스트셋 이미지 부풀리기 과정을 진행 안함.
test_datagen = ImageDataGenerator(rescale=1./255)
test_generator = test_datagen.flow_from_directory(
'./data-ch20/test',
target_size=(150, 150),
batch_size=5,
class_mode='binary')
#VGG16 모델 불러오기
transfer_model = VGG16(weights='imagenet', include_top=False, input_shape=(150, 150, 3))
transfer_model.trainable = False
transfer_model.summary()
#VGG16 모델 설정
finetune_model = models.Sequential()
finetune_model.add(transfer_model)
finetune_model.add(Flatten())
finetune_model.add(Dense(64))
finetune_model.add(Activation('relu'))
finetune_model.add(Dropout(0.5))
finetune_model.add(Dense(1))
finetune_model.add(Activation('sigmoid'))
finetune_model.summary()
#모델의 실행 옵션
finetune_model.compile(loss='binary_crossentropy', optimizer=optimizers.Adam(learning_rate=0.0002), metrics=['accuracy'])
#학습의 조기중단
early_stopping_callback = EarlyStopping(monitor='val_loss', patience=5)
#모델 실행
history = finetune_model.fit(
train_generator,
epochs=20,
validation_data=test_generator,
validation_steps=10,
callbacks=[early_stopping_callback])
#검증셋과 학습셋 오차 저장
y_vloss=history.history['val_loss']
y_loss=history.history['loss']
#그래프 표현
x_len = np.arange(len(y_loss))
plt.plot(x_len, y_vloss, marker='.', c='red', label='Testset_loss')
plt.plot(x_len, y_loss, marker='.', c='blue', label='Trainset_loss')
plt.legend(loc='upper right')
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()
이렇게 나옵니다.
전이학습을 하지 않았을 때보다 기울기가 안정적으로 바뀌었습니다. 학습속도도 빨려졌구요
전이학습으로 딥러닝 모델의 성능을 올려보았습니다.
이제 마지막 1개만 남았네요
참고: [모두의 딥러닝]
'프로그래밍 > 인공지능' 카테고리의 다른 글
오차역전파 계산법 -2 (0) | 2023.08.11 |
---|---|
오차 역전파의 계산법 -1 (0) | 2023.08.11 |
전이 학습(transfer learning) - 1 (0) | 2023.08.05 |
오토인코더(Auto-Encoder) (0) | 2023.08.04 |
생성적 적대 신경망(Generative Adversarial Networks) (0) | 2023.08.03 |