A Self-Supervised Learning (SSL) foundation model for plant disease classification, built with SimCLR and a ResNet-18 backbone. The model is pre-trained on unlabelled plant images and then fine-tuned for 38-class plant disease classification. GradCAM explainability is integrated for inference visualisation.
- Overview
- Project Structure
- Pipeline
- Installation
- Data Format
- Usage
- Model Architecture
- Fine-tuning Strategies
- Metrics
- Output Files
- CI/CD
- Contributing
- License
This project implements a two-stage transfer learning pipeline:
- SSL Pre-training (SimCLR) β trains an encoder on unlabelled plant images using contrastive learning. No labels required.
- Fine-tuning β loads the pre-trained encoder and trains a classification head on labelled plant disease images (38 classes).
- GradCAM Inference β generates visual explanations highlighting which leaf regions influenced each prediction.
| Property | SSL Approach |
|---|---|
| Labels needed for pre-training | None |
| Transfer to new tasks | Add a small classification head |
| Data efficiency at fine-tune | High β few labels needed |
| Explainability | GradCAM heatmaps per prediction |
Plant-disease-classification-FM/
β
βββ model.py # Encoder (ResNet-18) + ProjectionHead + SimCLRModel
βββ dataset.py # SSL contrastive dataset + augmentation pipeline
βββ loss.py # NT-Xent contrastive loss
βββ train.py # SSL pre-training loop + checkpoint saving
βββ finetune.py # Fine-tuning classifier + full metrics reporting
βββ gradcam_inference.py # GradCAM inference + visualisation
β
βββ requirements.txt # Python dependencies
βββ .gitignore
βββ .gitattributes
β
βββ data/ # (not committed β see .gitignore)
β βββ train/
β β βββ Apple___Apple_scab/
β β βββ ...
β βββ val/
β βββ Apple___Apple_scab/
β βββ ...
β
βββ checkpoints/ # SSL pre-training checkpoints (not committed)
β βββ foundation_encoder.pt
β βββ checkpoint_epoch_*.pt
β
βββ finetune_checkpoints/ # Fine-tuning outputs (not committed)
β βββ best_model.pt
β βββ final_model.pt
β βββ metrics_log.csv
β βββ confusion_matrix_*.png
β
βββ xai/ # GradCAM outputs (not committed)
βββ <ClassName>/
β βββ original.jpg
β βββ gradcam_heatmap.png
β βββ gradcam_overlay.png
β βββ gradcam_panel.png
βββ summary_grid.png
βββ confidence_report.png
Unlabelled plant images
β
βΌ
βββββββββββββββ
β SSL Pre- β train.py β checkpoints/foundation_encoder.pt
β training β (SimCLR)
βββββββββββββββ
β
βΌ
βββββββββββββββ
β Fine-tuning β finetune.py β finetune_checkpoints/best_model.pt
β Classifier β (38 classes)
βββββββββββββββ
β
βΌ
βββββββββββββββ
β GradCAM β gradcam_ β xai/
β Inference β inference.py
βββββββββββββββ
- Python 3.9+
- PyTorch 2.0+
- CUDA-capable GPU recommended (CPU works but is slow for training)
# Clone the repository
git clone https://github.com/gadhane/Plant-disease-classification-FM.git
cd Plant-disease-classification-FM
# Create and activate a virtual environment
python -m venv venv
source venv/bin/activate # Linux / macOS
venv\Scripts\activate # Windows
# Install dependencies
pip install -r requirements.txtdata/
train/
Apple___Apple_scab/
Apple___Black_rot/
Apple___Cedar_apple_rust/
Apple___healthy/
Tomato___Early_blight/
Tomato___Late_blight/
Tomato___healthy/
... (38 classes total)
val/
Apple___Apple_scab/
...
Train the foundation model on unlabelled images (labels/folder names are ignored):
python train.py \
--data_dir data \
--epochs 100 \
--batch_size 64 \
--image_size 224 \
--embed_dim 256 \
--temperature 0.5 \
--save_dir checkpointsKey arguments:
| Argument | Default | Description |
|---|---|---|
--data_dir |
data |
Root folder with plant images |
--epochs |
100 |
Training epochs |
--batch_size |
64 |
Larger = more negatives = better SSL |
--embed_dim |
256 |
Encoder output dimension |
--temperature |
0.5 |
NT-Xent loss temperature |
--resume |
None |
Path to checkpoint to resume from |
Outputs:
checkpoints/
foundation_encoder.pt β use this for fine-tuning
checkpoint_epoch_010.pt
checkpoint_epoch_020.pt
...
Fine-tune the foundation encoder on labelled plant disease images:
python finetune.py \
--data_dir data \
--checkpoint_path checkpoints/foundation_encoder.pt \
--strategy partial \
--epochs 30 \
--batch_size 32 \
--lr 1e-3Key arguments:
| Argument | Default | Description |
|---|---|---|
--checkpoint_path |
checkpoints/foundation_encoder.pt |
Pre-trained encoder |
--strategy |
partial |
frozen / partial / full |
--epochs |
30 |
Fine-tuning epochs |
--num_classes |
38 |
Number of disease classes |
--lr |
1e-3 |
Learning rate |
Run inference on one image per class and generate GradCAM visualisations:
python gradcam_inference.py \
--model_path finetune_checkpoints/best_model.pt \
--val_dir data/val \
--xai_dir xai \
--seed 42Input (B, 3, 224, 224)
β
ββββββ΄βββββ
β Encoder β ResNet-18 backbone (layer1βlayer4βAvgPool)
β β + Linear(512 β 256) + BatchNorm1d
ββββββ¬βββββ
β (B, 256) β saved as foundation_encoder.pt
ββββββ΄βββββββββ
β Projection β Linear(256β512) β BN β ReLU
β Head β Linear(512β512) β BN β ReLU
β [discarded]β Linear(512β128)
ββββββ¬βββββββββ
β (B, 128) L2-normalised
βΌ
NT-Xent Loss
Input (B, 3, 224, 224)
β
ββββββ΄βββββ
β Encoder β Loaded from foundation_encoder.pt
ββββββ¬βββββ
β (B, 256)
ββββββ΄βββββββββββ
β Classifier β Linear(256β512) β BN β ReLU β Dropout(0.3)
β Head β Linear(512β256) β BN β ReLU β Dropout(0.15)
ββββββ¬βββββββββββ Linear(256β38)
β
CrossEntropyLoss (label_smoothing=0.1)
| Strategy | Trainable Params | When to Use |
|---|---|---|
frozen |
Head only | Few labels, fast training |
partial |
ResNet layer4 + embedding fc + head |
Default β best balance |
full |
Entire encoder + head | Lots of labelled data |
checkpoints/ # SSL pre-training
foundation_encoder.pt β encoder weights for fine-tuning
finetune_checkpoints/ # Fine-tuning
best_model.pt β best validation accuracy
final_model.pt β last epoch
metrics_log.csv β all metrics, all epochs
confusion_matrix_epoch_030.png β normalised heatmap
xai/ # GradCAM
<ClassName>/
original.jpg
gradcam_heatmap.png
gradcam_overlay.png
gradcam_panel.png β Original | Heatmap | Overlay
summary_grid.png β all 38 classes in one image
confidence_report.png β per-class confidence bar chart
This project uses GitHub Actions for automated testing and linting.
| Workflow | Trigger | Description |
|---|---|---|
ci.yml |
Push / PR to main, develop |
Lint + unit tests |
codeql.yml |
Push / PR + weekly schedule | Security analysis |
# Lint
flake8 . --max-line-length=120
# Tests
pytest tests/ -v- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Commit your changes:
git commit -m "feat: add my feature" - Push to the branch:
git push origin feature/my-feature - Open a Pull Request
This project is licensed under the MIT License. See LICENSE for details.