Multi output resent + foolbox.models.PyTorchModel

In my main ResNet block as below:

class ResNet(nn.Module):
    def __init__(self, block, num_blocks, num_classes=10):
        super(ResNet, self).__init__()
        self.in_planes = 64

        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(64)
        self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)
        self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)
        self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)
        self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)
        self.linear = nn.Linear(512*block.expansion, num_classes)

    def _make_layer(self, block, planes, num_blocks, stride):
        strides = [stride] + [1]*(num_blocks-1)
        layers = []
        for stride in strides:
            layers.append(block(self.in_planes, planes, stride))
            self.in_planes = planes * block.expansion
        return nn.Sequential(*layers)

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.layer1(out)
        out = self.layer2(out)
        out = self.layer3(out)
        out = self.layer4(out)
        out = F.avg_pool2d(out, 4)
        out0 = out.view(out.size(0), -1)
        out = self.linear(out0)
        return out, out0

I want to output two last layers, i.e. out & out0 here.
In my main code I try to use foolbox for say fgsm attack. So just giving a few lines I have:

fmodel_source = foolbox.models.PyTorchModel(model, bounds=(0, 1), num_classes=10, preprocessing=(0, 1))
attack = foolbox.attacks.GradientSignAttack(model=fmodel_source, criterion=attack_criteria)

Then trying to execute the line
adversarial = attack(inputs.astype(np.float32), targets, max_epsilon=config['epsilon'])

I get error that
File “anaconda36/lib/python3.6/site-packages/foolbox/models/pytorch.py”, line 94, in batch_predictions
predictions = predictions.to(“cpu”)
AttributeError: ‘tuple’ object has no attribute ‘to’

Is there a way I get around this and still have the last two layers outputs from the ResNet but don’t change the foolbox under pytorch.py?

Any suggestions?

1 Like

I’m not familiar with foolbox, but it seems as if the attack expects your model to output a single tensor, while your model outputs two.
If you don’t need out0 for the training (or something else), just remove it from the return statement.

1 Like