๋์๋ฆฌ,ํํ/GDGoC
[AI ์คํฐ๋] Section 8 : ์ ์ดํ์ต
egahyun
2024. 12. 27. 02:11
์ ์ดํ์ต์ด๋?
๋ชจ๋ธ ์๋ ํ๋ฆ
- ๊ธฐ์กด์ ํ๋ จ๋ ๋ชจ๋ธ : 1000๊ฐ์ง๋ฅผ ๋ถ๋ฅํ ์ ์๋ ํฐ ๋ชจ๋ธ
- weight transfer
- ์ฌ์ฉ ์์ : ๊ธฐ์กด ํฐ ๋ชจ๋ธ์ด ์๊ณ , 2๊ฐ์ง๋ฅผ ๋ถ๋ฅํ ์ ์๋ ๋ชจ๋ธ์ ํ๊ณ ์ถ์ ๋
- ํจ๊ณผ : ์๊ท๋ชจ์ ๋ฐ์ดํฐ ์ ์ผ๋ก ํ๋ จ์๋ ์ข์ ์ฑ๋ฅ์ ๋ผ ์ ์์
- ํ๋ จ๋ ์ปจ๋ณผ๋ฃจ์ ๋ ์ด์ด : ํ๋ จ๋ ํํฐ๋ค์ด ๋ด์ฅ๋์ด์์
- ⇒ ์์ ๋ฐ์ดํฐ์ ์ผ๋ก๋ ๋ถ๋ฅ ๊ฐ๋ฅํ๊ฒ ํจ
- : ๊ธฐ์กด ๋ชจ๋ธ์ ์ปจ๋ณผ๋ฃจ์ ๋ ์ด์ด๋ฅผ ๊ฐ์ ธ์ ๊ฐ์ค์น๋ฅผ ์ ์์์ผ ์ฌ์ฉํ๋ ๊ฒ
ํ์ต ์ ๋ต
- CNN layer = ์ ์ง / ์ถ๊ฐํ ์์ ์ฐ๊ฒฐ์ธต (Dense Layer) = ์๋กญ๊ฒ ํ์ต
- ์ฌ์ฉ ์์ : ๋ฐ์ดํฐ๊ฐ ๊ต์ฅํ ์์ ๊ฒฝ์ฐ
- ์ ์ฒด ๋ ์ด์ด = ๋งค์ฐ ์์ learning rate๋ก ์ฌํ์ต
- ์ฌ์ฉ ์์ : ๋ฐ์ดํฐ๋ฅผ ์ ์ฒด ํ๋ จ ์ํฌ ์ ๋๋ก ๋ง์ด ์๋ ๊ฒฝ์ฐ
- ์์ ํ์ต๋ฅ ์ ์ฌ์ฉํด์ผํจ ⇒ ๊ฐ๊ธ์ ๊ฐ์ค์น๋ฅผ ์ ์ ์งํ๋ฉฐ, ์กฐ๊ธ ํ๋ํ๋๋ก !(ํฐ ํ์ต๋ฅ ์ฌ์ฉ์, ๊ฐ์ค์น๊ฐ ๋ค ํํธ๋ฌ์ง)
- (์ด๋ฏธ ํ๋ จ๋ convolutional layer๋ฅผ ์ฌํ๋ จํ๊ธฐ ๋๋ฌธ)
๊ณ ๋ ค ์ฌํญ
- ๋ชฉ์ ์ ๋ง๋ ๋ฐ์ดํฐ ์
์ ํ
- ์๋ ๋ฐ์ดํฐ์ : ๋ถ๋ฅ๊ฐ ์๋ ๊ฐ๋ฅ์ฑ์ด ๋์ (ex : Cat & Dog ๊ตฌ๋ถ → ImageNet ์ ํฌํจ)
- ์๋ ๋ฐ์ดํฐ์ : ๋ถ๋ฅ๊ฐ ์๋จ (ex : Cancer cell ๊ตฌ๋ถ → ImageNet ์ ์์ ⇒ ์ผ๊ตฌ๊ณต ๋ฑ์ผ๋ก ๋ถ๋ฅ)
- : ImageNet์ ์๋ ๋ฐ์ดํฐ ์ ์ธ์ง ํ์ธ ํ์
- ๋ณด์ ๋ฐ์ดํฐ์ Volume ๊ณ ๋ ค
- ๊ตฌ์กฐ๋ง ๊ฐ์ ธ์ค๊ณ , ๋ชจ๋ weight ์๋ก์ด training (Large Data ๋ณด์ )
- Weight ์ ์ผ๋ถ๋ง training
- ๋ง์ง๋ง layer ๋ง Fine-tuning (Small Data ๋ณด์ ) : ํ๋ จ์ ๋์ด ์๋ ๋ถ๋ถ์ ๊ฑด๋ค์ง ์์
Tensorflow Hub
https://www.tensorflow.org/hub?hl=ko : ํ์ด์ฌ๋ง ์ฌ์ฉํ ์ค ์๋ฉด ๋ชจ๋ธ์ ๋ง๋ค ์ ์์
ImageDataGenerator
: ์ด๋ฏธ์ง ๋ ์ด๋ธ๋ง์ด๋๋๋ก ๋ฐํํด์ฃผ๋ ํจ์


