Transfer Learning


By Prof. Seungchul Lee
http://iai.postech.ac.kr/
Industrial AI Lab at POSTECH

Table of Contents

0. Video LecturesĀ¶

InĀ [1]:
%%html
<center><iframe src="https://www.youtube.com/embed/n296VACHPws?start=1242&rel=0" 
width="560" height="315" frameborder="0" allowfullscreen></iframe></center>

1. Pre-trained Model (VGG16)Ā¶

  • Training a model on ImageNet from scratch takes days or weeks.
  • Many models trained on ImageNet and their weights are publicly available!
  • Transfer learning
    • Use pre-trained weights, remove last layers to compute representations of images
    • The network is used as a generic feature extractor
    • Train a classification model from these features on a new classification task
    • Pre- trained models can extract more general image features that can help identify edges, textures, shapes, and object composition
    • Better than handcrafted feature extraction on natural images






1.1. Import LibraryĀ¶

InĀ [1]:
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

1.2. Load DataĀ¶

Download data files from here

InĀ [2]:
train_imgs = np.load('./data_files/target_images.npy')
train_labels = np.load('./data_files/target_labels.npy')
test_imgs = np.load('./data_files/test_images.npy')
test_labels = np.load('./data_files/test_labels.npy')

print(train_imgs.shape)
print(train_labels[0]) # one-hot-encoded 5 classes 

# remove one-hot-encoding
train_labels = np.argmax(train_labels, axis = 1)
test_labels = np.argmax(test_labels, axis = 1)
(65, 224, 224, 3)
[1. 0. 0. 0. 0.]
InĀ [3]:
n_train = train_imgs.shape[0]
n_test = test_imgs.shape[0]

# very small dataset
print(n_train)
print(n_test)
65
9
InĀ [4]:
Dict = ['Hat','Cube','Card','Torch','Screw']

plt.figure(figsize = (15,10))
plt.subplot(2,3,1)
plt.imshow(train_imgs[1])
plt.title("Label : {}".format(Dict[train_labels[1]]))
plt.axis('off')
plt.subplot(2,3,2)
plt.imshow(train_imgs[2])
plt.title("Label : {}".format(Dict[train_labels[2]]))
plt.axis('off')
plt.subplot(2,3,3)
plt.imshow(train_imgs[3])
plt.title("Label : {}".format(Dict[train_labels[3]]))
plt.axis('off')
plt.subplot(2,3,4)
plt.imshow(train_imgs[18])
plt.title("Label : {}".format(Dict[train_labels[18]]))
plt.axis('off')
plt.subplot(2,3,5)
plt.imshow(train_imgs[25])
plt.title("Label : {}".format(Dict[train_labels[25]]))
plt.axis('off')
plt.show()

1.3. Load VGG16 ModelĀ¶





InĀ [5]:
model_type = tf.keras.applications.vgg16
base_model = model_type.VGG16()
base_model.trainable = False
base_model.summary()
Model: "vgg16"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544 
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
predictions (Dense)          (None, 1000)              4097000   
=================================================================
Total params: 138,357,544
Trainable params: 0
Non-trainable params: 138,357,544
_________________________________________________________________

1.4. Testing for Target DataĀ¶

InĀ [6]:
idx = np.random.randint(n_test)
pred = base_model.predict(test_imgs[idx].reshape(-1, 224, 224, 3))
label = model_type.decode_predictions(pred)[0]

print('%s (%.2f%%)' % (label[0][1], label[0][2]*100))
print('%s (%.2f%%)' % (label[1][1], label[1][2]*100))
print('%s (%.2f%%)' % (label[2][1], label[2][2]*100))
print('%s (%.2f%%)' % (label[3][1], label[3][2]*100))
print('%s (%.2f%%)' % (label[4][1], label[4][2]*100))
    
plt.figure(figsize = (6,6))
plt.imshow(test_imgs[idx])
plt.title("Label : {}".format(Dict[test_labels[idx]]))
plt.axis('off')
plt.show()    
envelope (3.21%)
toilet_tissue (2.80%)
mosquito_net (2.60%)
Band_Aid (1.69%)
shower_curtain (1.34%)

2. Learn From ScratchĀ¶

InĀ [7]:
model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(filters = 32, 
                           kernel_size = (3,3), 
                           activation = 'relu',
                           padding = 'SAME',
                           input_shape = (224, 224, 3)),
    
    tf.keras.layers.MaxPool2D((2,2)),
    
    tf.keras.layers.Conv2D(filters = 64, 
                           kernel_size = (3,3), 
                           activation = 'relu',
                           padding = 'SAME'),
    
    tf.keras.layers.MaxPool2D((2,2)),
    
    tf.keras.layers.Conv2D(filters = 64, 
                           kernel_size = (3,3), 
                           activation = 'relu',
                           padding = 'SAME'),
    
    tf.keras.layers.MaxPool2D((2,2)),
    
    tf.keras.layers.Conv2D(filters = 64, 
                           kernel_size = (3,3), 
                           activation = 'relu',
                           padding = 'SAME'),
    
    tf.keras.layers.MaxPool2D((2,2)),
    
    tf.keras.layers.Flatten(),
    
    tf.keras.layers.Dense(units = 128, activation = 'relu'),
    
    tf.keras.layers.Dense(units = 5, activation = 'softmax')
])
InĀ [8]:
model.compile(optimizer = 'adam',
              loss = 'sparse_categorical_crossentropy',
              metrics = 'accuracy')
