Sheep breed classification¶
Credit: AITS Cainvas Community
Photo by Petter Pentilä on Dribbble
Identify the breed of the sheep in the image using neural networks.
In [1]:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix
from keras import layers, optimizers, models, preprocessing, losses, callbacks, Input, Model, applications
import os
import random
from PIL import Image
In [2]:
!wget https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/SheepFaceImages.zip
!unzip -qo SheepFaceImages.zip
!rm SheepFaceImages.zip
In [3]:
# Loading the dataset
path = 'SheepFaceImages'
train_df = preprocessing.image_dataset_from_directory(path, label_mode = 'categorical', validation_split = 0.2, subset = 'training', seed = 113)
test_df = preprocessing.image_dataset_from_directory(path, label_mode = 'categorical', validation_split = 0.2, subset = 'validation', seed = 113)
In [4]:
# How many samples in each class
for x in os.listdir(path):
print(x, ' - ', len(os.listdir(path + '/' + x)))
This is a balanced dataset!
In [5]:
# Looking into the class labels
class_names = train_df.class_names
print("Train class names: ", train_df.class_names)
print("Test class names: ", test_df.class_names)
Visualization¶
In [6]:
num_samples = 4 # the number of samples to be displayed in each class
for x in class_names:
plt.figure(figsize=(20, 20))
filenames = os.listdir(path + '/' + x)
for i in range(num_samples):
ax = plt.subplot(1, num_samples, i + 1)
img = Image.open(path +'/' + x + '/' + filenames[i])
plt.imshow(img)
plt.title(x)
plt.axis("off")
In [7]:
# Normalizing the pixel values for faster convergence
normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)
train_df = train_df.map(lambda x, y: (normalization_layer(x), y))
test_df = test_df.map(lambda x, y: (normalization_layer(x), y))
The model¶
In [8]:
model = models.Sequential([
layers.Conv2D(8, 2, activation='relu', input_shape=(256,256,3)),
layers.Conv2D(16, 2, activation='relu'),
layers.MaxPool2D(pool_size=(2, 2)),
layers.Conv2D(16, 2, activation='relu'),
layers.Conv2D(32, 2, activation='relu'),
layers.MaxPool2D(pool_size=(2, 2)),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(32, activation='relu'),
layers.Dense(len(class_names), activation='softmax')
])
cb = [callbacks.EarlyStopping(monitor = 'val_loss', patience = 5, restore_best_weights = True)]
In [9]:
model.compile(loss=losses.CategoricalCrossentropy(), optimizer=optimizers.Adam(0.0001), metrics=['accuracy'])
history = model.fit(train_df, validation_data = test_df, epochs=32, callbacks = cb)
In [10]:
model.compile(loss=losses.CategoricalCrossentropy(), optimizer=optimizers.Adam(0.00001), metrics=['accuracy'])
history1 = model.fit(train_df, validation_data = test_df, epochs=32, callbacks = cb)
In [11]:
model.evaluate(test_df)
Out[11]:
In [12]:
Xtest = []
ytest = []
for x in test_df.enumerate():
for y in x[1][0]:
Xtest.append(np.array(y).tolist())
ytest.extend(np.array(x[1][1]).tolist())
len(ytest), len(Xtest)
Out[12]:
In [13]:
cm = confusion_matrix(np.argmax(ytest, axis = 1), np.argmax(model.predict(Xtest), axis = 1))
cm = cm.astype('int') / cm.sum(axis=1)[:, np.newaxis]
fig = plt.figure(figsize = (10, 10))
ax = fig.add_subplot(111)
for i in range(cm.shape[1]):
for j in range(cm.shape[0]):
if cm[i,j] > 0.8:
clr = "white"
else:
clr = "black"
ax.text(j, i, format(cm[i, j], '.2f'), horizontalalignment="center", color=clr)
_ = ax.imshow(cm, cmap=plt.cm.Blues)
ax.set_xticks(range(len(class_names)))
ax.set_yticks(range(len(class_names)))
ax.set_xticklabels(class_names, rotation = 90)
ax.set_yticklabels(class_names)
plt.xlabel('Predicted')
plt.ylabel('True')
plt.show()
In [14]:
del Xtest, ytest
Plotting the metrics¶
In [15]:
def plot(history1, history2, variable1, variable2):
# combining metrics from both trainings
var1_history = history1[variable1]
var1_history.extend(history2[variable1])
var2_history = history1[variable2]
var2_history.extend(history2[variable2])
# plotting them
plt.plot(range(len(var1_history)), var1_history)
plt.plot(range(len(var2_history)), var2_history)
plt.legend([variable1, variable2])
plt.title(variable1)
In [16]:
plot(history.history, history1.history, "accuracy", 'val_accuracy')
In [17]:
plot(history.history, history1.history, "loss", 'val_loss')
Prediction¶
In [18]:
# pick random test data sample from one batch
x = random.randint(0, 32 - 1)
for i in test_df.as_numpy_iterator():
img, label = i
plt.axis('off') # remove axes
plt.imshow(img[x]) # shape from (32, 256, 256, 3) --> (256, 256, 3)
output = model.predict(np.expand_dims(img[x],0))[0] # getting output; input shape (256, 256, 3) --> (1, 256, 256, 3)
pred = np.argmax(output)
print("Predicted: ", class_names[pred]) # Picking the label from class_names base don the model output
print("Probability: ", output[pred])
print("\nTrue: ", class_names[np.argmax(label[x])])
break
deepC¶
In [19]:
model.save('sheep.h5')
!deepCC sheep.h5
In [20]:
# pick random test data sample from one batch
x = random.randint(0, 32 - 1) # batch size is 32
for i in test_df.as_numpy_iterator():
img, label = i
plt.axis('off') # remove axes
plt.imshow(img[x]) # shape from (32, 256, 256, 3) --> (256, 256, 3)
np.savetxt('sample.data', (img[x]).flatten()) # xth sample into text file
print("True: ", class_names[np.argmax(label[x])])
print()
break
# run exe with input
!sheep_deepC/sheep.exe sample.data
# show predicted output
nn_out = np.loadtxt('deepSea_result_1.out')
pred = np.argmax(nn_out)
print("\nPredicted: ", class_names[pred]) # Picking the label from class_names base don the model output
print("Probability: ", nn_out[pred])