Closed codingwolfman closed 5 years ago
Hi, yeah it is possible, you'll need define a ensemble_predict
function like this and pass it to the adversary's predict
def ensemble_predict(data):
return model_1(data) + model_2(data) + model_3(data)
here I assume model_i (data)
outputs the logits (layer before softmax)
Is this something that you're looking for? @codingwolfman
@gwding yeah, i see, thanks a lot
@gwding when i try to use ensemble attack , i meet this error, RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.
i can't understand this, i think i just backward through the graph once, my code is as follows class EnsembleModel(torch.nn.Module): def init(self,models): super(EnsembleModel,self).init() self.models = models self.out = torch.zeros((1,110)).to('cuda:0') def forward(self, x): for model in self.models: self.out += model(x) return self.out/len(self.models)
def generate_data(models, device, test_loader):
# Accuracy counter
correct = 0
init_correct = 0
widgets = ['test:',Percentage(), ' ', Bar('#'),' ', Timer(),
' ', ETA(), ' ', FileTransferSpeed()]
pbar = ProgressBar(widgets=widgets)
ensemble_model = EnsembleModel(models)
ensemble_model.to(device)
#momentums = [MomentumIterativeAttack(model,F.nll_loss) for model in models]
attack = FGSM(predict=ensemble_model,loss_fn=F.cross_entropy,clip_min=-1,clip_max=1)
#attacks = [LinfBasicIterativeAttack(model, F.nll_loss) for model in models]
# Loop over all examples in test set
for data, target, image_path in pbar(test_loader):
# Send the data and label to the device
data, target = data.to(device), target.to(device)
# Set requires_grad attribute of tensor. Important for Attack
data.requires_grad = True
# Forward pass the data through the model
output = ensemble_model(data)
init_pred = output.max(1, keepdim=True)[1] # get the index of the max log-probability
image_path = image_path[0].replace('/origin_examples/', '/ifgsm_incepv3_incepv1_data/')
_dir, filename = os.path.split(image_path)
if not os.path.exists(_dir):
os.makedirs(_dir)
if init_pred.item() != target.item():
perturbed_data = data
else:
init_correct += 1
perturbed_data = attack.perturb(data,target)
image = Image.fromarray(np.uint8((perturbed_data.squeeze().detach().cpu().numpy() * 0.5 + 0.5) * 255).transpose((1, 2, 0)))
image.save(image_path)
output = ensemble_model(perturbed_data)
# Check for success
final_pred = output.max(1, keepdim=True)[1] # get the index of the max log-probability
if final_pred.item() == target.item():
correct += 1
# Calculate final accuracy for this epsilon
final_acc = correct/float(len(test_loader))
origin_acc = init_correct/float(len(test_loader))
print("Test Accuracy = {} / {} = {}".format(correct, len(test_loader), final_acc))
print("Origin Accuracy = {} / {} = {}".format(init_correct, len(test_loader), origin_acc))
@codingwolfman it looks ok for me, unless you have repeated a model in models
?
could you make a script that I can directly run and reproduce the error? (doesn't involve loading files and etc) so i can try to reproduce the problem
@codingwolfman I'm closing this issue for now. Please reopen if the problem persists.
the parameter of attack is like MomentumIterativeAttack(model,F.nll_loss),could i pass a list of model to this???