File size: 3,527 Bytes
1b26403 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | ---
license: mit
tags:
- solar-energy
- image-classification
- photovoltaic
- dust-detection
- efficientnet
- svm
- explainable-ai
datasets:
- safwanshamsir99/solar-photovoltaics-panell-for-dust-dectection
library_name: scikit-learn
pipeline_tag: image-classification
metrics:
- accuracy
- roc_auc
model-index:
- name: solar-panel-dust-xai
results:
- task:
type: image-classification
name: Solar panel clean vs dirty
metrics:
- type: accuracy
value: 0.9029
name: Test Accuracy (merged held-out)
- type: roc_auc
value: 0.9596
name: AUC-ROC
- type: accuracy
value: 0.9824
name: External accuracy (2,562 imgs)
- type: accuracy
value: 0.9974
name: External accuracy (383 imgs)
---
# 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` — fitted `StandardScaler` applied 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
```bash
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.
|