Plant Disease Detection Using Convolutional Neural Networks with PyTorch
Machine learning, Deep learning, and Artificial intelligence are the Future. We use these technologies in almost every field. In the Farming sector, we can also use this technology for the Preparation of soil, adding fertilizers, sowing of seed, Irrigation, weed protection, harvesting, disease prediction, etc.
Read Full Blog AI In Agriculture.
Overview :
We are using Deep Learning for Plant disease detection based on images of a leaf of a plant. We are using deep learning for this task because here we are working with image data. Deep learning has a Convolution neural network that is used to find features from the leaf of the plant.
Prerequisites :
PyTorch
Convolutional Neural Networks
Learn PyTorch from Here :
(1) Aladdin Person Youtube Playlist
(2) Python Engineer Youtube Playlist
Learn CNN From Here :
(1) Convolutional Neural Networks (CNNs) explained by Deeplizard
(2) Simple Explanation Of Convolutional Neural Network by CodeBasics
Dataset :
In this data-set, 39 different classes of plant leaf and background images are available. The data-set containing 61,486 images. We used six different augmentation techniques for increasing the data-set size. The techniques are image flipping, Gamma correction, noise injection, PCA color augmentation, rotation, and Scaling.
There is a total of 39 Classes that we have to predict using the CNN Model.
Download the Dataset. ( Plant Village Dataset )
Code Implementation :
Import Dependencies:
# General
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt# Torch
import torch
from torchvision import datasets, transforms # datsets , transforms
from torch.utils.data.sampler import SubsetRandomSampler
import torch.nn as nn
import torch.nn.functional as F
from datetime import datetime
Transforms are used for Data Augmentation like cropping the image, resize the image, convert the image to tensor, rotate the image, and many more. Transforms work as a filter for all images. We are using the following code to transform the images.
transform = transforms.Compose(
[transforms.Resize(255), transforms.CenterCrop(224), transforms.ToTensor()]
)
datasets class is used to create or import datasets. In datasets, it has many famous datasets like MNIST, CIFAR-10, CIFAR-100, KMNIST, etc.
Check out all dataset lists here.
We use the dataset for making our own dataset from images and for that we are using the ImageFolder method from datasets.
The folder where I stored all images is named as āDatasetā. We also apply our transform to all images.
dataset = datasets.ImageFolder("Dataset", transform=transform)
Train Test Split :
indices = list(range(len(dataset)))split = int(np.floor(0.85 * len(dataset))) # train_sizevalidation = int(np.floor(0.70 * split)) # validationnp.random.shuffle(indices)train_indices, validation_indices, test_indices = (
indices[:validation],
indices[validation:split],
indices[split:],
)
Here in the above code we first getting indices and then split the data into train , test and validation data. Total 36584 for train , 15679 for validaiton and remaining images for testing.
train_sampler = SubsetRandomSampler(train_indices)
validation_sampler = SubsetRandomSampler(validation_indices)
test_sampler = SubsetRandomSampler(test_indices)
SubsetRandomSampler is used to sample our data. Here we are creating an object of SubsetRandomSampler Object and later we will use this sampler in train data loader and test data loader.
batch_size = 64train_loader = torch.utils.data.DataLoader(
dataset, batch_size=batch_size, sampler=train_sampler
)test_loader = torch.utils.data.DataLoader(
dataset, batch_size=batch_size, sampler=test_sampler
)validation_loader = torch.utils.data.DataLoader(
dataset, batch_size=batch_size, sampler=validation_sampler
)
As we discussed we use train_sampler for train-loader and vice-versa.
Now our dataset is ready for training and testingā¦!!
Model Creation :
We use a convolutional neural network for model creation. We create model layers as mentioned below the image. We also specified filter size for the Conv layer and Pool layer and the shape on each layer.
shape = ( channels , height , width )
In PyTorch shape is not automatically calculated we manually have to take care of shape on each layer. At the First Fully connected layer we have to mention output size as per the shape of the convolutional layer. This calculation is also called Convolutional Arithmetic.
Here is Equation for Convolutional Arithmetic:
Here for this project dilation = 0.
For model code do check out My Github repo here
model = CNN(targets_size) # targets_size = 39
Here we have to classify the images into 39 Categories so thatās why we used categorical cross-entropy as loss and adam optimizer. In the Model, we are using ReLU as activation but for the last layer, we have to use Softmax activation. In PyTorch, we have a cross-entropy loss which is a mixture of softmax and category cross-entropy loss.
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters())
Batch Gradient Descent:
def batch_gd(model, criterion, train_loader, test_laoder, epochs):
train_losses = np.zeros(epochs)
test_losses = np.zeros(epochs)for e in range(epochs):
t0 = datetime.now()
train_loss = []
for inputs, targets in train_loader:
inputs, targets = inputs.to(device), targets.to(device)optimizer.zero_grad()output = model(inputs)loss = criterion(output, targets)train_loss.append(loss.item()) # torch to numpy worldloss.backward()
optimizer.step()train_loss = np.mean(train_loss)validation_loss = []for inputs, targets in validation_loader:inputs, targets = inputs.to(device), targets.to(device)output = model(inputs)loss = criterion(output, targets)validation_loss.append(loss.item()) # torch to numpy worldvalidation_loss = np.mean(validation_loss)train_losses[e] = train_loss
validation_losses[e] = validation_lossdt = datetime.now() - t0print(
f"Epoch : {e+1}/{epochs} Train_loss:{train_loss:.3f} Test_loss:{validation_loss:.3f} Duration:{dt}"
)return train_losses, validation_losses
As you can see above function is used for Batch Gradient Descent. batch_gd() is the function where all the learning happened.
def accuracy(loader):
n_correct = 0
n_total = 0for inputs, targets in loader:
inputs, targets = inputs.to(device), targets.to(device)outputs = model(inputs)_, predictions = torch.max(outputs, 1)n_correct += (predictions == targets).sum().item()
n_total += targets.shape[0]acc = n_correct / n_total
return acctrain_acc = accuracy(train_loader)
test_acc = accuracy(test_loader)
validation_acc = accuracy(validation_loader)
The above function is used for finding the accuracy of the model. It is very simple to understand code. You can check the full code at My Github.
By Using this Current Model we are getting accuracy
87 % on Train data, 84 % On Validation data and 83% on Test data.
For this practical we use test data as completely new data. We were not used test data on any phase it was made only for final testing.
Working of Model :
If you know the working of CNN then You get my point about what I do in this project. This section is for those who donāt understand. Basically, First we Resize every image into 224 x 224. After that this image feed into the Convolutional Neural Network. We feed color image so it has 3 channels RGB. First conv layer we apply 32 filter size or output channels. That means 32 different filters apply to the images and try to find features and after that using 32 features, we create a features map that has channels 32. So from 3 x 224 x 224 it will become 32 x 222 x 222. After that we are applying ReLU activation function to remove non linearity and after that we are applying Batch Normalization to normalize the weights of the neuron. After that this image we feed to the max pool layer which takes only the most relevant features only so that why we get the output image in shape 32 x 112 x 112. After that, we feed this image to the next convolutional layer and its process is the same as mentioned above. At last, we flatten the final max pool layer output and feed to the next linear layer which is also called a fully connected layer, and finally, as a final layer, we predict 39 categories. So as a model output we get tensor 1x39 size. And from that tensor, we take an index of the maximum value in the tensor. That particular index is our main prediction. Thatās how everything works...!!
Hope you will understandā¦šš»š
Flask Web App :
After Creating this Model We create on web application on flask and deployed it on heroku cloud sever.
Coding of flask framework is also available on my github repo here.
Plant-Disease-Detection-AI.Herokuapp.com
Code :
LinkedIn :
Conclusion :
This model is working great without Transfer learning. But I will use transfer learning and many other methods to improve the accuracy of the model.
I hope you enjoyed this project š.
More Blogs and Projects :
Projects :
Blogs :
Final Note :
Thanks for reading! If you enjoyed this article, please hit the clap šbutton as many times as you can. It would mean a lot and encourage me to keep sharing my knowledge. If you like my content follow me on medium I will try to post as many blogs as I can.