Python中求梯度的奇怪现象

在使用pytorch循环求梯度时,发现以下现象

for i in range(self.steps):
	adv_images.requires_grad = True

	# 下面这行代码会使得求梯度时,对象由上面一行转移到下面一行
    adv_images = self.input_diversity(adv_images)
	outputs = self.get_logits(adv_images)
    
	# Calculate loss
	if self.targeted:
	    cost = -loss(outputs, target_labels)
	else:
	    cost = loss(outputs, labels)

	# Update adversarial images
	grad = torch.autograd.grad(cost, adv_images,
	                           retain_graph=False, create_graph=False)[0]

	with torch.no_grad():
	    pred = torch.argmax(outputs.detach(), dim=1)
	    is_equal_list.append((pred == labels).cpu())

	grad = grad / torch.mean(torch.abs(grad), dim=(1,2,3), keepdim=True)
	grad = grad + momentum*self.decay
	momentum = grad

	adv_images = adv_images.detach() + self.alpha*grad.sign()
	delta = torch.clamp(adv_images - images, min=-self.eps, max=self.eps)
	adv_images = torch.clamp(images + delta, min=0, max=1).detach()

上面代码求出的梯度有误,猜测原因可能是self.input_diversity赋予的新变量adv_images会影响后续求梯度,grad是对进行变换后的样本求的,而不是针对最开始的样本求的。

for i in range(self.steps):
	adv_images.requires_grad = True
	
    # solution 1 
	adv_images1 = self.input_diversity(adv_images)
	outputs = self.get_logits(adv_images1)
	# solution 2
	# outputs = self.get_logits(self.input_diversity(adv_images))

    # Calculate loss
	if self.targeted:
	    cost = -loss(outputs, target_labels)
	else:
	    cost = loss(outputs, labels)

	# Update adversarial images
	grad = torch.autograd.grad(cost, adv_images,
	                           retain_graph=False, create_graph=False)[0]

	with torch.no_grad():
	    pred = torch.argmax(outputs.detach(), dim=1)
	    is_equal_list.append((pred == labels).cpu())

	grad = grad / torch.mean(torch.abs(grad), dim=(1,2,3), keepdim=True)
	grad = grad + momentum*self.decay
	momentum = grad

	adv_images = adv_images.detach() + self.alpha*grad.sign()
	delta = torch.clamp(adv_images - images, min=-self.eps, max=self.eps)
	adv_images = torch.clamp(images + delta, min=0, max=1).detach()
Table of Contents