Potato Disease Classification Using Neural Networks

Santhosh Kakarla
3 min readJan 2, 2023

--

Aim of the project is to create a Neural Network model which takes potato plant leaf image as an input and predicts whether the potato is healthy or diseased(Early Blight or Late Blight).

Dataset can be downloaded from Kaggle https://www.kaggle.com/datasets/emmarex/plantdisease. Download only the folders starting with potato and put all the folders in a Folder, I kept in plantVillage Folder.

Now, let’s start the coding part.

First, we need to import the Libraries required

import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import models, layers

We can directly access the image dataset using preprocessing.image_dataset_from_directory from keras library

dataset=tf.keras.preprocessing.image_dataset_from_directory(
'plantvillage',
shuffle=True,
image_size=(256, 256),
batch_size= 32
)

Here, ‘plantVillage’ is relative path for the folder containing all the image class folders. We gave (256, 256) as Image size, no matter what is the size, it resizes into (256, 256). We are batching the images to avoid bottlenecks, here every batch contains 32 images.

Now, let’s see our class names

class_names=dataset.class_names
class_names

Now, let’s see some images in a batch and their class names

plt.figure(figsize=(10, 10))
for image_batch, label_batch in dataset.take(1):
for i in range(12):
ax=plt.subplot(3, 4, i+1)
plt.imshow(image_batch[i].numpy().astype('uint8'))
plt.title(class_names[label_batch[i]])
plt.axis('off')

Now, let’s divide the dataset as 80% into training dataset, 10% validation and remaining 10% into testing dataset

train_ds=dataset.take(int(0.8*len(dataset)))
valid_ds=dataset.skip(int(0.8*len(dataset))).take(int(0.1*len(dataset)))
test_ds=dataset.skip(int(0.8*len(dataset))).skip(int(0.1*len(dataset)))

Now, we will configure the dataset for training the model

train_ds= train_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
valid_ds=valid_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)
test_ds=test_ds.cache().shuffle(1000).prefetch(buffer_size=tf.data.AUTOTUNE)

It’s time to create the model. We will start with resize and rescale and data augmentation which helps model to better generalize., followed by CNN layers and Dense layers. Our model is shown below

resize_and_rescale=tf.keras.Sequential([
layers.experimental.preprocessing.Resizing(IMAGE_SIZE, IMAGE_SIZE),
layers.experimental.preprocessing.Rescaling(1.0/255)
])
data_augumentation= tf.keras.Sequential([
layers.experimental.preprocessing.RandomFlip('horizontal_and_vertical'),
layers.experimental.preprocessing.RandomRotation(0.2)

])
input_shape=(BATCH_SIZE, IMAGE_SIZE, IMAGE_SIZE, 3)
model=models.Sequential([
resize_and_rescale,
data_augumentation,
layers.Conv2D(32, (3,3), activation='relu', input_shape=input_shape),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64, (3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64, (3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64, (3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64, (3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Conv2D(64, (3,3), activation='relu'),
layers.MaxPooling2D((2,2)),
layers.Flatten(),
layers.Dense(64, activation='relu'),
layers.Dense(3,activation='softmax')
])
model.build(input_shape=input_shape)

We need to compile the model and fit the model with data. For compiling, we will have Adam optimizer, Sparse Categorical cross entropy as loss function since our class names/labels are integer encoded rather than one hot encoded and accuracy metrics.

model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False), metrics=['accuracy'])

It’s time to fit the data. We will train for 50 epochs.

history= model.fit(train_ds, epochs=50, batch_size=BATCH_SIZE, validation_data=valid_ds)

After training for 50 epochs, I achieved an accuracy of 98.96% for training accuracy and 97.92% for validation accuracy.

We need to test our model on unseen data.

for image_batch, label_batch in test_ds.take(1):
first_image=image_batch[0].numpy().astype('uint8')
first_label= label_batch[0].numpy()
print('The first image to be predicted')
print(f'The label is {class_names[first_label]}')
plt.imshow(first_image)
batch_prediction=model.predict(image_batch)
print(f'The predicted label is: {class_names[np.argmax(batch_prediction[0])]}')

By following steps, you can train a model. You can access the full code here.

Credits: Codebasics

--

--