Cross-Dataset Plant Disease Classification Under Field Conditions: Reproducible Unsupervised Domain Adaptation and Pareto-Guided Model Selection
Authors/Creators
Contributors
Researcher (2):
Description
Plant Swarm is a reproducible research stack for transfer-aware plant disease detection and classification. It combines curated dataset loaders, Ultralytics YOLO detection wrappers, TIMM-based classifiers, and mixed-variable multi-objective swarm search so that Pareto-optimal configurations can be surfaced for both laboratory and in-field imagery.
Overview
The framework targets experiments where PlantDoc provides heterogeneous web imagery for supervised training and FieldPlant contributes expert-annotated, in-field images for transfer evaluation. Mixed-variable Particle Swarm Optimisation (PSO/MOPSO) explores hyperparameters, preprocessing switches (CLAHE, Retinex, HSV jitter), and model families (YOLOv8/YOLOv8s, ResNet, EfficientNet) while respecting latency and size constraints.
Methodology
Data ingestion & preprocessing
Deterministic dataset recipes in configs/dataset/plantdoc.yaml and configs/dataset/fieldplant.yaml define folder layouts, splits, augmentations, and Albumentations equivalents so cross-validation runs are reproducible. PlantDoc operates in folder-labelled classification mode, whereas FieldPlant accepts a _classes.csv annotation file with multi-label columns. The optional configs/dataset/cross.yaml trains on PlantDoc while reserving FieldPlant for evaluation-only transfer.
Label spaces differ across benchmarks; configs/labels/fieldplant_to_plantdoc.json records a mapping for collapsing FieldPlant labels into PlantDoc’s taxonomy when needed. During ingestion the loaders surface deterministic 80/10/10 splits (configurable via split_ratios) and honour environment overrides (FIELDPLANT_PATH).
Model families
Classification uses TIMM backbones through plantswarm/models/cls_timm.py with linear heads for efficient fine-tuning or frozen-feature evaluation. Detection experiments rely on Ultralytics YOLO wrappers in plantswarm/models/det_yolo.py and the training helper in plantswarm/training/det_loop.py so YOLOv8 variants can be called programmatically inside the search loop.
Optimisation strategy
The plantswarm/search/ package implements a hierarchy of swarm optimisers:
pso_base.pydefines particles, velocity updates, and convergence utilities for continuous search.mopso.pyandpso_ndwpso.pyextend this base to multi-objective settings that preserve non-dominated archives.qd_mapelites.pyadds quality-diversity (QD) archiving so distinct high-performing solutions are retained alongside the Pareto front.
Continuous hyperparameters (learning rate, HSV jitter) and discrete switches (model family, CLAHE variants) are encoded jointly through plantswarm/search/spaces.py, allowing mixed-variable exploration inside each particle vector.
Multi-objective search setup
Search configuration files describe which objectives and design variables are active. For example, configs/search/mopso_transfer.yaml targets detection transfer with the mixed space defined in configs/space/joint.yaml:
| Objective key | Description | Source |
|---|---|---|
mAP_in |
PlantDoc validation mean Average Precision | Ultralytics evaluation inside each YOLO run |
mAP_xfer |
FieldPlant evaluation mAP using the same checkpoint | --external-test fieldplant evaluation hooks |
latency_ms |
Median inference latency on the evaluation device | Timing wrapper inside the evaluator |
params_M |
Total learnable parameters in millions | Model summary from TIMM/Ultralytics |
Mixed-variable search spaces combine continuous and categorical descriptors. In configs/space/joint.yaml the swarm jointly tunes learning rate bounds and HSV augmentation intensity alongside discrete toggles for the YOLO variant and CLAHE grid size (off, grid4, grid8). Alternative spaces such as configs/space/cls.yaml restrict the search to classification-only backbones, while configs/space/preproc.yaml isolates preprocessing ablations.
Pareto archiving & quality diversity
MOPSO maintains an external archive of non-dominated solutions. Each particle’s objective vector is compared against the archive; solutions with worse accuracy or higher latency are discarded so the Pareto frontier remains compact. When the archive becomes dense, crowding-distance pruning is applied to preserve coverage across the trade-off surface. The optional MOPSO_QD mode (see configs/search/qd_mopso.yaml) hybridises Pareto selection with MAP-Elites-style bins from plantswarm/search/qd_mapelites.py, ensuring that rare but practically valuable configurations (e.g., ultra-low latency) stay discoverable for deployment studies.
Training & evaluation workflow
Classification branch
The CLI supports deterministic classification training with TIMM backbones, Albumentations augmentation, and optional cross-dataset evaluation:
# Train on PlantDoc and evaluate its validation split plantswarm train --dataset plantdoc --epochs 20 --ckpt runs/plantdoc.pt # Cross-dataset evaluation using FieldPlant without fine-tuning plantswarm eval runs/plantdoc.pt fieldplant --split test # Joint configuration: train on PlantDoc, validate on FieldPlant during training plantswarm train --dataset plantdoc --epochs 20 \ --external-test fieldplant --ckpt runs/plantdoc_fieldplant.pt
Hyperparameters (--lr, --weight-decay, cosine scheduling) inherit defaults from the dataset YAMLs and can be overridden per run. Albumentations pipelines in the YAML files are activated automatically; --no-albumentations falls back to torchvision-only augmentations for ablation studies.
Detection branch
Ultralytics models plug into the same infrastructure via the dedicated wrappers:
# Minimal YOLOv8n training on a YOLO-format dataset definition
python - <<'PY'
from pathlib import Path
from plantswarm.models.det_yolo import create_model
from plantswarm.training import det_loop
model = create_model(name="yolov8n", num_classes=15, pretrained=True)
det_loop.train(model, data=Path("data/fieldplant/yolo.yaml"), epochs=50, imgsz=640,
project="runs/det", name="fieldplant_yolov8n")
# Evaluate the resulting checkpoint on PlantDoc-style export
metrics = model.val(data="data/plantdoc/yolo.yaml", imgsz=640)
print(metrics.results_dict)
PY
The dataset argument accepts any Ultralytics-compatible YAML, enabling PlantDoc or FieldPlant splits exported to bounding-box format. During multi-objective search these wrappers run inside the evaluator so that mAP, latency, and parameter counts are collected consistently. Detection metrics contribute to the same Pareto archive (mAP_in, mAP_xfer) alongside resource objectives, allowing direct comparison with classification baselines during joint search experiments.
Domain adaptation recipe
Unsupervised domain adaptation (UDA) can be invoked directly from the CLI. PlantDoc remains the labelled source dataset while FieldPlant images provide the unlabeled target domain:
plantswarm train --dataset plantdoc --epochs 15 --uda \ --uda-method pseudo --uda-threshold 0.6 --uda-epochs 5 --uda-lr 1e-4 \ --external-test fieldplant --ckpt runs/uda_pseudo.pt
The helper script benchmarks/uda_sweep.py automates sweeps over --uda-threshold, --uda-epochs, --uda-lr, and --uda-method (pseudo-labels, entropy minimisation, DANN) to profile sensitivity. It now exposes the supervised training epochs, optional dataset size cap, and pretrained toggle as CLI arguments so the default invocation runs a publication-grade sweep:
python benchmarks/uda_sweep.py --train-epochs 20 --uda-epochs 10 15 --uda-lrs 3e-4 1e-4
Results are written to runs/uda_sweep_results.json for tables and plots. Pass --dataset-size 2 --train-epochs 1 --no-pretrained to reproduce the lightweight smoke test used in CI.
Swarm sweep for hyperparameter refinement
Once supervised and UDA baselines are in place, run the built-in particle swarm helper to explore a handful of learning-rate, weight-decay, and augmentation knobs without writing a custom script:
plantswarm swarm \ --dataset plantdoc \ --iters 15 \ --ckpt runs/swarm/plantdoc_swarm.pt \ --verbose
The command maintains a small population of particles, iteratively updates them against PlantDoc validation accuracy, and writes three artefacts next to the provided checkpoint path:
plantdoc_swarm.pt– validation-best weights for the best-performing particle.plantdoc_swarm.sweep.csv– iteration-by-iteration metrics for every particle.plantdoc_swarm.params.json– hyperparameters associated with the best checkpoint.
Store swarm results in dedicated subdirectories (as shown above with runs/swarm/) so their metadata files do not collide with other checkpoints. Use the CSV/JSON outputs to compare against the UDA runs and decide which configurations should seed the more advanced search scripts under configs/search/*.yaml.
Interpretability & artifacts
Every run captures deterministic splits, metric logs, and checkpoints under runs/. Search executions emit per-particle summaries including metric vectors and configuration dictionaries, enabling Pareto-front visualisation. Optional confident-learning passes flag likely label issues before optimisation, while exported YOLO validation visualisations and Grad-CAM overlays (produced through the evaluation helpers) support qualitative analyses for paper figures.
Reproduction checklist
- Sync datasets – Download PlantDoc and FieldPlant, arrange them according to
configs/dataset/*.yamlexpectations, and confirm_classes.csvaligns withconfigs/labels/fieldplant_to_plantdoc.jsonwhen running transfer experiments. - Baseline training – Reproduce the classification baselines with
plantswarm trainusing the dataset configs above. Export accuracy/F1 tables for both in-domain and cross-domain splits. - Domain adaptation sweep – Execute
benchmarks/uda_sweep.pywith full-dataset defaults (or adjusted arguments for your hardware budget) to select UDA hyperparameters. Recordruns/uda_sweep_results.jsonfor supplementary materials. - Swarm sweep – Run
plantswarm swarmafter locking in supervised/UDA baselines to capture quick PSO refinements. Archive the.pt,.sweep.csv, and.params.jsonartefacts under a dedicated directory such asruns/swarm/. - Search configuration – Choose a search template from
configs/search/*.yamland adjust objective weights or iteration counts. Modify the design variables throughconfigs/space/*.yamlif additional preprocessing toggles are required. - Launch PSO/MOPSO/QD runs – Follow the commands in docs/search.md to execute classification-only, detection-only, or joint searches. Archive the emitted Pareto fronts and configuration JSON for reproducibility.
- Report artefacts – Collect qualitative figures (Grad-CAM, YOLO detection overlays), confident-learning audit reports, and metric summaries to accompany paper-ready documentation.
Documentation & support
- User guide – docs/user_guide.md covers dataset preparation, CLI walkthroughs, and troubleshooting tips.
- Dataset notes – docs/datasets.md expands on data layouts, augmentation policies, and validation splits.
- Search methodology – docs/search.md details the PSO/MOPSO/QD implementations, configuration knobs, and execution recipes for the optimisation stack.
- Full documentation site – Visit docs/index.md (rendered via MkDocs) for roadmaps, CLI references, and planning spreadsheets.
Ready-made commands, YAML templates, and detailed diagrams are designed so you can cite this repository in academic work and reproduce cross-dataset optimisation studies out of the box.