0421 Fine Tuning_VGG16

wldnjswldnjs·2022년 5월 16일
0

딥러닝

목록 보기
9/10
post-custom-banner

1. Transfer Learning

keras는 전이학습을 위해 VGG16 제공

### keras는 전이학습을 위해서 VGG16을 제공해줘요!
from tensorflow.keras.applications import VGG16

model_base = VGG16(weights='imagenet',
                   include_top=False,
                   input_shape=(150,150,3))

## 우리가 가지고 있는 데이터(개와 고양이)를 VGG16에 통과시켜서
## 이미지의 특성을 ndarray형태로 저장해야 해요!

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

base_dir = './data/cat_dog_small'
train_dir = os.path.join(base_dir, 'train')  # ./data/cat_dog_small/train
valid_dir = os.path.join(base_dir, 'validation')
test_dir = os.path.join(base_dir, 'test')

datagen = ImageDataGenerator(rescale=1/255)

def extraction_feature(directory, sample_count):
    features = np.zeros(shape=(sample_count,4,4,512))
    labels = np.zeros(shape=(sample_count,))
    
    generator = datagen.flow_from_directory(
        directory,
        classes=['cats', 'dogs'],
        target_size=(150,150),
        batch_size=20,
        class_mode='binary'
    )
    
    i = 0
    
    for x_data_batch, t_data_batch in generator:
        feature_batch = model_base.predict(x_data_batch)  # 20개 이미지 특성추출.
        features[i*20:(i+1)*20] = feature_batch
        labels[i*20:(i+1)*20] = t_data_batch
        
        i = i + 1
        
        if i*20 >= sample_count:
            break
            
    return features, labels
    

train_features, train_labels = extraction_feature(train_dir, 2000)
valid_features, valid_labels = extraction_feature(valid_dir, 1000)
test_features, test_labels = extraction_feature(test_dir, 1000)

## 이 ndarray를 이용해서 DNN 학습을 하면 될 거 같아요!

train_x_data = np.reshape(train_features,(2000,4*4*512))  # 2차원
train_t_data = train_labels

valid_x_data = np.reshape(valid_features,(1000,4*4*512))  # 2차원
valid_t_data = valid_labels

test_x_data = np.reshape(test_features,(1000,4*4*512))  # 2차원
test_t_data = test_labels

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'])

history = model.fit(train_x_data,
                    train_t_data,
                    epochs=30,
                    batch_size=20,
                    validation_data=(valid_x_data, valid_t_data))

### history 객체를 이용해서 결과 그래프를 그려보아요!! ###

import matplotlib.pyplot as plt

train_acc = history.history['accuracy']
valid_acc = history.history['val_accuracy']

train_loss = history.history['loss']
valid_loss = history.history['val_loss']

figure = plt.figure()
ax1 = figure.add_subplot(1,2,1)
ax2 = figure.add_subplot(1,2,2)

ax1.plot(train_acc, color='r', label='train accuracy')
ax1.plot(valid_acc, color='b', label='valid accuracy')
ax1.legend()

ax2.plot(train_loss, color='r', label='train loss')
ax2.plot(valid_loss, color='b', label='valid loss')
ax2.legend()

plt.tight_layout()
plt.show()

학습이 제대로 이루어졌다고 보기 어렵다.

학습에 사용되는 이미지가 2000개밖에 안 되므로 증식해야 함

2. 이미지 증식을 이용한 전이학습

import os
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 Flatten, Dense, Dropout
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt

train_dir = './data/cat_dog_small/train'
valid_dir = './data/cat_dog_small/validation'

train_datagen = ImageDataGenerator(rescale=1/255,
                                   rotation_range=30,
                                   width_shift_range=0.1,
                                   height_shift_range=0.1,
                                   zoom_range=0.2,
                                   horizontal_flip=True,
                                   vertical_flip=True,
                                   fill_mode='nearest')

valid_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') # categorical(다중분류인 경우)

valid_generator = valid_datagen.flow_from_directory(valid_dir,
                                                    classes=['cats', 'dogs'],
                                                    target_size=(150,150),
                                                    batch_size=20,
                                                    class_mode='binary') # categorical(다중분류인 경우)

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

model_base.trainable = False  # Convolution layer안의 parameter 동결!

