Skip to content

Instantly share code, notes, and snippets.

@zckkte
Created August 28, 2019 13:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zckkte/b2465e36295f024356730e0d67b034d6 to your computer and use it in GitHub Desktop.
Save zckkte/b2465e36295f024356730e0d67b034d6 to your computer and use it in GitHub Desktop.
Cat vs dog image classifier
import os
import math
import random
import shutil
import numpy as np
import matplotlib.pyplot as plt
from time import time
from functional import seq
from collections import namedtuple
import keras
from keras import layers
from keras import optimizers
from keras.regularizers import l1
from keras.preprocessing.image import ImageDataGenerator
EPOCHS = 80
BATCH_SIZE = 64
IMG_HEIGHT, IMG_WIDTH=(150, 150)
ClassSplit = namedtuple('ClassSplit', 'class_label name split_label')
CopyVector = namedtuple('CopyVector', 'src dest')
def partition_on_ratio(entries, ratio):
test_ratio, val_ratio, train_ratio = ratio
split_train_index = int(train_ratio * len(entries))
split_val_index = split_train_index + int(val_ratio * len(entries))
files_train = entries[:split_train_index]
files_val = entries[split_train_index:split_val_index]
files_test = entries[split_val_index:]
return ('test', files_test), ('validation', files_val), ('training', files_train)
def class_split_to_copy_vec(base, class_split):
src = os.path.join(base, '{}'.format(class_split.name))
dest = os.path.join(base, '{}/{}/{}'.format(class_split.split_label, class_split.class_label, class_split.name))
return CopyVector(src=src, dest=dest)
def copy_makedir(copy_vector):
dest_dir = os.path.dirname(copy_vector.dest)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
print(copy_vector.src)
print(copy_vector.dest)
shutil.copyfile(copy_vector.src, copy_vector.dest)
def split_files(src='dataset', ratio=(0.15, 0.15, 0.70)):
base = os.path.join(os.getcwd(), src)
test, validation, training = partition_on_ratio(os.listdir(base), ratio)
get_label = lambda x : 'cats' if 'cat' in x else 'dogs'
copy_vectors = seq([test, validation, training]) \
.flat_map(lambda r : seq(r[1]).map(lambda x : ClassSplit(name=x, split_label=r[0], class_label=get_label(x)))) \
.map(lambda x : class_split_to_copy_vec(base, x))
copy_vectors.for_each(copy_makedir)
def construct_model():
return keras.Sequential([
layers.Conv2D(32, kernel_size=(3, 3), activation='relu',padding='same',
input_shape=(IMG_HEIGHT, IMG_WIDTH, 3)),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Conv2D(64, kernel_size=(3, 3), activation='relu',padding='same' ),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Conv2D(128, kernel_size=(3, 3), activation='relu',padding='same'),
layers.MaxPooling2D(pool_size=(2, 2)),
layers.Flatten(),
# feed-forward classifier
layers.Dense(256, activation='relu'),
layers.Dropout(0.5),
layers.Dense(1, activation='sigmoid')
])
def summarise_plot(res):
epochs = range(0, len(res.history['val_acc']))
#plot loss
plt.subplot(211)
plt.plot(res.history['loss'], color='blue',marker='o', label='Training Loss')
plt.plot(res.history['val_loss'], color='red',marker='o', label='Validation Loss')
plt.xlabel("Epochs")
plt.ylabel("Loss")
plt.legend()
# plot accuracy
plt.subplot(212)
plt.plot(epochs, res.history['acc'], marker='o', color='red', label="Training Accuracy")
plt.plot(epochs, res.history['val_acc'], marker='o', color='blue', label="Validation Accuracy")
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()
# save plot to file
plt.savefig('pet_class_plot_{}.png'.format(time()))
plt.close()
def main():
model = construct_model()
model.compile(optimizer=optimizers.Adam(), loss='binary_crossentropy', metrics=['accuracy'])
model.summary()
train_data_gen = \
ImageDataGenerator(rotation_range=40,
width_shift_range=0.1,
height_shift_range=0.1,
rescale=1.0/255,
shear_range=0.1,
zoom_range=0.1,
horizontal_flip=True,
fill_mode='nearest')
test_data_gen = ImageDataGenerator(rescale=1.0/255)
train_iter = train_data_gen.flow_from_directory('dataset/training/', shuffle=True,
class_mode='binary', batch_size=BATCH_SIZE, target_size=(IMG_HEIGHT, IMG_WIDTH))
validation_iter = test_data_gen.flow_from_directory('dataset/validation/', shuffle=True,
class_mode='binary', batch_size=BATCH_SIZE, target_size=(IMG_HEIGHT, IMG_WIDTH))
test_iter = test_data_gen.flow_from_directory('dataset/test/', shuffle=True,
class_mode='binary', batch_size=BATCH_SIZE, target_size=(IMG_HEIGHT, IMG_WIDTH))
res = model.fit_generator(train_iter, steps_per_epoch=len(train_iter),
validation_data=validation_iter, validation_steps=len(validation_iter),
epochs=EPOCHS, verbose=1, workers=4)
loss, acc = model.evaluate_generator(test_iter, steps=len(test_iter), verbose=0)
print('Test: [ loss = {}; accuracy = {} ]'.format(loss, acc))
model.save('pet_classifier_ccn.h5')
summarise_plot(res)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment