# Day_34_01_tfhub_finetune.py
import tensorflow as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import PIL.Image as Image
import tensorflow_hub as hub
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# Fine-tuning 이란
# 남이 만들어 놓은 모듈을 내가 조금만 다듬어서 사용하겠다
# trainable=True to hub.KerasLayer이걸 써서
# resnet_50 모델을 사용해서 꽃 데이터셋에 대해 학습하고 랜덤으로 뽑은 32장의 이미지에 대해 예측한 결과를 출력하세요
# Day_33_02 가져와서 파인튜닝하는 코드로 수정 후에 정확도 계산
def get_image_classifier_with_fine_tune():
# cnn -> 좋은 피처를 추출하는 것임 그래서 classification 지나치다.
# tf.keras.applications.VGG16(include_top=True)
# url = 'https://tfhub.dev/tensorflow/resnet_50/classification/1'
# tf.keras.applications.VGG16(include_top=False) # 아래께 더 좋음
url = 'https://tfhub.dev/tensorflow/resnet_50/feature_vector/1'
model = tf.keras.Sequential()
model.add(tf.keras.layers.Input(shape=[224, 224, 3]))
# 기존의 성능이 안 좋으면 -> fine_tuning 을 쓰는 것이 맞음.
# 자체적으로 soft_max가 있음
# 이거 학습하는 것이 너무 오래 걸려서 False 쓸 것임
model.add(hub.KerasLayer(url, trainable=False)) # 여기서 trainable 쓰는 거임 기본 값 False
# 앞쪽에서는 학습하지 않음 -> 공통된 feature 만 추출함
# 밑에 쪽에서는 나만의 레이어 학습하는것
model.add(tf.keras.layers.Dense(1024, activation='relu'))
model.add(tf.keras.layers.Dense(5, activation='softmax')) # 1001개의 데이터를 반환하는데 우리는 5개만있음 그래서 써줌
# softmax가 여러번 반복되는 안좋음 -> graident vanishing 그리디언트 소실 -> 미분해야하는데 값이 너무 작아짐
# 하지만 어쩔 수 없음
model.summary()
return model
def classify_image_by_generator():
img_url = 'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz'
img_path = tf.keras.utils.get_file('flower_photos', img_url, untar=True) # 압축 풀기 까지
# print(img_path) # C:\Users\82103\.keras\datasets\flower_photos
# 이미지 증강은 의미가 없음 그냥 데이터 32개를 예측만 할거임
data_gen = ImageDataGenerator(rescale=1 / 255)
batch_size = 32
# 3가지 방법 -> (x,y), pandas, 폴더에 있는것
# 우리 폴더 안에 있는 25000개의 데이터를 무제한으로 가져옴 -> 조심해야함
data_flow = data_gen.flow_from_directory(
img_path,
batch_size=batch_size,
target_size=(224, 224), # resize 기능을 제공해줌
class_mode='sparse', # "categorical", "binary", "sparse",
)
# 써먹을대가 많음
# print(data_flow.batch_size, data_flow.samples) # 32 3670
# print(data_flow.classes) # [0 0 0 ... 4 4 4] 3670개에 대해서
# print(data_flow.class_indices) # class의 indices 가 들어있음
# {'daisy': 0, 'dandelion': 1, 'roses': 2, 'sunflowers': 3, 'tulips': 4}
# key : value
# ['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips'] 정렬 한번 하자.
labels = sorted([k for k in data_flow.class_indices])
# print(labels)
model = get_image_classifier_with_fine_tune()
# compile을 통해 모델의 부족한 부분을 채워줘야함
model.compile(optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.sparse_categorical_crossentropy,
metrics=['acc'])
# generator 안써도 잘 돌아감 deprecated 되었기 때문에
steps_per_epoch = data_flow.samples // data_flow.batch_size
model.fit(data_flow, epochs=2, steps_per_epoch=steps_per_epoch)
# 이미지, label
xx, yy = data_flow.next() # 1번째 데이터 갯수는 32개
preds = model.predict(xx)
preds_arg = np.argmax(preds, axis=1)
for i, (img, label, pred) in enumerate(zip(xx, yy, preds_arg)):
# print(i, img.shape, pred)
plt.subplot(4, 8, i+1)
plt.title(labels[pred], color='g' if pred == label else 'r') # 맞은 건 g 틀린건 r
plt.axis('off')
plt.imshow(img) # -> 대부분 꽃 그림이 나옴 데이지를 학습했으니깐
plt.show()
classify_image_by_generator()