본문 바로가기
인공지능

컴퓨터비전 전이학습 Computer Vision Transfer Learning - Feature Extraction

by 피키타임즈 2023. 10. 4.

컴퓨터비전 전이학습 Computer Vision Transfer Learning - Feature Extraction

midjourney로 생성한 computer vision 이미지

전이학습 (Transfer Learning)

  • MNIST 예측 시 사용한 CNN 은 convolution layer 3개 + FC(Fully Connected Layer) Layer (DNN) classifier
  • 성능이 떨어진다.
  • 실무에서는 Pre-trained Network (기학습네트워크)를 이용하여 학습 및 예측한다.

전이학습을 Pre-Trained Network(사전 학습된 모델)을 사용한다.

  • 학습의 시간을 대폭적으로 줄이고 
  • 모델의 정확도를 높인다.

컴퓨터비전에서 Pre Trained Network 종류

1. Google Inception (Convolution Layer 30개)

2. MS의 Resnet  (Convolution Layer 150개)

3. mobilenet : 성능은 떨어지지만 빠른 속도로 학습 및 예측이 가능

4. efficientnet : B0 ~ B6 (각각의 모델에 따라 크기와 성능이 차이가 있다)

5. VGG16(16개 layer), VGG19(19개 layer) : 연습용 모델

VGG16 Pre-trained Network

  • CNN은 이미지 특징추출(필터), 학습으로 나뉘어 있다.
  • VGG16은 imagenet Dataset은 1000개의 카테고리로 학습이 되어 있다.
  • 전이학습 시 VGG16의 특성 추출 Convolution Layer만 떼어다 사용한다.
  • 기존에 학습된 특성추출 필터 부분만 가져다 사용

 

VGG16 (Pre-trained Network)

  • 이 모델이 가지는 Filter들 (특성 추출)은 Imagenet Data Set을 가지고 만든 Filter이다. (weights)

Pre-trained Network 사용하는 방법

1. Feature Extraction (특성추출) 부분만 가져다 사용하는 방법

2. Fine Tuning 방법

모델 생성시 cat vs dog 이미지 사용하기 위해 input_shape을 (150, 150, 3)으로 설정하였다.

 

VGG16 특징

기존 vgg16 모델을 관찰해보면, input에서 멀어질수록, image사이즈가 작아지고, filter 수는 증가하는 것을 알 수 있습니다.

# Pretrained Network 이용
# VGG16 모델 이용

from tensorflow.keras.applications import VGG16

# weights='imagenet'
# 이미지넷 데이터셋으로 학습된 모델을 불러올 수 있다.
# include_top=False
# 모델의 FC Layer(Classifier)부분을 포함할지 결정
# input_shape=(150,150,3)
# 네트워크에 주입할 이미지의 shape

model_base = VGG16(weights='imagenet',
                   include_top=False, # top 쪽이 classifier 부분이다
                   input_shape=(150,150,3))

model_base.summary()

# 원래 VGG16 모델의 예측값은 당연히 각 class에 대한 확률값
# include_top=False로 classifier를 없앴기 떄문에
# 해당 모델의 예측값은 이미지의 특성을 추출한 데이터가 될 것이다.

import os
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator

train_dir = '/content/cat_dog_small/train'
validation_dir = '/content/cat_dog_small/validation'

datagen = ImageDataGenerator(rescale=1/255)
batch_size = 20

def extract_feature(directory, sample_count):
  features = np.zeros(shape=(sample_count,4,4,512)) # convolution 통과하면 4,4,512로 변한다. model.summary() -> block5_pool (MaxPooling2D)  (None, 4, 4, 512) 
  labels = np.zeros(shape=(sample_count,))

  generator = datagen.flow_from_directory(
      directory,
      target_size=(150, 150),
      batch_size=batch_size,
      class_mode='binary'
  )

  i = 0

  for x_data_batch, t_data_batch in generator:
      feature_batch = model_base.predict(x_data_batch)
      features[i*batch_size:(i+1)*batch_size] = feature_batch
      labels[i*batch_size:(i+1)*batch_size] = t_data_batch
      
      i += 1
      if i * batch_size >= sample_count:
          break;
  
  return features, labels


train_features, train_labels = extract_feature(train_dir,2000)
validation_features, validation_labels = extract_feature(validation_dir,1000)
# 이미지의 특성 추출된 데이터가 준비
# 학습 시키자
# DNN으로 처리

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense, Dropout
from tensorflow.keras.optimizers import Adam

model = Sequential()
model.add(Flatten(input_shape=(4*4*512,)))
model.add(Dense(units=256,
                activation='relu'))
model.add(Dropout(rate=0.5))
model.add(Dense(units=1,
                activation='sigmoid'))

model.compile(optimizer=Adam(learning_rate=1e-4),
              loss='binary_crossentropy',
              metrics=['accuracy'])

x_data = np.reshape(train_features, (2000, 4*4*512))
t_data = train_labels

valid_x_data = np.reshape(validation_features, (1000, 4*4*512))
valid_t_data = validation_labels

history = model.fit(
    x_data,
    t_data,
    epochs=30,
    batch_size=20,
    validation_data=(valid_x_data, valid_t_data)
)
import matplotlib.pyplot as plt

train_acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
train_loss = history.history['loss']
val_loss = history.history['val_loss']

plt.plot(train_acc, 'o', color='r', label='training accuracy')
plt.plot(val_acc, color='b', label='validation accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
plt.show()

plt.plot(train_loss, 'o', color='r', label='training loss')
plt.plot(val_loss, color='b', label='validation loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()

VGG16 사용시 데이터 증식 이용하기

VGG16의 Convolution Layer의 weight를 고정으로 훈련하지 않고, classifier 쪽만 변경하여 훈련시키기

# 증식까지 포함한 pretrained network를 이용한 개, 고양이 분류 구현

import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.applications import VGG16
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Flatten
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt

train_dir = '/content/cat_dog_small/train'
validation_dir = '/content/cat_dog_small/validation'

train_datagen = ImageDataGenerator(rescale=1/255,
                                   rotation_range=30,
                                   width_shift_range=0.1,
                                   height_shift_range=0.1,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   horizontal_flip=True)

validation_datagen = ImageDataGenerator(rescale=1/255)

train_generator = train_datagen.flow_from_directory(
    train_dir,
    classes=['cats', 'dogs'],
    target_size=(150,150),
    batch_size=20,
    class_mode='binary'
)

validation_generator = validation_datagen.flow_from_directory(
    validation_dir,
    classes=['cats', 'dogs'],
    target_size=(150,150),
    batch_size=20,
    class_mode='binary'
)


# Pretrained Network Loading
model_base = VGG16(weights='imagenet',
                   include_top=False,
                   input_shape=(150,150,3))

model_base.trainable = False # Convolution Layer 동결

model = Sequential()

model.add(model_base) # VGG16 Convolution Layer를 추가

model.add(Flatten(input_shape=(4 * 4 * 512,)))

model.add(Dense(units=256, activation='relu'))

model.add(Dropout(rate=0.5))

model.add(Dense(units=1,
                activation='sigmoid'))

model.summary()

model.compile(optimizer=Adam(learning_rate=1e-4),
              loss='binary_crossentropy',
              metrics=['accuracy'])

history = model.fit(
    train_generator,
    steps_per_epoch=100, #generator batch 20이라, 20 * 100 = 2000 (데이터 개수)
    epochs=30,
    validation_data=validation_generator,
    validation_steps=50,
    verbose=1
)

 

반응형

댓글