- methods : .flow_from_directory
- ๋์ฉ๋ data ๋ฅผ directory ์์ ์ง์ ๋ก๋
- directory ๊ตฌ์กฐ์ ์ํด ์๋์ผ๋ก label ์ธ์
2. flow_from_directory ์ฌ์ฉ๋ฒ
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# Instance ์์ฑ
train_data_gen = ImageDataGenerator(rescale=1/255.)
# flow_from_directory method ํธ์ถ :
train_generator = train_data_gen.flow_from_directory(
train_dir,
target_size(150, 150), # image size ํต์ผ
batch_size=20,
class_mode='binary’ or 'categorical)
3. data augmentation (๋ฐ์ดํฐ ์ฆ๊ฐ)
: ๋ค๋ฅธ์ด๋ฏธ์ง ์ฒ๋ผ ๋ณด์ด๋๋ก ํ์ฌ ๋ถ์กฑํ ๋ฐ์ดํฐ๋ฅผ ๋ณด์ถฉํด์ฃผ๋ ๊ธฐ๋ฅ
→ ex) ์ด๋ฏธ์ง๋ฅผ ์ฐ๊ทธ๋ฌํธ๋ฆผ / ์ข์ฐ ๋ฐ์
→ flow_from_directory ๊ฐ ๋ถ์์ ์ผ๋ก ์ ๊ณตํ๋ ๊ธฐ๋ฅ
์ค์ต - Tensorflow Hub ๋ชจ๋ธ์ ์ด์ฉํ ์ ์ด ํ์ต
๋ฌธ์ ์ ์
: pre-trained model (MobileNet_V2) ์ feature extractor๋ก ์ด์ฉํ์ฌ ๊ฝ image ์ ํนํ๋ image ๋ถ๋ฅ model
๋ชจ๋ธ ๊ตฌ์ฑ : MobileNet
- ImageNet ์ ์๋ฐฑ๋ง์ฅ ์ด๋ฏธ์ง ๋ฅผ ์ด์ฉํ์ฌ ํ๋ จ๋จ
- 1000 ๊ฐ์ class ๋ก ์ด๋ฏธ์ง ๊ตฌ๋ถ
- class์ค ํ๋ฅ ์ด ๋์ 5๊ฐ๋ฅผ ๋ฐํ
model = tf.keras.Sequntial([
**MobileNet_feature_extractor_layer**
tf.keras.layers.Dense(flowers_data.num_classes, activation='softmax')
])
๋ชจ๋ธ ๊ตฌ์ฑ : ํ์ธํ๋ํ์ง ์์ ๋ชจ๋ธ
import tensorflow as tf
import tensorflow_hub as hub
from tensorflow.keras.applications.mobilenet import decode_predictions # ๋ช ๋ฒ์งธ์ ์ด๋ค ์ฌ์ง์ธ์ง ํ์ธ ํ ์ ์์
# Fine Tuning ์์ด ์ฌ์ฉํ๊ธฐ ์ํด Full Model download
Trained_MobileNet_url = "<https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/2>"
Trained_Mobilenet = tf.keras.Sequential([
hub.KerasLayer(Trained_MobileNet_url , input_shape=(224, 224,3))]) # ์ฌ์ ํ๋ จ์, ์ฌ์ฉํ๋ ์
๋ ฅ ์ฌ์ด์ฆ๋ฅผ ๊ทธ๋๋ก ํด์ผํจ
Trained_Mobilenet.input, Trained_Mobilenet.output
# (,
# ) -> 1001 ๊ฐ์ ํ๋ฅ ๋ถํฌ ์์ฑ
# ์์ ์ฝ๋๊ฐ ์ค๋ฅ๋๋ ๊ฒฝ์ฐ ํด๊ฒฐ ๋ฐฉ๋ฒ 1
!pip install tf_keras
import tf_keras as tfk
Trained_MobileNet_url = "<https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/2>"
Trained_MobileNet = tfk.Sequential([
hub.KerasLayer(Trained_MobileNet_url, input_shape=(224, 224, 3))
])
Trained_MobileNet.input, Trained_MobileNet.output
# ํด๊ฒฐ ๋ฐฉ๋ฒ 2 : ์๋์ฒ๋ผ ๋ค์ด๊ทธ๋ ์ด๋ํ, ์๋ ์ฝ๋ ์คํ
!pip install tensorflow==2.13.0 !pip install tensorflow_hub==0.14.0
ํ์ธ ํ๋ํ์ง ์์ ๋ชจ๋ธ๋ก ๋ถ๋ฅ
from PIL import Image # ์ด๋ฏธ์ง ์ฒ๋ฆฌ
from urllib import request # ์ธํฐ๋ท์์ ๊ฐ์ ธ์ค๊ธฐ ํจ
from io import BytesIO # ์ธํฐ๋ท์์ ์ฌ์ง ์์ง์ ์์คํค์ฝ๋๋ก ์์ง๋๋ฏ๋ก ์ด๋ฏธ์งํํ๋ก ๋ฐ๊พธ๊ธฐ ์ํด
# ์์งํ ์ด๋ฏธ์ง url๋ก ๊ฐ์ ธ์ด
url = "<https://github.com/ironmanciti/MachineLearningBasic/blob/master/datasets/TransferLearningData/watch.jpg?raw=true>"
res = request.urlopen(url).read()
Sample_Image = Image.open(BytesIO(res)).resize((224, 224)) # ๋ชจ๋ธ ์
๋ ฅ ์ฌ์ด์ฆ์ ๋ง์ถฐ์ resize (tuple๋ก)
# numpy array๋ก ์ํ์ด๋ฏธ์ง๋ฅผ ๋ฃ์ด์ ํ๋ฆฌํ๋ก์ธ์ฑ๋ ์ด๋ฏธ์ง ๋ฐ์ดํฐ ์ถ๋ ฅ
# ๋ชจ๋ธ์ด ์
๋ ฅ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ์ ์ฒ๋ฆฌ ํ๋์ง ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์ preprocess_input์ ์ฌ์ฉํด ์ ์ฒ๋ฆฌ
x = tf.keras.applications.mobilenet.preprocess_input(np.array(Sample_Image))
x.shape # (224, 224, 3)
# ํด๋์ค ์์ธก : 1001๊ฐ์ง ํ๋ฅ ๋ถํฌ (1000๊ฐ์ ํด๋์ค + ๋ฐฐ๊ฒฝ 1๊ฐ)
predicted_class = Trained_Mobilenet.predict(np.expand_dims(x, axis = 0)) # ํ๊ฑด์ ์ด๋ฏธ์ง์ง๋ง ๋ฐฐ์น์ธ๊ฒ ์ฒ๋ผ์ค
# ๋ถ๋ฅ๋ ํด๋์ค์ ์ธ๋ฑ์ค๊ฐ ์ถ์ถ -> ex) 827 : 827๋ฒ์งธ ํด๋์ค๋ก ๋ถ๋ฅ๊ฒ
predicted_class.argmax(axis=-1)
# ํด๋น ์ฌ์ง์ ํด๋์ค๋ณ ์์ธก ํ๋ฅ top 5 ํ์ธ
decode_predictions(predicted_class[:, 1:]) # ์ฒซ๋ฒ์งธ label์ background
[[('n04328186', 'stopwatch', 9.666367),
('n02708093', 'analog_clock', 8.007808),
('n03706229', 'magnetic_compass', 6.8384614),
('n04548280', 'wall_clock', 6.563991),
('n03197337', 'digital_watch', 4.9182053)]]
# ์
๋ ฅ ์ฌ์ง๊ณผ ๋ถ๋ฅ๋ ๊ฒ์ผ๋ก ์ ๋ชฉ์ผ๋ก ํ์ฌ ์๊ฐํ
plt.imshow(Sample_Image)
predicted_class = imagenet_labels[np.argmax(predicted_class)]
plt.title("Predicted Class is: " + predicted_class.title())

