Skip to content

Commit 00a8e85

Browse files
author
wu-dx16
committed
init
1 parent 12ad6ef commit 00a8e85

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+6604
-0
lines changed

AT_AWP/awp.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# This is a simple implementation of AWP for Standard Adversarial Training (Madry)
2+
import copy
3+
import torch.nn as nn
4+
import torch.optim as optim
5+
import torch
6+
EPS = 1E-20
7+
8+
9+
def normalize(perturbations, weights):
10+
perturbations.mul_(weights.norm()/(perturbations.norm() + EPS))
11+
12+
13+
def normalize_grad_by_weights(weights, ref_weights):
14+
for w, ref_w in zip(weights, ref_weights):
15+
if w.dim() <= 1:
16+
w.grad.data.fill_(0) # ignore perturbations with 1 dimension (e.g. BN, bias)
17+
else:
18+
normalize(w.grad.data, ref_w)
19+
20+
21+
class AdvWeightPerturb(object):
22+
"""
23+
This is an implementation of AWP ONLY for Standard adversarial training
24+
"""
25+
def __init__(self, model, eta, nb_iter=1):
26+
super(AdvWeightPerturb, self).__init__()
27+
self.eta = eta
28+
self.nb_iter = nb_iter
29+
self.model = model
30+
self.optim = optim.SGD(model.parameters(), lr=eta/nb_iter)
31+
self.criterion = nn.CrossEntropyLoss()
32+
self.diff = None
33+
34+
def perturb(self, X_adv, y):
35+
# store the original weight
36+
old_w = copy.deepcopy([p.data for p in self.model.parameters()])
37+
38+
# perturb the model
39+
for idx in range(self.nb_iter):
40+
self.optim.zero_grad()
41+
outputs = self.model(X_adv)
42+
loss = - self.criterion(outputs, y)
43+
loss.backward()
44+
45+
# normalize the gradient
46+
normalize_grad_by_weights(self.model.parameters(), old_w)
47+
48+
self.optim.step()
49+
50+
# calculate the weight perturbation
51+
self.diff = [w1 - w2 for w1, w2 in zip(self.model.parameters(), old_w)]
52+
53+
def restore(self):
54+
for w, v in zip(self.model.parameters(), self.diff):
55+
w.data.sub_(v.data)

AT_AWP/logs/cifar100_l2/preactresnet18_awp/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar100_l2/preactresnet18_standard/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar100_linf/preactresnet18_awp/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar100_linf/preactresnet18_standard/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar10_l2/preactresnet18_awp/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar10_l2/preactresnet18_standard/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar10_linf/preactresnet18_awp/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar10_linf/preactresnet18_standard/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar10_linf/wrn34_awp/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/cifar10_linf/wrn34_standard/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/svhn_l2/preactresnet18_awp/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/svhn_l2/preactresnet18_standard/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/svhn_linf/preactresnet18_awp/output.log

+202
Large diffs are not rendered by default.

AT_AWP/logs/svhn_linf/preactresnet18_standard/output.log

+202
Large diffs are not rendered by default.

AT_AWP/preactresnet.py

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
'''Pre-activation ResNet in PyTorch.
2+
3+
Reference:
4+
[1] Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
5+
Identity Mappings in Deep Residual Networks. arXiv:1603.05027
6+
'''
7+
import torch
8+
import torch.nn as nn
9+
import torch.nn.functional as F
10+
11+
12+
class PreActBlock(nn.Module):
13+
'''Pre-activation version of the BasicBlock.'''
14+
expansion = 1
15+
16+
def __init__(self, in_planes, planes, stride=1):
17+
super(PreActBlock, self).__init__()
18+
self.bn1 = nn.BatchNorm2d(in_planes)
19+
self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
20+
self.bn2 = nn.BatchNorm2d(planes)
21+
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)
22+
23+
if stride != 1 or in_planes != self.expansion*planes:
24+
self.shortcut = nn.Sequential(
25+
nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False)
26+
)
27+
28+
def forward(self, x):
29+
out = F.relu(self.bn1(x))
30+
shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x
31+
out = self.conv1(out)
32+
out = self.conv2(F.relu(self.bn2(out)))
33+
out += shortcut
34+
return out
35+
36+
37+
class PreActBottleneck(nn.Module):
38+
'''Pre-activation version of the original Bottleneck module.'''
39+
expansion = 4
40+
41+
def __init__(self, in_planes, planes, stride=1):
42+
super(PreActBottleneck, self).__init__()
43+
self.bn1 = nn.BatchNorm2d(in_planes)
44+
self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=1, bias=False)
45+
self.bn2 = nn.BatchNorm2d(planes)
46+
self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)
47+
self.bn3 = nn.BatchNorm2d(planes)
48+
self.conv3 = nn.Conv2d(planes, self.expansion*planes, kernel_size=1, bias=False)
49+
50+
if stride != 1 or in_planes != self.expansion*planes:
51+
self.shortcut = nn.Sequential(
52+
nn.Conv2d(in_planes, self.expansion*planes, kernel_size=1, stride=stride, bias=False)
53+
)
54+
55+
def forward(self, x):
56+
out = F.relu(self.bn1(x))
57+
shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else x
58+
out = self.conv1(out)
59+
out = self.conv2(F.relu(self.bn2(out)))
60+
out = self.conv3(F.relu(self.bn3(out)))
61+
out += shortcut
62+
return out
63+
64+
65+
class PreActResNet(nn.Module):
66+
def __init__(self, block, num_blocks, num_classes=10):
67+
super(PreActResNet, self).__init__()
68+
self.in_planes = 64
69+
70+
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
71+
self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
72+
self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
73+
self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
74+
self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
75+
self.bn = nn.BatchNorm2d(512 * block.expansion)
76+
self.linear = nn.Linear(512*block.expansion, num_classes)
77+
78+
def _make_layer(self, block, planes, num_blocks, stride):
79+
strides = [stride] + [1]*(num_blocks-1)
80+
layers = []
81+
for stride in strides:
82+
layers.append(block(self.in_planes, planes, stride))
83+
self.in_planes = planes * block.expansion
84+
return nn.Sequential(*layers)
85+
86+
def forward(self, x):
87+
out = self.conv1(x)
88+
out = self.layer1(out)
89+
out = self.layer2(out)
90+
out = self.layer3(out)
91+
out = self.layer4(out)
92+
out = F.relu(self.bn(out))
93+
out = F.avg_pool2d(out, 4)
94+
out = out.view(out.size(0), -1)
95+
out = self.linear(out)
96+
return out
97+
98+
99+
def PreActResNet18(num_classes=10):
100+
return PreActResNet(PreActBlock, [2,2,2,2], num_classes=num_classes)
101+
102+
def PreActResNet34():
103+
return PreActResNet(PreActBlock, [3,4,6,3])
104+
105+
def PreActResNet50():
106+
return PreActResNet(PreActBottleneck, [3,4,6,3])
107+
108+
def PreActResNet101():
109+
return PreActResNet(PreActBottleneck, [3,4,23,3])
110+
111+
def PreActResNet152():
112+
return PreActResNet(PreActBottleneck, [3,8,36,3])
113+
114+
115+
def test():
116+
net = PreActResNet18()
117+
y = net((torch.randn(1,3,32,32)))
118+
print(y.size())
119+
120+
# test()

0 commit comments

Comments
 (0)