NLPV commited on
Commit
e607b43
Β·
verified Β·
1 Parent(s): a8a4f36

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -0
app.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import torchvision
4
+ import torchvision.transforms as transforms
5
+ from torchvision import models
6
+ import torch.nn as nn
7
+ import torch.optim as optim
8
+ import numpy as np
9
+ from PIL import Image
10
+
11
+ # CIFAR-10 labels
12
+ cifar10_classes = ['airplane', 'automobile', 'bird', 'cat', 'deer',
13
+ 'dog', 'frog', 'horse', 'ship', 'truck']
14
+
15
+ # Transforms
16
+ transform = transforms.Compose([
17
+ transforms.Resize((32, 32)),
18
+ transforms.ToTensor(),
19
+ transforms.Normalize((0.5,), (0.5,))
20
+ ])
21
+
22
+ # Load CIFAR-10
23
+ trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
24
+ testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
25
+ testloader = torch.utils.data.DataLoader(testset, batch_size=64, shuffle=False)
26
+
27
+ def predict(model, image_tensor):
28
+ model.eval()
29
+ with torch.no_grad():
30
+ outputs = model(image_tensor.unsqueeze(0))
31
+ probs = torch.nn.functional.softmax(outputs[0], dim=0)
32
+ pred = torch.argmax(probs).item()
33
+ return probs, pred
34
+
35
+ def unlearn(model, image_tensor, label_idx, learning_rate, steps=10):
36
+ model.train()
37
+ for m in model.modules():
38
+ if isinstance(m, nn.BatchNorm2d):
39
+ m.eval()
40
+
41
+ criterion = nn.CrossEntropyLoss()
42
+ optimizer = optim.SGD(model.parameters(), lr=learning_rate)
43
+
44
+ for _ in range(steps):
45
+ output = model(image_tensor.unsqueeze(0))
46
+ loss = -criterion(output, torch.tensor([label_idx]))
47
+ optimizer.zero_grad()
48
+ loss.backward()
49
+ optimizer.step()
50
+
51
+ def evaluate_model(model, testloader):
52
+ model.eval()
53
+ total, correct, loss_total = 0, 0, 0.0
54
+ criterion = nn.CrossEntropyLoss()
55
+ with torch.no_grad():
56
+ for images, labels in testloader:
57
+ outputs = model(images)
58
+ _, preds = torch.max(outputs, 1)
59
+ loss = criterion(outputs, labels)
60
+ total += labels.size(0)
61
+ correct += (preds == labels).sum().item()
62
+ loss_total += loss.item() * labels.size(0)
63
+ return round(100 * correct / total, 2), round(loss_total / total, 4)
64
+
65
+ def run_unlearning(index_to_unlearn, learning_rate):
66
+ # Load original model
67
+ original_model = models.resnet18(weights=None)
68
+ original_model.fc = nn.Linear(original_model.fc.in_features, 10)
69
+ original_model.load_state_dict(torch.load("resnet18.pth"))
70
+ original_model.eval()
71
+
72
+ # Duplicate model for unlearning
73
+ unlearned_model = models.resnet18(weights=None)
74
+ unlearned_model.fc = nn.Linear(unlearned_model.fc.in_features, 10)
75
+ unlearned_model.load_state_dict(torch.load("resnet18.pth"))
76
+
77
+ # Get sample
78
+ image_tensor, label_idx = trainset[index_to_unlearn]
79
+ label_name = cifar10_classes[label_idx]
80
+
81
+ # Prediction before
82
+ probs_before, pred_before = predict(original_model, image_tensor)
83
+ conf_before = probs_before[label_idx].item()
84
+
85
+ # Unlearning
86
+ unlearn(unlearned_model, image_tensor, label_idx, learning_rate)
87
+
88
+ # Prediction after
89
+ probs_after, pred_after = predict(unlearned_model, image_tensor)
90
+ conf_after = probs_after[label_idx].item()
91
+
92
+ # Evaluate full test set
93
+ orig_acc, orig_loss = evaluate_model(original_model, testloader)
94
+ unlearn_acc, unlearn_loss = evaluate_model(unlearned_model, testloader)
95
+
96
+ result = f"""
97
+ πŸ“ Index Unlearned: {index_to_unlearn} | Label: {label_name}
98
+
99
+ πŸ”Ž BEFORE Unlearning:
100
+ - Prediction: {cifar10_classes[pred_before]}
101
+ - Confidence: {conf_before:.4f}
102
+
103
+ 🧽 AFTER Unlearning:
104
+ - Prediction: {cifar10_classes[pred_after]}
105
+ - Confidence: {conf_after:.4f}
106
+
107
+ πŸ“‰ Confidence Drop: {conf_before - conf_after:.4f}
108
+
109
+ πŸ§ͺ Test Set Performance:
110
+ - Original Model: {orig_acc:.2f}% | Loss: {orig_loss:.4f}
111
+ - Unlearned Model: {unlearn_acc:.2f}% | Loss: {unlearn_loss:.4f}
112
+ """
113
+ return result
114
+
115
+ # Gradio Interface
116
+ demo = gr.Interface(
117
+ fn=run_unlearning,
118
+ inputs=[
119
+ gr.Slider(0, len(trainset)-1, step=1, label="Select Index to Unlearn"),
120
+ gr.Slider(0.0001, 0.1, step=0.0001, value=0.01, label="Learning Rate (for Unlearning)")
121
+ ],
122
+ outputs="text",
123
+ title="πŸ” CIFAR-10 Machine Unlearning",
124
+ description="Load a pre-trained ResNet18 and unlearn a specific index from the CIFAR-10 training set."
125
+ )
126
+
127
+ if __name__ == "__main__":
128
+ demo.launch()