| 2 | |
| 3 | |
| 4 | class DiffAugPGDAttacker(): |
| 5 | def __init__(self, samp_num, trans, |
| 6 | radius, steps, step_size, random_start, ascending=True): |
| 7 | self.samp_num = samp_num |
| 8 | self.trans = trans |
| 9 | |
| 10 | self.radius = radius / 255. |
| 11 | self.steps = steps |
| 12 | self.step_size = step_size / 255. |
| 13 | self.random_start = random_start |
| 14 | self.ascending = ascending |
| 15 | |
| 16 | def perturb(self, model, criterion, x, y): |
| 17 | ''' initialize noise ''' |
| 18 | delta = torch.zeros_like(x.data) |
| 19 | if self.steps==0 or self.radius==0: |
| 20 | return delta |
| 21 | |
| 22 | if self.random_start: |
| 23 | delta.uniform_(-self.radius, self.radius) |
| 24 | |
| 25 | ''' temporarily shutdown autograd of model to improve pgd efficiency ''' |
| 26 | model.eval() |
| 27 | for pp in model.parameters(): |
| 28 | pp.requires_grad = False |
| 29 | |
| 30 | delta.requires_grad_() |
| 31 | for step in range(self.steps): |
| 32 | delta.grad = None |
| 33 | |
| 34 | for i in range(self.samp_num): |
| 35 | adv_x = (self.trans(x) + delta).clamp(0., 255.) |
| 36 | _y = model(adv_x) |
| 37 | lo = criterion(_y, y) |
| 38 | lo.backward() |
| 39 | |
| 40 | with torch.no_grad(): |
| 41 | grad = delta.grad.data |
| 42 | if not self.ascending: grad.mul_(-1) |
| 43 | delta.add_(torch.sign(grad), alpha=self.step_size) |
| 44 | delta.clamp_(-self.radius, self.radius) |
| 45 | |
| 46 | ''' reopen autograd of model after pgd ''' |
| 47 | for pp in model.parameters(): |
| 48 | pp.requires_grad = True |
| 49 | |
| 50 | return delta.data |
nothing calls this directly
no outgoing calls
no test coverage detected