# model 구현

model = Sequential()

model.add(model_base)

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'])

history = model.fit(train_generator,
                    steps_per_epoch=100,
                    epochs=30,
                    validation_data=valid_generator,
                    validation_steps=50,
                    verbose=2)

model.save('./data/cat_dog_small/transfer_learning_cnn_cat_dog_small.h5')

### history 객체를 이용해서 결과 그래프를 그려보아요!! ###

import matplotlib.pyplot as plt

train_acc = history.history['accuracy']
valid_acc = history.history['val_accuracy']

train_loss = history.history['loss']
valid_loss = history.history['val_loss']

figure = plt.figure()
ax1 = figure.add_subplot(1,2,1)
ax2 = figure.add_subplot(1,2,2)

ax1.plot(train_acc, color='r', label='train accuracy')
ax1.plot(valid_acc, color='b', label='valid accuracy')
ax1.legend()

ax2.plot(train_loss, color='r', label='train loss')
ax2.plot(valid_loss, color='b', label='valid loss')
ax2.legend()

plt.tight_layout()
plt.show()

3. 이미지 증식을 이용한 전이학습 (fine tuning)

import os
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 Flatten, Dense, Dropout
from tensorflow.keras.optimizers import Adam
import matplotlib.pyplot as plt

train_dir = '/content/drive/MyDrive/colab/cat_dog_small/train'
valid_dir = '/content/drive/MyDrive/colab/cat_dog_small/validation'

train_datagen = ImageDataGenerator(rescale=1/255,
                                   rotation_range=30,
                                   width_shift_range=0.1,
                                   height_shift_range=0.1,
                                   zoom_range=0.2,
                                   horizontal_flip=True,
                                   vertical_flip=True,
                                   fill_mode='nearest')

valid_datagen = ImageDataGenerator(rescale=1/255)

# Pretrained network마다 정해진 size가 있다.
train_generator = \
train_datagen.flow_from_directory(train_dir,
                                  classes=['cats', 'dogs'],
                                  target_size=(150,150),
                                  batch_size=20,
                                  class_mode='binary')

valid_generator = \
valid_datagen.flow_from_directory(valid_dir,
                                  classes=['cats', 'dogs'],
                                  target_size=(150,150),
                                  batch_size=20,
                                  class_mode='binary')

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

model_base.trainable = False # Convolution Layer안의 parameter 동결
# print(model_base.summary())

# model 구현
model = Sequential()

model.add(model_base)

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'))

# print(model.summary())

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

history = model.fit(train_generator,
                    steps_per_epoch=100,
                    epochs=30,
                    validation_data=valid_generator,
                    validation_steps=50, # 1000개를 20개씩
                    verbose=1)

# 여기까지 수행하면 classifier가 학습된다.

model_base.trainable =  True    # Convolution Layer안의 parameter 동결 해제

for layer in model_base.layers:
    if layer.name in ['block5_conv1', 'block5_conv2', 'block5_conv3']:
        layer.trainable = True  # 동결 해제
    else:
        layer.trainable = False # 동결

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

# 재학습 진행
history = model.fit(train_generator,
                    steps_per_epoch=100,
                    epochs=30,
                    validation_data=valid_generator,
                    validation_steps=50, # 1000개를 20개씩
                    verbose=1) # epoch 돌 때 화살표가 나오지 않음

import matplotlib.pyplot as plt

train_acc = history.history['accuracy']
valid_acc = history.history['val_accuracy']

train_loss = history.history['loss']
valid_loss = history.history['val_loss']

figure = plt.figure()
ax1 = figure.add_subplot(1,2,1)
ax2 = figure.add_subplot(1,2,2)

ax1.plot(train_acc, color='r', label='train accuracy')
ax1.plot(valid_acc, color='b', label='valid accuracy')
ax1.legend()
ㄴ
ax2.plot(train_loss, color='r', label='train loss')
ax2.plot(valid_loss, color='b', label='valid loss')
ax2.legend()

plt.tight_layout()
plt.show()

# loss: 0.0701 - accuracy: 0.9750 - val_loss: 0.2822 - val_accuracy: 0.9080

기본적으로 가지고 있는 데이터 사이즈가 작기 때문에overfitting 발생

post-custom-banner

0개의 댓글