forked from Verified-Intelligence/auto_LiRPA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimple_verification.py
71 lines (63 loc) · 2.58 KB
/
simple_verification.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import torch.nn as nn
import torch.nn.functional as F
import torchvision
from auto_LiRPA import BoundedModule, BoundedTensor
from auto_LiRPA.perturbations import *
import models
## Step 1: Define computational graph by implementing forward()
class Flatten(nn.Module):
def forward(self, x):
return x.view(x.size(0), -1)
# This simple model comes from https://github.com/locuslab/convex_adversarial
def mnist_model():
model = nn.Sequential(
nn.Conv2d(1, 16, 4, stride=2, padding=1),
nn.ReLU(),
nn.Conv2d(16, 32, 4, stride=2, padding=1),
nn.ReLU(),
Flatten(),
nn.Linear(32*7*7,100),
nn.ReLU(),
nn.Linear(100, 10)
)
return model
model = mnist_model()
# Load the pretrained weights
checkpoint = torch.load(os.path.join(os.path.dirname(__file__),"pretrain/kw_mnist.pth"))
model.load_state_dict(checkpoint)
## Step 2: Prepare dataset as usual
test_data = torchvision.datasets.MNIST("./data", train=False, download=True, transform=torchvision.transforms.ToTensor())
# For illustration we only use 2 image from dataset
N = 2
n_classes = 10
image = test_data.data[:N].view(N,1,28,28)
true_label = test_data.targets[:N]
# Convert to float
image = image.to(torch.float32) / 255.0
## Step 3: wrap model with auto_LiRPA
# The second parameter is for constructing the trace of the computational graph, and its content is not important.
model = BoundedModule(model, torch.empty_like(image))
# For larger convolutional models, setting bound_opts={"conv_mode": "patches"} is more efficient.
# model = BoundedModule(model, torch.empty_like(image), bound_opts={"conv_mode": "patches"})
## Step 4: Compute bounds using LiRPA given a perturbation
eps = 0.1
norm = np.inf
# ptb = PerturbationL0Norm(eps=eps)
ptb = PerturbationLpNorm(norm = norm, eps = eps)
image = BoundedTensor(image, ptb)
# Get model prediction as usual
pred = model(image)
label = torch.argmax(pred, dim=1).cpu().numpy()
## Step 5: Compute bounds for final output
for method in ['IBP', 'IBP+backward (CROWN-IBP)', 'backward (CROWN)']:
lb, ub = model.compute_bounds(x=(image,), method=method.split()[0])
lb = lb.detach().cpu().numpy()
ub = ub.detach().cpu().numpy()
print("Bounding method:", method)
for i in range(N):
print("Image {} top-1 prediction {} ground-truth {}".format(i, label[i], true_label[i]))
for j in range(n_classes):
indicator = '(ground-truth)' if j == true_label[i] else ''
print("f_{j}(x_0): {l:8.3f} <= f_{j}(x_0+delta) <= {u:8.3f} {ind}".format(
j=j, l=lb[i][j], u=ub[i][j], ind=indicator))
print()