# 1000๊ฐ์ง ๋ ์ด๋ธ์ด ๋ญ๊ฐ ์๋์ง ํ์ธ
labels_path = tf.keras.utils.get_file('ImageNetLabels.txt',
'<https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt>')
imagenet_labels = np.array(open(labels_path).read().splitlines())
print(imagenet_labels[:10])
๊ฝ ์ฌ์ง Batch Image ์ ๋ํ MobileNet ํ๊ฐ - ํ์ธ ํ๋ํ์ง ์์ ๋ชจ๋ธ
flower data ๋ 5 ๊ฐ์ class ๋ก ๊ตฌ์ฑ
# Specify path of the flowers dataset : ๋ฐ์ดํฐ ๋ค์ด๋ก๋
flowers_data_path = tf.keras.utils.get_file(
'flower_photos','<https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz>',
untar=True)
# ์ด๋ฏธ์ง ์๋ ๋ ์ด๋ธ๋ง : Found 3670 images belonging to 5 classes
image_generator = tf.keras.preprocessing.image.ImageDataGenerator(
preprocessing_function=tf.keras.applications.mobilenet.preprocess_input) # ์ ์ฒ๋ฆฌ ๋ชจ๋
flowers_data = image_generator.**flow_from_directory**(flowers_data_path,
target_size=(224, 224), batch_size = 64, shuffle = True)
# input_batch : ์ด๋ฏธ์ง ์์ฒด
# label_batch : ์ด๋ฏธ์ง๊ฐ ์กด์ฌํ๋ ํด๋ ์ด๋ฆ
input_batch, label_batch = next(flowers_data) # ์ ๋๋ ์ดํฐ ํจ์์ด๋ฏ๋ก next๋ฅผ ์ด์ฉํด ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ด
print("Image batch shape: ", input_batch.shape) # (64, 224, 224, 3)
print("Label batch shape: ", label_batch.shape) # (64, 5) : ์ํซ์ธ์ฝ๋ฉ ๋์ด์์
print("Label class ์: ", flowers_data.num_classes) # 5
print("Class Index : ", flowers_data.class_indices) # {'daisy': 0, 'dandelion': 1, 'roses': 2, 'sunflowers': 3, 'tulips': 4}
# Key : label ์ด๋ฆ, Value : index => Key : index, Value : label ์ด๋ฆ
# ์ด๋ค ์ธ๋ฑ์ค๊ฐ ์ด๋ค ๋ ์ด๋ธ ๋ช
์ธ์ง ํ์ธ ๊ฐ๋ฅํ๋ก
class_names = {v:k for k,v in flowers_data.class_indices.items()}
# ์์์ ๊ฝ ์ด๋ฏธ์ง 1 ๊ฐ๋ฅผ ์ ํํ์ฌ prediction ๋น๊ต : ์ฑ๋ฅ์ด ์ ์ข๋ค.
prediction = Trained_Mobilenet.predict(input_batch[2:3])
decode_predictions(prediction[:, 1:])
[[('n03930313', 'picket_fence', 5.1765366),
('n03944341', 'pinwheel', 4.367714),
('n03598930', 'jigsaw_puzzle', 3.9853535),
('n03447721', 'gong', 3.9513822),
('n09256479', 'coral_reef', 3.7957406)]]
๋ถ๋ฅ๋ ์ด๋ฏธ์ง ํ์ธ ์๊ฐํ
# 10 ๊ฐ image ์๊ฐํ
plt.figure(figsize=(16, 8))
for i in range(10):
plt.subplot(1, 10, i+1)
img = ((input_batch[i]+1)*127.5).astype(np.uint8)
idx = np.argmax(label_batch[i])
plt.imshow(img)
plt.title(class_names[idx])
plt.axis('off')

