<jupyter_start><jupyter_text>Using Transfer Learning to Train a CNNFirst, we'll import the latest version of Keras and prepare to load our training data.<jupyter_code>!pip install --upgrade keras

import keras
from keras import backend as K

print('Keras version:',keras.__version__)<jupyter_output>Requirement already up-to-date: keras in /home/nbuser/anaconda3_501/lib/python3.6/site-packages (2.2.4)
Requirement already satisfied, skipping upgrade: six>=1.9.0 in /home/nbuser/anaconda3_501/lib/python3.6/site-packages (from keras) (1.11.0)
Requirement already satisfied, skipping upgrade: numpy>=1.9.1 in /home/nbuser/anaconda3_501/lib/python3.6/site-packages (from keras) (1.14.6)
Requirement already satisfied, skipping upgrade: pyyaml in /home/nbuser/anaconda3_501/lib/python3.6/site-packages (from keras) (3.13)
Requirement already satisfied, skipping upgrade: scipy>=0.14 in /home/nbuser/anaconda3_501/lib/python3.6/site-packages (from keras) (1.1.0)
Requirement already satisfied, skipping upgrade: keras-preprocessing>=1.0.5 in /home/nbuser/anaconda3_501/lib/python3.6/site-packages (from keras) (1.0.9)
Requirement already satisfied, skipping upgrade: h5py in /home/nbuser/anaconda3_501/lib/python3.6/site-packages (from keras) (2.8.0)
Requirement already satisfied, skipping upgrade: ker[...]<jupyter_text>Prepare the Data<jupyter_code>import os
from keras.preprocessing.image import ImageDataGenerator

# The images are in a folder named 'classification/training'
training_folder_name = '../data/classification/training'

# The folder contains a subfolder for each class of shape
classes = sorted(os.listdir(training_folder_name))
print(classes)

# Our source images are 128x128, but the base model we're going to use was trained with 224x224 images
pretrained_size = (224,224)
batch_size = 15

print("Getting Data...")
datagen = ImageDataGenerator(rescale=1./255, # normalize pixel values
                             validation_split=0.3) # hold back 30% of the images for validation

print("Preparing training dataset...")
train_generator = datagen.flow_from_directory(
    training_folder_name,
    target_size=pretrained_size,
    batch_size=batch_size,
    class_mode='categorical',
    subset='training') # set as training data

print("Preparing validation dataset...")
validation_generator = datagen.flow_from_directory(
    training_folder_name,
    target_size=pretrained_size,
    batch_size=batch_size,
    class_mode='categorical',
    subset='validation') # set as validation data<jupyter_output>['automobile', 'plane', 'train']
Getting Data...
Preparing training dataset...
Found 168 images belonging to 3 classes.
Preparing validation dataset...
Found 72 images belonging to 3 classes.<jupyter_text>Download a trained model to use as a base<jupyter_code>from keras import applications
#Load the base model, not including its final connected layer, and set the input shape to match our images
base_model = keras.applications.vgg16.VGG16(weights='imagenet', include_top=False, input_shape=train_generator.image_shape)<jupyter_output>Downloading data from https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
58892288/58889256 [==============================] - 10s 0us/step<jupyter_text>Freeze the already trained layers and add a custom output layer for our classes<jupyter_code>from keras import Model
from keras.layers import Flatten, Dense
from keras import optimizers

# Freeze the already-trained layers in the base model
for layer in base_model.layers:
    layer.trainable = False

# Create layers for classification of our images
x = base_model.output
x = Flatten()(x)
prediction_layer = Dense(len(classes), activation='sigmoid')(x) 
model = Model(inputs=base_model.input, outputs=prediction_layer)

# Compile the model
opt = optimizers.Adam(lr=0.001)
model.compile(loss='categorical_crossentropy',
              optimizer=opt,
              metrics=['accuracy'])

