Machine Learning/Tensorflow

Tensorflow Keras - 7일차 (Resnet50V2) 및 실제 이미지로 학습하기

Joon09 2021. 4. 2. 18:39
반응형

전이학습(Transfer learning)을 이용한 학습 방법입니다.

 

라이브러리

import tensorflow as tf
import matplotlib.pyplot as plt
from tensorflow.keras.layers import *
from tensorflow.keras.models import Model,Sequential
import zipfile

import gdown

google drive에서 데이터 다운로드

google_path = 'https://drive.google.com/uc?id='
file_id = '1Of_X6StezV0vwE0WrQ7MNbIFjITkW4dJ'
output_name = 'animals_images.zip'
gdown.download(gdrive_url+file_id,output_name)

zip 압축 해제

input_path = './animals_images.zip'
output_path = './data'
zip_animal = zipfile.ZipFile(input_path)
zip_animal.extractall(output_path)
train_path = './data/animals'

Hyper parameter 수정

# 예측할 클래스 수
classes = 3

# Input으로 사용될 크기와 채널수
height = 256
width = 256
channels = 3

이미지 처리 진행

image_generator = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1/255, validation_split=0.33)
image_data_train = image_generator.flow_from_directory(train_path,subset='training')
image_data_test = image_generator.flow_from_directory(train_path,subset='validation')

케라스에서 제공하는 ImageDataGenerator를 이용하면 처음 설정때는 이미지를 스케일하는 방법과

이미지 증폭, 이미지 회전등을 제공합니다. 인스턴스를 받고나면 flow_form_directory 메서드를 이용해서 path만 넣으면 자동으로 전처리가 되는거죠!

 

모델로드

resnetv2 = tf.keras.applications.ResNet50V2(include_top=False,input_shape=(height,width,channels))

여기서 include_top은 마지막 레이어인 1000개의 클래스를 예측하는 Dense Layer를 안쓰겠다는 뜻입니다.

이러면 이미지의 크기와 상관없이 이미 만들어진 레이어가 resnetv2라는 변수에 담기게 되는거죠!

include_top을 True로 설정하면 크기는 224,224,3으로 제한됩니다.

 

하지만 우리는 레이어와 이미 학습된 가중치만을 사용합니다.

 

resnetv2.trainable=False

기존 레이어의 가중치의 학습을 안하겠다고 하는겁니다.

model = Sequential([
                 resnetv2,
                 Dense(512,activation='relu'),
                 BatchNormalization(),
                 GlobalAveragePooling2D(),
                 Dense(classes,activation='softmax')
])

우리만의 레이어를 다시 한번 쌓아줍니다.

 

이미 깊게 쌓여진 Resnet이기 때문에 다른 레이어는 거의 할필요 없고,

GlobalAveragePooling2D와 마지막 레이어인 Dense 레이어만 사용을 권합니다.

GlobalAveragePooling2D는 Flatten과 비슷한 역할을 하지만 성능은 전자가 낫다고 합니다..^^

model.summary()

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
resnet50v2 (Functional)      (None, 8, 8, 2048)        23564800  
_________________________________________________________________
dense_30 (Dense)             (None, 8, 8, 512)         1049088   
_________________________________________________________________
batch_normalization_15 (Batc (None, 8, 8, 512)         2048      
_________________________________________________________________
global_average_pooling2d_5 ( (None, 512)               0         
_________________________________________________________________
dense_31 (Dense)             (None, 3)                 1539      
=================================================================
Total params: 24,617,475
Trainable params: 1,051,651
Non-trainable params: 23,565,824
_________________________________________________________________

 

모델학습

model.compile(optimizer='adam',loss='categorical_crossentropy',metrics='accuracy')
def scheduler(epoch, lr):
    if epoch < 2:
        return lr
    else:
        return lr * tf.math.exp(-0.1)
lrs = tf.keras.callbacks.LearningRateScheduler(scheduler)
model.fit(image_data_train,batch_size=32,epochs=5,callbacks=[lrs],validation_data=(image_data_test),
          validation_steps =image_data_test.samples/image_data_test.batch_size)

Epoch 1/5 63/63 [==============================] - 17s 235ms/step - loss: 0.1536 - accuracy: 0.9465 - val_loss: 0.0319 - val_accuracy: 0.9899 Epoch 2/5 63/63 [==============================] - 14s 220ms/step - loss: 0.0171 - accuracy: 0.9945 - val_loss: 0.0351 - val_accuracy: 0.9889 Epoch 3/5 63/63 [==============================] - 14s 219ms/step - loss: 0.0043 - accuracy: 0.9983 - val_loss: 0.0329 - val_accuracy: 0.9899 Epoch 4/5 63/63 [==============================] - 14s 219ms/step - loss: 0.0022 - accuracy: 1.0000 - val_loss: 0.0317 - val_accuracy: 0.9889 Epoch 5/5 63/63 [==============================] - 14s 220ms/step - loss: 0.0017 - accuracy: 0.9998 - val_loss: 0.0307 - val_accuracy: 0.9899

[185]:

<tensorflow.python.keras.callbacks.History at 0x7f30ac771b50>

 

 

Test

from tensorflow.keras.preprocessing.image import load_img
from tensorflow.keras.preprocessing.image import img_to_array
import matplotlib.pyplot as plt
import numpy as np

img_height = 256
img_width = 256

filename = ['./data/test/cat.jpg','./data/test/dog.jpg','./data/test/panda.jpg']

predict_dictionary = {0:'cat',1:'dog',2:'panda'}

for file in filename:
    original = load_img(file, target_size = (img_height,img_width))

    numpy_image = img_to_array(original)
    plt.imshow(np.uint8(numpy_image))
    plt.show()
    print("numpy array size : ", numpy_image.shape)
    image_batch = np.expand_dims(numpy_image , axis = 0)

    predict = np.argmax(model.predict(image_batch/255.))

    print('결과 : ',predict_dictionary[predict])

numpy array size : (256, 256, 3) 결과 : cat

numpy array size : (256, 256, 3) 결과 : dog

numpy array size : (256, 256, 3) 결과 : panda

 

예측이 잘됐네요~

 

예측을 하실땐 꼭 이미지를 학습하기전에 전처리 할때 처럼 꼭 전처리를 해줘야합니다!

이미지는 대부분 255.로 나누어줍니다 0~1사이로 Scale하는거죠

 

긴글 봐주셔서 감사합니다.

다음엔 YoloV5 사용하는 방법을 올립니다.

 

최종코드는 깃허브에 업로드됩니다.

 

github.com/Joonyeong97/Tensorflow-tutorial

 

Joonyeong97/Tensorflow-tutorial

GitHub Desktop tutorial repository. Contribute to Joonyeong97/Tensorflow-tutorial development by creating an account on GitHub.

github.com

 

반응형