์ ์ดํ์ต ๋ชจ๋ธ์ Flower ๋ถ๋ฅ์ ์ ํฉํ ๋ชจ๋ธ๋ก ์ฌํ๋ จ
⇒ Fine Tuning ์ ์ํด head ๊ฐ ์ ๊ฑฐ๋ model ์ download

# ํ ๋ ์ด์ด๋ฅผ ์ ๊ฑฐํ ๋ชจ๋ธ์ url
extractor_url = "<https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/2>"
# ํน์ฑ ํผ์ฒ๊ฐ
extractor_layer = hub.KerasLayer(extractor_url, input_shape=(224, 224, 3))
feature_batch = extractor_layer(input_batch)
# MobileNet ์ pre-trained weight ๋ update x
# Top layer ์ Dense layer ์ถ๊ฐ
# CNN layer = ์ ์ง / ์ถ๊ฐํ ์์ ์ฐ๊ฒฐ์ธต (Dense Layer) = ์๋กญ๊ฒ ํ์ต ํ๋ ๋ต
extractor_layer.trainable = False
# Build a model with two pieces:
# (1) MobileNet Feature Extractor
# (2) Dense Network (classifier) added at the end
model = tf.keras.Sequential([
extractor_layer,
tf.keras.layers.Dense(flowers_data.num_classes, activation='softmax')
])
# output shape ์ด ์ ํํ์ง training ์ ์ ์ฌ์ check
# (,
# )
model.input, model.output
# ๋ชจ๋ธ ์ปดํ์ผ ๋ฐ ํ๋ จ
# ๋ค์ค๋ถ๋ฅ์ด๋ฏ๋ก categorical_crossentropy
# 64๊ฐ์ฉ flower data๊ฐ ๋ถ๋ฌ๋ค์ฌ์ด
model.compile(optimizer=tf.keras.optimizers.Adam(),
loss='categorical_crossentropy', metrics=['accuracy'])
history = model.fit(flowers_data, epochs=30)
Flower ๋ถ๋ฅ ์ ๋ฌธ์ผ๋ก Fine Tuning ๋ MODEL ํ๊ฐ
# ํ๋ฅ ๋ถํฌ๋ก ๋์ด
y_pred = model.predict(input_batch)
# ๋ถ๋ฅ๋ ๊ฒ์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ง๋๋ก
y_pred = np.argmax(y_pred, axis=-1)
# ์ ๋ต ๋ฐ์ดํฐ์ ์ธ๋ฑ์ค ํ์ธ
y_true = np.argmax(label_batch, axis=-1)
# ์ ํ๋ : 100 %
f"{sum(y_pred == y_true) / len(y_true) * 100:.2f} %"
# ์์ธก ์๊ฐํ
plt.figure(figsize=(10,9))
plt.subplots_adjust(hspace=0.5)
for i in range(64):
plt.subplot(8, 8, i+1)
img = ((input_batch[i]+1)*127.5).astype(np.uint8)
plt.imshow(img)
color = "green" if y_pred[i] == y_true[i] else "red"
plt.title(class_names[y_pred[i]], color=color)
plt.axis('off')
