keras_lesson1.ipynb -- CodeAlong of fastai/courses/dl1/keras_lesson1.ipynb

Wayne H Nixalo

Using TensorFlow backend # pip install tensorflow-gpu keras

Introduction to our first task: 'Dogs vs Cats'


In [1]:
%reload_ext autoreload
%autoreload 2
%matplotlib inline

In [2]:
PATH = "data/dogscats/"
sz = 224
batch_size=64

In [3]:
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing import image
from keras.layers import Dropout, Flatten, Dense
from keras.models import Model, Sequential
from keras.layers import Dense, GlobalAveragePooling2D
from keras import backend as K


Using TensorFlow backend.

In [4]:
train_data_dir = f'{PATH}train'
valid_data_Dir = f'{PATH}valid'

Data Augmentation parameters copied from fastai --> copied from Keras Docs

Instead of creating a single data object, in Keras we have to define a data generator to specfy how to generate the data. We have to tell it what kind of dat aug, and what kind of normalization.

Generally, copy-pasting Keras code from the internet works.

Keras uses the same directory structure as FastAI.

2 possible outcomes: class_mode='binary'. Multipe: 'categorical'

In Keras you have to specify a data generator without augmentation for the testing set. Important to NOT shuffle the validation set, or else accuracy tracking can't be done.


In [ ]:
train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.2, 
                                   zoom_range=0.2, horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)

train_generator = train_datagen.flow_from_directory(train_data_dir, 
                                                    target_size=(sz,sz), 
                                                    batch_size=batch_size, 
                                                    class_mode='binary')
validation_generator = train_datagen.flow_from_directory(valid_data_dir, 
                                                         shuffle=False,
                                                         target_size=(sz,sz), 
                                                         batch_size=batch_size, 
                                                         class_mode='binary')

In Keras you have to manually specify the base model and construct on top the layers you want to add.


In [ ]:
base_model = ResNet50(weights='imagenet', include_top=False)
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(1, activation='sigmoid')(x)

Specify the model. There's no concept of automatically freezing layers in Keras, so you have to loop through the layers you want to freeze and call .trainable=False

Keras also has a concept of compiling a model, which DNE in FastAI / PyTorch


In [ ]:
model = Model(inputs=base_model.input, outputs=predictions)
for layer in base_model.layers: layer.trainable = False
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])

Keras expects to be told how many batches there are per epoch. num_batches = size of generator / batch_size

Keras also defaults to zero workers. For good speed: include num workers.


In [ ]:
%%time
model.fit_generator(train_generator, train_generator.n // batch_size, epochs=3, workers=4, 
        validation_data=validation_generator, validation_steps=validation_generator.n // batch_size)

There isn't a concept of differential learning rates or layer groups in Keras or partial unfreezing, so you'll have to decide manually. In this case: printing out to take a look, and starting from layer 140 onwards. You'll have to recompile the model after this.


In [ ]:
split_at = 140
for layer in model.layers[:split_at]: layer.trainable = False
for layer in model.layers[:split_at]: layer.trainable = True
model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])

In [ ]:
%%time
model.fit_generator(train_generator, train_generator.n // batch_size, epochs=1, 
        validation_data=validation_generator, validation_steps=validation_generator.n // batch_size)

In [ ]:


In [ ]:


In [ ]: