Spaces:
Runtime error
Runtime error
| import os | |
| import sys | |
| import io | |
| import torch | |
| import torch.nn.functional as F | |
| from PIL import Image | |
| from torchvision import transforms | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from config import ( | |
| BEST_MODEL_PATH, CLASS_NAMES, IDX_TO_CLASS, | |
| IMAGE_SIZE, MEAN, STD, MODEL_ARCH, NUM_CLASSES, | |
| ) | |
| from src.model import build_model | |
| # ββ Load model once ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| _model = None | |
| _device = None | |
| def _get_model(): | |
| global _model, _device | |
| if _model is None: | |
| _device = torch.device("cuda" if torch.cuda.is_available() else "cpu") | |
| _model = build_model(MODEL_ARCH) | |
| _model.load_state_dict(torch.load(BEST_MODEL_PATH, map_location=_device)) | |
| _model.to(_device).eval() | |
| return _model, _device | |
| # ββ Transform ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| _transform = transforms.Compose([ | |
| transforms.Resize((IMAGE_SIZE, IMAGE_SIZE)), | |
| transforms.ToTensor(), | |
| transforms.Normalize(mean=MEAN, std=STD), | |
| ]) | |
| # ββ Predict ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def predict_from_bytes(image_bytes: bytes) -> dict: | |
| image = Image.open(io.BytesIO(image_bytes)).convert("RGB") | |
| return _predict(image) | |
| def predict_from_path(image_path: str) -> dict: | |
| image = Image.open(image_path).convert("RGB") | |
| return _predict(image) | |
| def _predict(image: Image.Image) -> dict: | |
| model, device = _get_model() | |
| tensor = _transform(image).unsqueeze(0).to(device) | |
| with torch.no_grad(): | |
| logits = model(tensor) | |
| probs = F.softmax(logits, dim=1).squeeze().cpu().numpy() | |
| pred_idx = int(probs.argmax()) | |
| pred_key = IDX_TO_CLASS[pred_idx] | |
| pred_name = CLASS_NAMES[pred_idx] | |
| confidence = float(probs[pred_idx]) | |
| all_probs = { | |
| IDX_TO_CLASS[i]: round(float(probs[i]), 4) | |
| for i in range(NUM_CLASSES) | |
| } | |
| # Sort by probability descending | |
| all_probs = dict(sorted(all_probs.items(), key=lambda x: x[1], reverse=True)) | |
| return { | |
| "predicted_class": pred_key, | |
| "class_name": pred_name, | |
| "confidence": round(confidence, 4), | |
| "probabilities": all_probs, | |
| } | |
| # ββ CLI test βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if __name__ == "__main__": | |
| import os, json | |
| samples_dir = os.path.join("data", "raw", "ham10000_images") | |
| # pick one image per class for quick test | |
| from config import CLASS_LABELS | |
| import pandas as pd | |
| df = pd.read_csv(os.path.join("data", "raw", "HAM10000_metadata.csv")) | |
| print(f"{'True':>6} {'Pred':>6} {'Conf':>7} Class Name") | |
| print("-" * 55) | |
| correct = 0 | |
| for cls in sorted(CLASS_LABELS.keys()): | |
| row = df[df["dx"] == cls].iloc[0] | |
| img_path = os.path.join(samples_dir, row["image_id"] + ".jpg") | |
| result = predict_from_path(img_path) | |
| match = "OK" if result["predicted_class"] == cls else "--" | |
| correct += 1 if match == "OK" else 0 | |
| print(f"[{match}] {cls:>6} {result['predicted_class']:>6} {result['confidence']*100:6.1f}% {result['class_name']}") | |
| print(f"\nAccuracy on 1-per-class samples: {correct}/7") | |