Solar Panel Dust Detection with Explainable AI
Hybrid EfficientNet-B2 (frozen) + RBF-SVM model for classifying a single RGB image of a photovoltaic (PV) panel as clean or dirty, with a focus on cross-dataset generalisation and explainability (Grad-CAM, Score-CAM, Integrated Gradients, SHAP, LIME).
Model
- Feature extractor: EfficientNet-B2, ImageNet weights, frozen, global-average pooled โ 1,408-d vector.
- Head: RBF-kernel SVM (
C=10,gamma=auto),class_weight="balanced". - Architecture is exactly the deployed production model (version
v007).
| Metric | Value |
|---|---|
| Test accuracy (merged held-out, 381 imgs) | 90.29% |
| AUC-ROC | 0.9596 |
| 5-fold CV accuracy | 86.38% |
| External: Dusty/Clean (2,562 imgs) | 98.24% (98.0% dirty recall) |
| External: Faulty-panel clean/dirty (383 imgs) | 99.74% (100% dirty recall) |
Files
svm_classifier.pklโ trained RBF-SVM head (joblib).scaler.pklโ fittedStandardScalerapplied to pooled features.pipeline_meta.jsonโ full training metadata and per-metric scores.class_names.jsonโ label order (["clean", "dirty"]).demo.pyโ self-contained inference script.
Usage
pip install tensorflow scikit-learn joblib numpy pillow
python demo.py panel.jpg # print label, confidence, dustiness
python demo.py clean.jpg dirty.jpg # batch
The first run downloads the EfficientNet-B2 ImageNet weights (~80 MB) from TensorFlow via
keras.
How it was trained
A single-source model overfits one acquisition pipeline and collapses on new data (observed: ~6% dirty recall on external sets). The fix was to merge three public PV-dust sources into one 3,787-image corpus and retrain:
| Split | Clean | Dirty | Total |
|---|---|---|---|
| Train | 1,750 | 1,279 | 3,029 |
| Val | 218 | 159 | 377 |
| Test | 220 | 161 | 381 |
| All | 2,188 | 1,599 | 3,787 |
The frozen representation + margin-based SVM then transfers far better across acquisition sources (see external-validation metrics above).
Intended use & limitations
- For single-panel RGB inspection; labels are binary (clean/dirty), not severity.
- Confidence for every prediction is produced; a configurable confidence threshold can route low-confidence samples to human review.
- The backbone is loaded fresh from ImageNet weights at inference (not stored in this repo), matching the deployed frozen-backbone protocol.
Related
Full experimental details, the IEEE-format paper, and the five-method XAI module live in the companion project repo.
Evaluation results
- Test Accuracy (merged held-out)self-reported0.903
- AUC-ROCself-reported0.960
- External accuracy (2,562 imgs)self-reported0.982
- External accuracy (383 imgs)self-reported0.997