<jupyter_start><jupyter_text>Transfer Learning 전이학습* 기존의 이미 만들어진 모델을 사용하여 새로운 모델을 만든다. * **Transfer learning의 필요성**    * Convolution network을 처음부터 학습시키는 것은 시간과 자원이 많이 든다.    * 복잡한 모델일수록 학습시키기 어렵다.     * 실질적으로 처음부터 학습시키려면 많은 시도가 필요* **Transfer learning 장점**    * 적은 데이터로도 학습이 가능    * 학습 속도도 빠르다.     * 예측을 더 높이는 방법이다.    * 이미 잘 훈련된 모델이 있고, 특히 해당 모델과 유사한 문제를 해결하고자 할 때  transfer learning을 사용할 수 있다.    * 예를 들어 Imagenet으로 훈련된 모형을 피부암 진단에 사용할 수 있다.* 일반적으로 VGG, ResNet, gooGleNet 등 이미 이러한 사전에 학습이 완료된 모델(Pre-Training Model)을 가지고 우리가 원하는 학습에 미세 조정하여 학습시키는 방법이 Transfer Learning이다.* **ConvNet as fixed feature extractor**: ConvNet 끝에 달린 fully-connected layer를 없애고, convolutional layer를 통해 처리되는 값만 얻는 방법이다. 전체 ConvNet을 target 데이터 세트의 고정된 feature 추출기로 사용할 수 있다는 것이다. top layer인 fully-connected layer만을 훈련한다.**tf.keras.application 모듈**에서 이미 훈련된(pre-trained) model을 다운로드 할 수 있다.<jupyter_code>import tensorflow as tf
from tensorflow import keras
print("TensorFlow version is ", tf.__version__)

import os
import numpy as np

import matplotlib.pyplot as plt
import matplotlib.image as mpimg<jupyter_output>TensorFlow version is  2.7.0<jupyter_text>이미지 데이터를 loading한다.<jupyter_code>import os
print(os.environ['USERPROFILE'])
_URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip'

path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True)

PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered')

#path_to_zip = os.environ['USERPROFILE'] + '\\.keras\\datasets'

#PATH = os.path.join(path_to_zip, 'cats_and_dogs_filtered')
print(PATH)
train_dir = os.path.join(PATH, 'train')
validation_dir = os.path.join(PATH, 'validation')
train_cats_dir = os.path.join(train_dir, 'cats')  # directory with our training cat pictures
train_dogs_dir = os.path.join(train_dir, 'dogs')  # directory with our training dog pictures
validation_cats_dir = os.path.join(validation_dir, 'cats')  # directory with our validation cat pictures
validation_dogs_dir = os.path.join(validation_dir, 'dogs')  # directory with our validation dog pictures
num_cats_tr = len(os.listdir(train_cats_dir))
num_dogs_tr = len(os.listdir(train_dogs_dir))

num_cats_val = len(os.listdir(validation_cats_dir))
num_dogs_val = len(os.listdir(validation_dogs_dir))

total_train = num_cats_tr + num_dogs_tr
total_val = num_cats_val + num_dogs_val
print('total training cat images:', num_cats_tr)
print('total training dog images:', num_dogs_tr)

print('total validation cat images:', num_cats_val)
print('total validation dog images:', num_dogs_val)
print("--")
print("Total training images:", total_train)
print("Total validation images:", total_val)
batch_size = 128
epochs = 15
IMG_HEIGHT = 160
IMG_WIDTH = 160<jupyter_output><empty_output><jupyter_text>디렉토리의 이미지를 dataset으로 생성한다.<jupyter_code>from tensorflow.keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale=1./255) # Generator for our training data
validation_datagen = ImageDataGenerator(rescale=1./255) # Generator for our validation data
# image_size를 변경하지 마시오.
image_size = 160 # All images will be resized to 160x160
batch_size = 32

# Flow training images in batches of 20 using train_datagen generator
train_generator = train_datagen.flow_from_directory(
                train_dir,  # Source directory for the training images
                target_size=(image_size, image_size),
                batch_size=batch_size,
                # Since we use binary_crossentropy loss, we need binary labels
                class_mode='binary')

# Flow validation images in batches of 20 using test_datagen generator
validation_generator = validation_datagen.flow_from_directory(
                validation_dir, # Source directory for the validation images
                target_size=(image_size, image_size),
                batch_size=batch_size,
                class_mode='binary')<jupyter_output>Found 2000 images belonging to 2 classes.
