# utils/model_utils.py import torch import torch.nn as nn from torchvision.models import densenet121, DenseNet121_Weights # Disease labels DISEASE_LIST = [ 'Atelectasis', 'Cardiomegaly', 'Consolidation', 'Edema', 'Effusion', 'Emphysema', 'Fibrosis', 'Hernia', 'Infiltration', 'Mass', 'Nodule', 'Pleural_Thickening', 'Pneumonia', 'Pneumothorax' ] # Load trained CheXNet model class CheXNet(nn.Module): def __init__(self, num_classes=14): super().__init__() base_model = densenet121(weights=DenseNet121_Weights.IMAGENET1K_V1) self.features = base_model.features self.classifier = nn.Linear(base_model.classifier.in_features, num_classes) def forward(self, x): x = self.features(x) x = nn.functional.adaptive_avg_pool2d(x, (1, 1)) x = torch.flatten(x, 1) return self.classifier(x) from huggingface_hub import hf_hub_download def load_model(device): model_path = hf_hub_download(repo_id="cfgpp/danny_net", filename="dannynet.pth") # Rebuild model architecture model = CheXNet(num_classes=14) # Load state dict (just weights) state_dict = torch.load(model_path, map_location=device) model.load_state_dict(state_dict) model.to(device) model.eval() return model def predict(model, img_tensor, device): with torch.no_grad(): output = model(img_tensor.unsqueeze(0).to(device)) probs = torch.sigmoid(output[0]).cpu().numpy() # Sort all results by descending probability sorted_probs = sorted(zip(DISEASE_LIST, probs), key=lambda x: x[1], reverse=True) return dict(sorted_probs) import cv2 import numpy as np import torch def generate_gradcam(model, input_tensor, target_class, device): features = [] gradients = [] def forward_hook(module, input, output): features.append(output.detach()) def backward_hook(module, grad_input, grad_output): gradients.append(grad_output[0].detach()) last_conv_layer = model.features[-1] forward_handle = last_conv_layer.register_forward_hook(forward_hook) backward_handle = last_conv_layer.register_backward_hook(backward_hook) model.zero_grad() output = model(input_tensor.unsqueeze(0).to(device)) class_score = output[0][target_class] class_score.backward() grads = gradients[0] fmap = features[0] weights = grads.mean(dim=[2, 3], keepdim=True) cam = (weights * fmap).sum(dim=1).squeeze() cam = torch.relu(cam).cpu().numpy() cam = cam - cam.min() cam = cam / cam.max() cam = cv2.resize(cam, (224, 224)) forward_handle.remove() backward_handle.remove() return cam