| from pathlib import Path | |
| import numpy as np | |
| import torch | |
| from PIL import Image | |
| from src.logger import get_logger | |
| from src.model import ResNet18 | |
| from src.unknown import ( | |
| detect_unknown, | |
| calculate_entropy | |
| ) | |
| logger = get_logger(__name__) | |
| DEVICE = torch.device( | |
| "cuda" if torch.cuda.is_available() | |
| else "cpu" | |
| ) | |
| CLASS_NAMES = [ | |
| "airplane", | |
| "automobile", | |
| "bird", | |
| "cat", | |
| "deer", | |
| "dog", | |
| "frog", | |
| "horse", | |
| "ship", | |
| "truck", | |
| "unknown" | |
| ] | |
| def load_trained_model( | |
| model_path="models/best_resnet_cifar10.pth" | |
| ): | |
| """ | |
| Load best trained model. | |
| """ | |
| logger.info( | |
| f"Loading model from {model_path}" | |
| ) | |
| model = ResNet18( | |
| num_classes=11 | |
| ) | |
| model.load_state_dict( | |
| torch.load( | |
| model_path, | |
| map_location=DEVICE | |
| ) | |
| ) | |
| model.to(DEVICE) | |
| model.eval() | |
| logger.info( | |
| "Model loaded successfully" | |
| ) | |
| return model | |
| def load_external_image( | |
| image_path | |
| ): | |
| """ | |
| Load image and preprocess | |
| for CIFAR prediction. | |
| """ | |
| logger.info( | |
| f"Loading image: {image_path}" | |
| ) | |
| image = Image.open( | |
| image_path | |
| ).convert("RGB") | |
| image = image.resize( | |
| (32, 32) | |
| ) | |
| image = np.array( | |
| image | |
| ).astype( | |
| np.float32 | |
| ) / 255.0 | |
| logger.info( | |
| f"Image shape: {image.shape}" | |
| ) | |
| return image | |
| def preprocess_image( | |
| image | |
| ): | |
| """ | |
| Convert image to PyTorch tensor. | |
| Input: | |
| (32,32,3) | |
| Output: | |
| (1,3,32,32) | |
| """ | |
| image = torch.tensor( | |
| image, | |
| dtype=torch.float32 | |
| ) | |
| image = image.permute( | |
| 2, | |
| 0, | |
| 1 | |
| ) | |
| image = image.unsqueeze( | |
| 0 | |
| ) | |
| image = image.to( | |
| DEVICE | |
| ) | |
| return image | |
| def predict_single_image( | |
| model, | |
| image, | |
| confidence_threshold=0.60 | |
| ): | |
| """ | |
| Predict single image. | |
| """ | |
| logger.info( | |
| "Running prediction" | |
| ) | |
| image_tensor = preprocess_image( | |
| image | |
| ) | |
| with torch.no_grad(): | |
| outputs = model( | |
| image_tensor | |
| ) | |
| probabilities = torch.softmax( | |
| outputs, | |
| dim=1 | |
| ) | |
| probabilities_np = ( | |
| probabilities | |
| .cpu() | |
| .numpy() | |
| ) | |
| predicted_idx = int( | |
| np.argmax( | |
| probabilities_np | |
| ) | |
| ) | |
| confidence = float( | |
| np.max( | |
| probabilities_np | |
| ) | |
| ) | |
| entropy = calculate_entropy( | |
| probabilities_np | |
| ) | |
| logger.info( | |
| f"Entropy={entropy:.4f}" | |
| ) | |
| if detect_unknown( | |
| probabilities_np, | |
| threshold=confidence_threshold | |
| ): | |
| predicted_class = "unknown" | |
| else: | |
| predicted_class = CLASS_NAMES[ | |
| predicted_idx | |
| ] | |
| logger.info( | |
| f"Prediction={predicted_class}" | |
| ) | |
| logger.info( | |
| f"Confidence={confidence:.4f}" | |
| ) | |
| print("\nTop 3 Predictions\n") | |
| top3 = np.argsort( | |
| probabilities_np[0] | |
| )[-3:][::-1] | |
| for idx in top3: | |
| print( | |
| f"{CLASS_NAMES[idx]:12s}" | |
| f" : {probabilities_np[0][idx]:.4f}" | |
| ) | |
| print( | |
| f"\nFinal Prediction : " | |
| f"{predicted_class}" | |
| ) | |
| print( | |
| f"Confidence : " | |
| f"{confidence:.4f}" | |
| ) | |
| print( | |
| f"Entropy : " | |
| f"{entropy:.4f}" | |
| ) | |
| Path( | |
| "outputs/predictions" | |
| ).mkdir( | |
| parents=True, | |
| exist_ok=True | |
| ) | |
| with open( | |
| "outputs/predictions/predictions.log", | |
| "a", | |
| encoding="utf-8" | |
| ) as f: | |
| f.write( | |
| f"Prediction={predicted_class}, " | |
| f"Confidence={confidence:.4f}, " | |
| f"Entropy={entropy:.4f}\n" | |
| ) | |
| return ( | |
| predicted_class, | |
| confidence, | |
| probabilities_np | |
| ) | |
| if __name__ == "__main__": | |
| model = load_trained_model() | |
| image = load_external_image( | |
| "inputs/sample_image.jpg" | |
| ) | |
| prediction, confidence, _ = ( | |
| predict_single_image( | |
| model, | |
| image | |
| ) | |
| ) | |
| print( | |
| f"\nResult: {prediction}" | |
| ) | |
| print( | |
| f"Confidence: {confidence:.4f}" | |
| ) |