Found 1000 images belonging to 2 classes.<jupyter_text>pre trained model을 다운로드 한다.$HOME/.keras/models/ 폴더에 다운로드 된다.<jupyter_code>IMG_SHAPE = (image_size, image_size, 3)

# Create the base model from the pre-trained model MobileNet V2
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                               include_top=False,
                                               weights='imagenet')<jupyter_output><empty_output><jupyter_text>Pre-trained model의 가중치 freeze<jupyter_code>base_model.trainable = False
# Let's take a look at the base model architecture
base_model.summary()<jupyter_output>Model: "mobilenetv2_1.00_160"
__________________________________________________________________________________________________
 Layer (type)                   Output Shape         Param #     Connected to                     
==================================================================================================
 input_1 (InputLayer)           [(None, 160, 160, 3  0           []                               
                                )]                                                                
                                                                                                  
 Conv1 (Conv2D)                 (None, 80, 80, 32)   864         ['input_1[0][0]']                
                                                                                                  
 bn_Conv1 (BatchNormalization)  (None, 80, 80, 32)   128         ['Conv1[0][0]']                  
                                                                               [...]<jupyter_text>마지막에 이미지 분류를 위한 Dense layer를 추가한다.<jupyter_code>model = tf.keras.Sequential([
  base_model,
  keras.layers.GlobalAveragePooling2D(),
  keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer=tf.keras.optimizers.RMSprop(learning_rate=0.0001),
              loss='binary_crossentropy',
              metrics=['accuracy'])
model.summary()<jupyter_output>Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 mobilenetv2_1.00_160 (Funct  (None, 5, 5, 1280)       2257984   
 ional)                                                          
                                                                 
 global_average_pooling2d (G  (None, 1280)             0         
 lobalAveragePooling2D)                                          
                                                                 
 dense (Dense)               (None, 1)                 1281      
                                                                 
=================================================================
Total params: 2,259,265
Trainable params: 1,281
Non-trainable params: 2,257,984
_________________________________________________________________<jupyter_text>모형을 훈련한다.epoch수는 훈련시간을 고려하여 적절하게 선택한다.<jupyter_code>epochs = 3

history = model.fit(train_generator,
                              epochs=epochs,
                              workers=4,
                              validation_data=validation_generator)<jupyter_output>Epoch 1/3
63/63 [==============================] - 21s 297ms/step - loss: 0.6653 - accuracy: 0.6270 - val_loss: 0.5086 - val_accuracy: 0.7860
Epoch 2/3
63/63 [==============================] - 18s 292ms/step - loss: 0.4277 - accuracy: 0.8510 - val_loss: 0.3400 - val_accuracy: 0.8900
Epoch 3/3
63/63 [==============================] - 19s 303ms/step - loss: 0.2961 - accuracy: 0.9120 - val_loss: 0.2508 - val_accuracy: 0.9150<jupyter_text>훈련결과 시각화<jupyter_code>acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

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

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.ylabel('Accuracy')
plt.ylim([min(plt.ylim()),1])
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.ylabel('Cross Entropy')
plt.ylim([0,max(plt.ylim())])
plt.title('Training and Validation Loss')
plt.show()<jupyter_output><empty_output><jupyter_text>이미지 분류 예측<jupyter_code>probabilities = model.predict(validation_generator,1)

print(validation_generator.class_indices)
print(probabilities[:5])<jupyter_output>{'cats': 0, 'dogs': 1}
[[0.08398312]
 [0.0894354 ]
 [0.27284944]
 [0.0632942 ]
 [0.93301296]]<jupyter_text>훈련된 모형으로 예측하기<jupyter_code>imgs, labels = validation_generator.next()

preds = (model.predict(imgs) > 0.5).astype("int32") 
classes = ['cat','dog']

labels
# plot the images in the batch, along with the corresponding labels
fig = plt.figure(figsize=(25, 4))
# display 20 images
for idx in np.arange(20):
    ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])
    plt.imshow(imgs[idx])
    ax.set_title("{} ({})".format(classes[preds[idx].item()], classes[int(labels[idx])]),
                 color=("green" if preds[idx]==labels[idx].item() else "red"))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13173847153063434, 'fraction_numerical': 0.03431478675037887, 'mean_word_length': 2.921477079796265, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 36, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 30, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '604329', 'license': 'MIT', 'n_tokens_mistral': 3413, 'n_tokens_neox': 3349, 'n_words': 657, 'path': '02CNN/06Cat_Dog_Transfer_learning.ipynb', 'repo_name': 'aonekoda/tf_new', 'size': '9238'}