InĀ [9]:
model.fit(train_imgs, train_labels, batch_size = 10, epochs = 10)
Epoch 1/10
7/7 [==============================] - 2s 189ms/step - loss: 1.5000 - accuracy: 0.3692
Epoch 2/10
7/7 [==============================] - 1s 204ms/step - loss: 0.8308 - accuracy: 0.7077
Epoch 3/10
7/7 [==============================] - 1s 199ms/step - loss: 0.3868 - accuracy: 0.8769
Epoch 4/10
7/7 [==============================] - 1s 194ms/step - loss: 0.3472 - accuracy: 0.8923
Epoch 5/10
7/7 [==============================] - 1s 195ms/step - loss: 0.1995 - accuracy: 0.9385
Epoch 6/10
7/7 [==============================] - 1s 195ms/step - loss: 0.0572 - accuracy: 0.9846
Epoch 7/10
7/7 [==============================] - 1s 194ms/step - loss: 0.0322 - accuracy: 0.9846
Epoch 8/10
7/7 [==============================] - 1s 190ms/step - loss: 0.0130 - accuracy: 1.0000
Epoch 9/10
7/7 [==============================] - 1s 200ms/step - loss: 0.0141 - accuracy: 1.0000
Epoch 10/10
7/7 [==============================] - 1s 192ms/step - loss: 0.0130 - accuracy: 1.0000
Out[9]:
<tensorflow.python.keras.callbacks.History at 0x1854ee29dd8>
InĀ [10]:
test_loss, test_acc = model.evaluate(test_imgs, test_labels)
1/1 [==============================] - 0s 149ms/step - loss: 0.0424 - accuracy: 1.0000

3. Transfer LearningĀ¶

  • We assume that these model parameters contain the knowledge learned from the source data set and that this knowledge will be equally applicable to the target data set.
  • We will train the output layer from scratch, while the parameters of all remaining layers are fine tuned based on the parameters of the source model.
  • Or initialize all weights from pre-trained model, then train them with target data









3.1. Pre-trained Weights, BiasesĀ¶

InĀ [11]:
vgg16_weights = base_model.get_weights()

3.2. Build a Transfer Learning ModelĀ¶

InĀ [12]:
# replace new and trainable classifier layer
fc2_layer = base_model.layers[-2].output
output = tf.keras.layers.Dense(units = 5, activation = 'softmax')(fc2_layer)

# define new model
model = tf.keras.Model(inputs = base_model.inputs, outputs = output)
InĀ [13]:
model.summary()
Model: "model"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 224, 224, 3)]     0         
_________________________________________________________________
block1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      
_________________________________________________________________
block1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     
_________________________________________________________________
block1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         
_________________________________________________________________
block2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     
_________________________________________________________________
block2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    
_________________________________________________________________
block2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         
_________________________________________________________________
block3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    
_________________________________________________________________
block3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    
_________________________________________________________________
block3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         
_________________________________________________________________
block4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   
_________________________________________________________________
block4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   
_________________________________________________________________
block4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         
_________________________________________________________________
block5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   
_________________________________________________________________
block5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         
_________________________________________________________________
flatten (Flatten)            (None, 25088)             0         
_________________________________________________________________
fc1 (Dense)                  (None, 4096)              102764544 
_________________________________________________________________
fc2 (Dense)                  (None, 4096)              16781312  
_________________________________________________________________
dense_2 (Dense)              (None, 5)                 20485     
=================================================================
Total params: 134,281,029
Trainable params: 20,485
Non-trainable params: 134,260,544
_________________________________________________________________

3.3. Define Loss and OptimizerĀ¶

InĀ [14]:
model.compile(optimizer = 'adam', 
              loss = 'sparse_categorical_crossentropy', 
              metrics = 'accuracy')

3.4. OptimizeĀ¶

InĀ [15]:
model.fit(train_imgs, train_labels, batch_size = 10, epochs = 10)
Epoch 1/10
7/7 [==============================] - 5s 636ms/step - loss: 1.9524 - accuracy: 0.2615
Epoch 2/10
7/7 [==============================] - 5s 655ms/step - loss: 1.7324 - accuracy: 0.2154
Epoch 3/10
7/7 [==============================] - 4s 636ms/step - loss: 1.3197 - accuracy: 0.6154
Epoch 4/10
7/7 [==============================] - 5s 639ms/step - loss: 0.8798 - accuracy: 0.7846
Epoch 5/10
7/7 [==============================] - 5s 678ms/step - loss: 0.7127 - accuracy: 0.9231
Epoch 6/10
7/7 [==============================] - 5s 668ms/step - loss: 0.6179 - accuracy: 0.9538
Epoch 7/10
7/7 [==============================] - 5s 672ms/step - loss: 0.5628 - accuracy: 0.9385
Epoch 8/10
7/7 [==============================] - 5s 767ms/step - loss: 0.5056 - accuracy: 0.9077
Epoch 9/10
7/7 [==============================] - 5s 682ms/step - loss: 0.4690 - accuracy: 0.9385
Epoch 10/10
7/7 [==============================] - 5s 674ms/step - loss: 0.3972 - accuracy: 0.9692
Out[15]:
<tensorflow.python.keras.callbacks.History at 0x1854eff9d30>

3.5. Test and EvaluateĀ¶

InĀ [16]:
test_loss, test_acc = model.evaluate(test_imgs, test_labels)
1/1 [==============================] - 1s 1s/step - loss: 0.2822 - accuracy: 1.0000
InĀ [17]:
test_x = test_imgs[np.random.choice(n_test, 1)]
pred = np.argmax(model.predict(test_x))

plt.figure(figsize = (6,6))
plt.imshow(test_x.reshape(224, 224, 3))
plt.axis('off')
plt.show()

print('Prediction : {}'.format(Dict[pred]))
Prediction : Screw
InĀ [18]:
%%javascript
$.getScript('https://kmahelona.github.io/ipython_notebook_goodies/ipython_notebook_toc.js')