Skip to main content
Back
ML Models2025

AgriGuard — Apple Disease Detection CNN

Hamza Zeewaqar · 2025

PythonPyTorchCNNComputer VisionAgriculture

AgriGuard classifies apple leaf diseases — Scab, Black Rot, Cedar Rust, and Healthy — using a custom CNN built from scratch in PyTorch, achieving 99% test accuracy on 1,943 images. Aligned with SDG 2 (Zero Hunger) and SDG 15 (Life on Land).

Tech Stack

LayerTools
LanguagePython 3.10+
FrameworkPyTorch · Torchvision
HardwareNVIDIA RTX 5070 (CUDA 12.x)
MetricsScikit-Learn — precision, recall, F1, confusion matrix
VisualisationMatplotlib

Problem & Approach

Expert plant pathologists are inaccessible to most smallholder farmers. The goal was to build a lightweight, custom CNN — no pretrained weights — that can run on consumer-grade hardware and reliably detect disease from a single leaf photo. The model targets the 4 highest-impact apple categories from the New Plant Diseases Dataset (Kaggle).

1,943Test Images
4Disease Classes
99%Test Accuracy
10Training Epochs

Architecture — PlantNet

Three convolutional blocks progressively double the filter depth (32→64→128), each followed by ReLU and 2×2 max-pooling. A dropout layer (p=0.5) before the final FC layer prevents overfitting on the relatively small dataset.

class PlantNet(nn.Module):
    def __init__(self, num_classes):
        super(PlantNet, self).__init__()
        self.conv1 = nn.Conv2d(3,  32,  kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(32, 64,  kernel_size=3, padding=1)
        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)
        self.pool  = nn.MaxPool2d(2, 2)
        self.fc1   = nn.Linear(128 * 16 * 16, 512)
        self.dropout = nn.Dropout(0.5)
        self.fc2   = nn.Linear(512, num_classes)

    def forward(self, x):
        x = self.pool(torch.relu(self.conv1(x)))  # 128×128 → 64×64
        x = self.pool(torch.relu(self.conv2(x)))  # 64×64  → 32×32
        x = self.pool(torch.relu(self.conv3(x)))  # 32×32  → 16×16
        x = x.view(-1, 128 * 16 * 16)
        x = self.dropout(torch.relu(self.fc1(x)))
        return self.fc2(x)
PlantNet architecture — 3 convolutional blocks into fully connected classifier
PlantNet architecture — 3 convolutional blocks into fully connected classifier

Training Setup

  1. 01Normalize pixel values with ImageNet mean and std
  2. 02Augment with random horizontal flips and 10° rotations
  3. 03Stratified 80/10/10 train/val/test split
  4. 04Train with Adam optimizer — lr 0.001, batch size 32, 10 epochs
  5. 05Evaluate on held-out test set with Scikit-Learn classification report

Results

ClassPrecisionRecallF1-Score
Apple Scab0.980.980.98
Apple Black Rot0.980.990.99
Apple Cedar Rust0.990.990.99
Apple Healthy0.990.990.99
Overall0.990.990.99
Per-class accuracy
Per-class accuracy
Confusion matrix
Confusion matrix
Precision-recall curves
Precision-recall curves