cifar10 / app.py
dawn17's picture
Update app.py
e828884
import os
from typing import List
import gradio as gr
import numpy as np
import torch
import torch.nn.functional as F
from model import DavidPageNet
from PIL import Image
from pytorch_grad_cam import GradCAM
from pytorch_grad_cam.utils.image import show_cam_on_image
from pytorch_grad_cam.utils.model_targets import ClassifierOutputTarget
from torchvision import transforms
# imagenet mean and std
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
inv_mean = [-mean / std for mean, std in zip(mean, std)]
inv_std = [1 / s for s in std]
# transforms
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=mean, std=std),
]
)
inv_normalize = transforms.Normalize(mean=inv_mean, std=inv_std)
classes = [
'airplane',
'automobile',
'bird',
'cat',
'deer',
'dog',
'frog',
'horse',
'ship',
'truck'
]
class Gradio:
def __init__(self, model_path: str):
use_cuda = torch.cuda.is_available()
self.device = torch.device("cuda" if use_cuda else "cpu")
self.model = self.load_model(model_path)
self.temperature = 2
def load_model(self, model_path: str):
model = DavidPageNet().to(self.device)
if os.path.isfile(model_path):
model.load_state_dict(
torch.load(model_path, map_location=self.device), strict=False
)
return model
def cam(
self,
input_tensor: torch.Tensor,
target_class_id: int,
layer_nums: List,
transparency: float = 0.7,
):
targets = [ClassifierOutputTarget(target_class_id)]
target_layers = [getattr(self.model, f"block{layer-1}") for layer in layer_nums]
with GradCAM(
model=self.model,
target_layers=target_layers,
use_cuda=self.device == torch.device("cuda"),
) as cam:
grayscale_cam = cam(input_tensor=input_tensor, targets=targets)
grayscale_cam = grayscale_cam[0, :]
img = inv_normalize(input_tensor)
rgb_img = img[0].permute(1, 2, 0).cpu().numpy()
visualization = show_cam_on_image(
rgb_img, grayscale_cam, use_rgb=True, image_weight=transparency
)
return visualization
def inference(
self,
input_img: np.array,
transparency: float=0.7,
ntop_classes: int=2,
layer_nums: List=[3, 4],
cam_for_class: str="default",
):
self.model.eval()
input_img = transform(input_img)
input_img = input_img.to(self.device)
input_img = input_img.unsqueeze(0)
with torch.no_grad():
outputs = self.model(input_img).squeeze(0)
outputs = F.softmax(outputs / self.temperature, dim=-1)
probability, prediction = torch.sort(outputs, descending=True)
prediction = list(zip(prediction.tolist(), probability.tolist()))
class_id = (
prediction[0][0]
if cam_for_class in ["default", ""]
else classes.index(cam_for_class)
)
visualization = self.cam(
input_tensor=input_img,
target_class_id=class_id,
layer_nums=layer_nums,
transparency=transparency,
)
top_nclass_result = [
(classes[class_id], round(score, 2))
for class_id, score in prediction[:ntop_classes]
]
return visualization, dict(top_nclass_result)
method = Gradio(model_path="./checkpoint/model.pt")
demo = gr.Interface(
fn=method.inference,
inputs=[
gr.Image(shape=(32, 32), label="Input Image", value="./samples/dog_cat.jpeg"),
gr.Slider(
minimum=0,
maximum=1,
value=0.5,
label="Transparency",
info="Transparency of the CAM-Attention Output",
),
gr.Slider(
minimum=1,
maximum=10,
step=1,
value=2,
label="Top Classes",
info="Number of Top Predicted Classes",
),
gr.CheckboxGroup(
choices=[1, 2, 3, 4],
value=[3, 4],
label="Network Layers",
info="Network Layers for CAM-Attention Extraction",
),
gr.Dropdown(
choices=["default"] + classes,
multiselect=False,
value="default",
label="Class Activation Map (CAM) Focus Visualization",
info="This section showcases the specific region of interest within the input image that the Class Activation Map (CAM) algorithm emphasizes to make predictions based on the selected class from the dropdown menu. The 'default' value serves as the default choice, representing the top class predicted by the model.",
),
],
outputs=[
gr.Image(shape=(32, 32), label="CAM Output for the Chosen Class").style(width=256, height=256),
gr.Label(label="Top Classes"),
],
examples=[[os.path.join("./samples/", f)] for f in os.listdir("./samples/")]
)
demo.launch()