NOTE: This Use Case is not purposed for resource constrained devices.
Insect Classifier¶
Credit: AITS Cainvas Community
Photo by FM ILLUSTRATION on Dribbble
- Model classifies insects among Butterfly, Dragonfly, Grasshoper, Ladybird and Mosquito.
- Dataset contains 3.8k images of insects collected from different websites.
Import Libraries and Fetch Data¶
In [1]:
import tensorflow as tf
import cv2
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt
import os
In [2]:
!wget https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/archive_2.zip
In [3]:
!unzip -qo archive_2.zip
In [4]:
# Directory where images are present
main_dir = 'archive/insects'
num_fldrs = 5
In [5]:
# dictionary of labels
insect_names = {'1':"Butterfly",'2':"Dragonfly",
'3':"Grasshopper",'4':"Ladybird",
'5':"Mosquito"}
Create Dataframe for reference purposes.¶
In [6]:
def getdata(folder_path,num_subfolders):
global insect_names
insects = pd.DataFrame(columns=['image_abs_path','image_labels'])
for label in range(1,num_subfolders+1):
#print("processing for label: {}".format(label))
label_i = folder_path+"/"+insect_names[str(label)]
#read directory
dirs_label_i = os.listdir(label_i)
idx = 0
for image in dirs_label_i:
#create a absolute image path
insect_i = os.path.join(label_i,image)
#print('Absolute path for image no. {} and label {}: {}'\
#.format(idx,label,flower_i))
#fill the dataframe with path and label
insects = insects.append({'image_abs_path':insect_i,
'image_labels':insect_names[str(label)]},
ignore_index=True)
idx += 1
return insects
In [7]:
train = getdata(main_dir,num_fldrs)
Visualise Images¶
In [8]:
# A function to fetch single images based on path given
def get_image(path):
img = cv2.imread(path,0)
plt.imshow(img,cmap='gray')
In [9]:
# a function to fetch n images of any label given e.g. 5 Dragonfly and from which dataframe
def get_n_images(n,df,label):
import warnings
warnings.filterwarnings('ignore')
train = df[df["image_labels"]==label]
print(len(train))
i = 0
m = n/2
plt.figure(figsize=(12, 6))
for path in train['image_abs_path'][0:n]:
plt.subplot(2,m,i+1)
get_image(path)
i += 1
plt.tight_layout()
plt.show()
In [10]:
get_n_images(10,train,"Dragonfly")
Check Proportion of Insects¶
In [11]:
def plotHbar(df,labels):
numbers = []
label = list(labels.values())
for i in label:
numbers.append(len(df[df['image_labels']==i]))
plt.figure(figsize=(5,2))
plt.barh(label,numbers,align='center',color='green',)
plt.title("Label Counts")
plt.show()
In [12]:
plotHbar(train,insect_names)
Build Image Data generator to fetch image directly form main directory¶
In [13]:
def datapreprocessing(main_dir,bsize):
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_gen = ImageDataGenerator(rescale=1.0/255,
validation_split=0.30,
rotation_range=40,
horizontal_flip=True,
fill_mode='nearest')
train_generator = train_gen.flow_from_directory(
directory=main_dir,
target_size=(150,150),
batch_size=bsize,
color_mode="rgb",
shuffle=True,
subset="training",
class_mode='categorical')
valid_generator = train_gen.flow_from_directory(
directory=main_dir,
target_size=(150,150),
batch_size=bsize,
color_mode="rgb",
shuffle=True,
subset="validation",
class_mode='categorical')
return train_generator, valid_generator
In [14]:
# Build train and validation sets
traingen,validgen = datapreprocessing(main_dir,20)
Visualise Images in Generator¶
In [15]:
def visualize_gen(train_generator):
#Visualising Images Processed
plt.figure(figsize=(12, 6))
for i in range(0, 10):
plt.subplot(2, 5, i+1)
for X_batch, Y_batch in train_generator:
image = X_batch[0]
plt.axis("off")
plt.imshow((image*255).astype(np.uint8))
break
plt.tight_layout()
plt.show()
In [16]:
visualize_gen(traingen)
Build Model Architecture¶
In [17]:
def insectclf(input_shape):
from tensorflow import keras as ks
#from tensorflow.keras import regularizers
model = ks.models.Sequential()
#building architecture
#Adding layers
model.add(ks.layers.Conv2D(16,(3,3),
strides=1,
activation="relu",
padding='valid',
name="layer1",
input_shape=input_shape))
model.add(ks.layers.MaxPooling2D(pool_size=4))
model.add(ks.layers.Dropout(0.3))
model.add(ks.layers.Conv2D(32,(3,3),strides=1,padding="valid",activation="relu",name="layer2"))
model.add(ks.layers.MaxPooling2D(pool_size=2))
model.add(ks.layers.Dropout(0.3))
model.add(ks.layers.Conv2D(64,(3,3),strides=1,padding="valid",activation="relu",name="layer3"))
model.add(ks.layers.MaxPooling2D(pool_size=2))
model.add(ks.layers.Dropout(0.3))
model.add(ks.layers.Conv2D(128,(3,3),strides=1,padding="valid",activation="relu",name="layer4"))
model.add(ks.layers.MaxPooling2D(pool_size=2))
model.add(ks.layers.Dropout(0.3))
model.add(ks.layers.Flatten())
model.add(ks.layers.Dense(128,activation="relu",
name="layer7"))
model.add(ks.layers.Dropout(0.5))
model.add(ks.layers.Dense(128,activation="relu",
name="layer8"))
model.add(ks.layers.Dropout(0.5))
model.add(ks.layers.Dense(5,activation="softmax",
name="output"))#20 classes
model.summary()
return model
Build Model Compiler¶
In [18]:
def compiler(model,train_generator,valid_generator,epchs,bsize,lr=0.0001):
from tensorflow import keras as ks
callbck = ks.callbacks.EarlyStopping(monitor='val_loss',patience=20,
verbose=2,restore_best_weights=True)
#red_lr= ReduceLROnPlateau(monitor='val_acc',patience=3,verbose=1,factor=0.1)
opt = ks.optimizers.Adam(learning_rate=lr)
model.compile(loss="categorical_crossentropy",
optimizer=opt,
metrics=["accuracy"])
history = model.fit(train_generator,
epochs=epchs,
callbacks=[callbck],
validation_data=valid_generator,
verbose = 1,
steps_per_epoch = train_generator.n//bsize,
validation_steps = valid_generator.n//bsize
)
#Visualise curves
plt.plot(history.history['accuracy'], label='train_acc')
plt.plot(history.history['val_accuracy'], label='valid_acc')
plt.title('lrate='+str(lr), pad=-50)
plt.legend()
plt.grid(True)
return model,history
In [19]:
# Get input shape
input_shape = traingen.image_shape
input_shape
Out[19]:
Fit and Evaluate¶
In [20]:
model01 = insectclf(input_shape)
In [21]:
model01 = compiler(model01,traingen,validgen,100,bsize=32,lr=0.001)
Get Prediction¶
In [22]:
def get_predictions(n):
image1= validgen[0][0][n]
#print(image1.shape)
plt.imshow(image1)
input_arr = tf.keras.preprocessing.image.img_to_array(validgen[0][0][n])
input_arr = np.array([input_arr]) # Convert single image to a batch.
predictions = model01[0].predict_classes(input_arr)
#our dictionary starts from 1 whereas model has classes from 0.
return insect_names[str(predictions[0]+1)]
In [23]:
get_predictions(13)
Out[23]:
Save Model¶
In [24]:
model01[0].save(filepath='Dataset/saved_models/Model01.tf',save_format="tf")
DeepCC¶
In [53]:
!deepC 'Dataset/saved_models/Model01.tf'
In [ ]: