Start simple, measure everything
Deterministic splits, a frozen MobileNetV2 head, logging from day one: 0.9613 accuracy and 0.9501 F1 on PlantVillage.
A crop disease classifier covering 38 classes, trained on clean lab images, collapses on messy field photos: 0.95 F1 in the lab against 0.11 in the field. Twelve sprints of ablations across mixed domain training, backbone sweeps, routing and segmentation converged on one ResNet-50 recipe that holds 0.95 lab F1 with 0.65 field F1.
Every claim ships with a number. Checkpoints only survive if they beat what came before on both worlds.
Deterministic splits, a frozen MobileNetV2 head, logging from day one: 0.9613 accuracy and 0.9501 F1 on PlantVillage.
Flips, rotation, brightness, blur and JPEG noise on the train set only; a run ships only if it beats the baseline.
The baseline managed 0.11 F1 on PlantDoc. Fine tuning recovered 0.51 but forgot PlantVillage, dropping it to 0.31. The gap became the thesis.
Joint PlantVillage + PlantDoc batches held 0.96 lab with 0.41 field and no forgetting. Eightfold field upsampling added nothing.
ResNet-50 cleared 0.65 in the field but forgot the lab at 0.29. No single head passed both gates, so the architecture had to change.
Two heads, two backbones, a learned router at 74%: routed scoring reached 0.39 against the single model's 0.63. Routing was shelved.
GrabCut preprocessing dropped field F1 from 0.41 to 0.27. The same sweep found the real lever: backbone learning rate with repeat 20 sampling.
Test time augmentation did nothing. Class balanced sampling cleared every gate: 0.661 field accuracy, 0.654 field F1, lab intact.
Shipped to production| Checkpoint | Lab acc | Field acc | Field F1 |
|---|---|---|---|
| Stage 1 baseline | 0.96 | 0.14 | 0.11 |
| Mixed training | 0.96 | 0.41 | 0.41 |
| Repeat 20 sweep | 0.99 | 0.63 | 0.56 |
| Shipped · class balanced | 0.96 | 0.66 | 0.65 |
Held out test splits, seed 42. Accuracy counts the top guess; F1 is macro.
Everything behind these numbers
Ablation logs, confusion matrices, plots and the shipped weights live in the results folder.