ttoosi's picture
Update app.py
0657874 verified
Raw
History Blame Contribute Delete
6.7 kB
import torch
import gradio as gr
from torchvision import models, transforms
from PIL import Image
import requests
from huggingface_hub import hf_hub_download
from PIL import Image
import numpy as np
import random
# Load the model checkpoint from Hugging Face
checkpoint_path = hf_hub_download(repo_id="ttoosi/resnet50_robust_face", filename="100_checkpoint.pt")
# Initialize the model
model = models.resnet50()
# change the num_classes to 500
model.fc = torch.nn.Linear(model.fc.in_features, 500)
checkpoint = torch.load(checkpoint_path, map_location=torch.device('cpu'))['model']
# remove the prefix 'module.' from the keys
# remove the prefix 'model.' from the keys that have it
new_state_dict = {k.replace('module.', ''): v for k, v in checkpoint.items()}
new_state_dict = {k.replace('model.', ''): v for k, v in new_state_dict.items()}
new_state_dict = {k.replace('attacker.', ''): v for k, v in new_state_dict.items()}
print(new_state_dict.keys())
print('********************')
model.load_state_dict(new_state_dict, strict=False) # ignore Unexpected key(s) in state_dict: "normalizer.new_mean", "normalizer.new_std", "normalize.new_mean", "normalize.new_std".
model.eval()
# Image preprocessing
preprocess = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]), # vggface2
])
# # Function to make predictions
# def predict(image):
# if isinstance(image, np.ndarray):
# image = Image.fromarray(image) # Convert to PIL Image if i
# image = preprocess(image).unsqueeze(0) # Add batch dimension
# with torch.no_grad():
# output = model(image) # Perform inference on CPU
# _, predicted_class = output.max(1)
# # Fetch 9 random samples from the predicted class
# class_samples = ds.filter(lambda example: example['label'] == predicted_class.item())
# sample_images = random.sample(list(class_samples), min(len(class_samples), 9))
# sample_images_urls = [sample['image'] for sample in sample_images]
# return f"Predicted class: {predicted_class.item()}", sample_images_urls
import torch
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import numpy as np
def simple_generative_inference(image, mode, model, n_iterations=10, step_size=0.01, eps=0.1, noise_ratio=0.1):
# Preprocess image
transform = transforms.Compose([
transforms.Resize((224, 224)), # Enforce fixed size
transforms.ToTensor(),
transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])
image_original = transform(image).unsqueeze(0)
image_tensor = image_original.detach().clone()
image_tensor.requires_grad = True
# image_tensor.retain_grad() # Ensure gradients are retained for non-leaf tensor
if mode == "increase confidence":
output = model(image_tensor)
probs = torch.nn.functional.softmax(output, dim=1)
_, least_likely_indices = torch.topk(probs, k=2, largest=False)
elif mode == "ReverseDiffuse":
noisy_image = image_tensor + torch.randn_like(image_tensor) * noise_ratio
else:
raise ValueError("Invalid mode selected. Choose 'increase confidence' or 'ReverseDiffuse'.")
for _ in range(n_iterations):
# Zero gradients
model.zero_grad()
# Forward pass
output = model(image_tensor)
# Define inference loss based on mode
if mode == "increase confidence":
losses = []
for idx in least_likely_indices[0]:
target = torch.full((1,), idx, dtype=torch.long, device=output.device)
loss = torch.nn.CrossEntropyLoss()(output, target)
losses.append(loss)
loss = torch.stack(losses).mean()
elif mode == "ReverseDiffuse":
loss = torch.nn.functional.mse_loss(image_tensor, noisy_image)
# Backward pass
loss.backward()
# Access gradient
grad = image_tensor.grad # Gradient is now retained
if torch.isnan(grad).any(): # Check for NaN values in the gradient
print("Warning: Gradient contains NaN values. Aborting inference.")
return None, None
grad_norm = grad.view(grad.shape[0], -1).norm(dim=1, keepdim=True).view(grad.shape[0], 1, 1, 1)
grad = grad / (grad_norm + 1e-10) # Avoid division by zero
# Update image tensor
image_tensor = image_tensor + step_size * grad
delta = image_tensor - image_original
delta = torch.clamp(delta, -eps, eps) # Keep within range
image_tensor = torch.clamp(image_original + delta, 0, 1)
image_tensor = image_tensor.clone().detach().requires_grad_(True) # Ensure it's a new leaf tensor
image_tensor.retain_grad()
# Generate gradient visualization
grad_image = grad.abs().mean(dim=1).squeeze().cpu().numpy()
grad_image = (grad_image - grad_image.min()) / (grad_image.max() - grad_image.min())
grad_image = Image.fromarray((grad_image * 255).astype(np.uint8))
# Convert final processed image back to PIL format
processed_image = image_tensor.detach().squeeze().permute(1, 2, 0).cpu().numpy()
processed_image = (processed_image - processed_image.min()) / (processed_image.max() - processed_image.min())
processed_image = Image.fromarray((processed_image * 255).astype(np.uint8))
return processed_image, grad_image
# Gradio Interface
iface = gr.Interface(
fn=lambda image, mode, step_size, eps, noise_ratio, n_iterations: simple_generative_inference(
image, mode, model, step_size=step_size, eps=eps, noise_ratio=noise_ratio, n_iterations=n_iterations
),
inputs=[
gr.Image(type="pil", label="Input Image"), # Input image
gr.Radio(["increase confidence", "ReverseDiffuse"], label="Inference Mode"), # Mode selection
gr.Slider(0.1, 20, value=1, step=0.1, label="Step Size"), # Step size
gr.Slider(0.1, 40, value=0.5, step=0.1, label="Epsilon (eps)"), # Epsilon constraint
gr.Slider(0.0, 1.0, value=0.5, step=0.1, label="Noise Ratio"), # Noise ratio
gr.Slider(1, 1000, value=100, step=1, label="Number of Iterations"), # Number of iterations
],
outputs=[
gr.Image(label="Processed Image"), # Processed image
gr.Image(label="Gradient Visualization") # Gradient visualization
],
title="Generative Inference",
description="Perform generative inference on input images using adjustable parameters such as step size, epsilon, noise ratio, and number of iterations."
)
iface.launch()