# Now print the full model, which will include the layers of the base model plus the dense layer we added
print(model.summary())<jupyter_output>_________________________________________________________________
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_poo[...]<jupyter_text>Train the Model<jupyter_code># Train the model over 3 epochs
num_epochs = 3
history = model.fit_generator(
    train_generator,
    steps_per_epoch = train_generator.samples // batch_size,
    validation_data = validation_generator, 
    validation_steps = validation_generator.samples // batch_size,
    epochs = num_epochs)<jupyter_output>Epoch 1/3
11/11 [==============================] - 292s 27s/step - loss: 0.7369 - acc: 0.6909 - val_loss: 0.2580 - val_acc: 0.9333
Epoch 2/3
11/11 [==============================] - 157s 14s/step - loss: 0.0664 - acc: 0.9756 - val_loss: 0.0913 - val_acc: 0.9825
Epoch 3/3
11/11 [==============================] - 157s 14s/step - loss: 0.0185 - acc: 1.0000 - val_loss: 0.2156 - val_acc: 0.9474<jupyter_text>Use the Trained Model<jupyter_code># Helper function to resize image
def resize_image(src_img, size=(128,128), bg_color="white"): 
    from PIL import Image

    # rescale the image so the longest edge is the right size
    src_img.thumbnail(size, Image.ANTIALIAS)
    
    # Create a new image of the right shape
    new_image = Image.new("RGB", size, bg_color)
    
    # Paste the rescaled image onto the new background
    new_image.paste(src_img, (int((size[0] - src_img.size[0]) / 2), int((size[1] - src_img.size[1]) / 2)))
  
    # return the resized image
    return new_image

# Function to predict the class of an image
def predict_image(classifier, image_array):
    import numpy as np
    
    # We need to format the input to match the training data
    # The data generator loaded the values as floating point numbers
    # and normalized the pixel values, so...
    img_features = image_array.astype('float32')
    img_features /= 255
    
    # These are the classes our model can predict
    classnames = ['automobile', 'plane', 'train']
    
    # Predict the class of each input image
    predictions = classifier.predict(img_features)
    
    predicted_classes = []
    for prediction in predictions:
        # The prediction for each image is the probability for each class, e.g. [0.8, 0.1, 0.2]
        # So get the index of the highest probability
        class_idx = np.argmax(prediction)
        # And append the corresponding class name to the results
        predicted_classes.append(classnames[int(class_idx)])
    # Return the predictions
    return predicted_classes

print("Functions created - ready to use model for inference.")
import os
from random import randint
import numpy as np
from PIL import Image
from keras.models import load_model
from matplotlib import pyplot as plt
%matplotlib inline

#get the list of test image files
test_folder = '../data/classification/test'
test_image_files = os.listdir(test_folder)

# Empty array on which to store the images
image_arrays = []

size = (224,224)
background_color="white"

fig = plt.figure(figsize=(12, 8))

# Get the images and show the predicted classes
for file_idx in range(len(test_image_files)):
    img = Image.open(os.path.join(test_folder, test_image_files[file_idx]))
    
    # resize the image so it matches the training set - it  must be the same size as the images on which the model was trained
    resized_img = np.array(resize_image(img, size, background_color))
                      
    # Add the image to the array of images
    image_arrays.append(resized_img)

# Get predictions from the array of image arrays
# Note that the model expects an array of 1 or more images - just like the batches on which it was trained
predictions = predict_image(model, np.array(image_arrays))

# plot easch image with its corresponding prediction
for idx in range(len(predictions)):
    a=fig.add_subplot(1,len(predictions),idx+1)
    imgplot = plt.imshow(image_arrays[idx])
    a.set_title(predictions[idx])<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10594837261503928, 'fraction_numerical': 0.04062850729517396, 'mean_word_length': 4.3842900302114804, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 24, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '625401', 'license': 'MIT', 'n_tokens_mistral': 2852, 'n_tokens_neox': 2598, 'n_words': 799, 'path': 'Mod03/Lab 02 - Sample Solution (Keras).ipynb', 'repo_name': 'NickAjderian/dev290x', 'size': '8910'}