Download src/models/image_model.py from Asadrizvi64/electrical-outlets-diagnostic: direct link, hf CLI and curl.
- Browser
- Download file 2.39 kB
-
https://huggingface.co/Asadrizvi64/electrical-outlets-diagnostic/resolve/main/src/models/image_model.py
- Command line
-
hf download hf://Asadrizvi64/electrical-outlets-diagnostic/src/models/image_model.py
-
curl -L -o image_model.py https://huggingface.co/Asadrizvi64/electrical-outlets-diagnostic/resolve/main/src/models/image_model.py
2.39 kB
| """ | |
| Image classifier for Electrical Outlets. EfficientNet-B0 backbone + MLP head. | |
| FINAL v5: 5 classes (no GFCI). | |
| """ | |
| from pathlib import Path | |
| from typing import Dict, Any, Optional | |
| import json | |
| import torch | |
| import torch.nn as nn | |
| from torchvision import models | |
| class ElectricalOutletsImageModel(nn.Module): | |
| def __init__( | |
| self, | |
| num_classes: int = 5, | |
| label_mapping_path: Optional[Path] = None, | |
| pretrained: bool = True, | |
| head_hidden: int = 256, | |
| head_dropout: float = 0.4, | |
| ): | |
| super().__init__() | |
| self.num_classes = num_classes | |
| self.backbone = models.efficientnet_b0( | |
| weights=models.EfficientNet_B0_Weights.IMAGENET1K_V1 if pretrained else None | |
| ) | |
| in_features = self.backbone.classifier[1].in_features # 1280 | |
| self.backbone.classifier = nn.Identity() | |
| self.head = nn.Sequential( | |
| nn.Dropout(head_dropout), | |
| nn.Linear(in_features, head_hidden), | |
| nn.ReLU(), | |
| nn.Dropout(head_dropout * 0.5), | |
| nn.Linear(head_hidden, num_classes), | |
| ) | |
| self.idx_to_issue_type = None | |
| self.idx_to_severity = None | |
| if label_mapping_path and Path(label_mapping_path).exists(): | |
| with open(label_mapping_path) as f: | |
| lm = json.load(f) | |
| self.idx_to_issue_type = lm["image"]["idx_to_issue_type"] | |
| self.idx_to_severity = lm["image"]["idx_to_severity"] | |
| def forward(self, x: torch.Tensor) -> torch.Tensor: | |
| features = self.backbone(x) | |
| return self.head(features) | |
| def predict_to_schema(self, logits: torch.Tensor) -> Dict[str, Any]: | |
| probs = torch.softmax(logits, dim=-1) | |
| if logits.dim() == 1: | |
| probs = probs.unsqueeze(0) | |
| conf, pred = probs.max(dim=-1) | |
| pred = pred.item() if pred.numel() == 1 else pred | |
| conf = conf.item() if conf.numel() == 1 else conf | |
| issue_type = (self.idx_to_issue_type or ["unknown"] * self.num_classes)[pred] | |
| severity = (self.idx_to_severity or ["medium"] * self.num_classes)[pred] | |
| result = "normal" if issue_type == "normal" else "issue_detected" | |
| return { | |
| "result": result, | |
| "issue_type": issue_type, | |
| "severity": severity, | |
| "confidence": float(conf), | |
| "class_idx": int(pred), | |
| } | |