使用PyTorch的CNN架构中的高阶导数w.r.t.奇异特征Map

2fjabf4q  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(90)

我正试图为CNN实现XAI方法,为此我想访问输出w.r.t.的高阶导数到卷积层产生的每个特征图。PyTorch提供了一种访问和存储一阶梯度的好方法,根据我的理解,我将能够使用这些来计算高阶导数,因为我一直保留着我的图。但是当执行下面的代码时,它为我提供了None类型的结果。

def forward(self, x):
        x.requires_grad_(True)
        x1 = self.inc(x)
        x2 = self.down1(x1)
        _ = x2.register_hook(lambda grad: self._save_gradients(grad,x2))  # gradient hook
#... for each layer of interest

    def _save_gradients(self, grad, feat):
        self.gradients_list.append(grad.data.numpy())

        second_order_grad = torch.autograd.grad(grad, feat, retain_graph=True,     grad_outputs=torch.ones_like(grad), allow_unused=True)
        print(second_order_grad)
        self.gradients_2_list.append(second_order_grad[0].data.numpy())

        third_order_grad = torch.autograd.grad(second_order_grad, feat, retain_graph=True, grad_outputs=torch.ones_like(second_order_grad), allow_unused=True)
        print(second_order_grad)
        self.gradients_3_list.append(third_order_grad[0].data.numpy())

字符串
现在我已经尝试了不同的autograd应用程序,但它们似乎不能识别图形,或者对高阶导数产生None类型的输出。

qxgroojn

qxgroojn1#

看起来使用钩子会将生成的梯度与计算图断开连接。按照下面的方法修改代码可以让我在访问梯度和更高阶梯度的同时保持图的完整性。

...
    x3 = self.down2(x2)
    x3.requires_grad_(True)
    self.features["down2"] = x3

    x4 = self.down3(x3)
    x4.requires_grad_(True)
    self.features["down3"] = x4
    
    x5 = self.down4(x4)
    x5.requires_grad_(True)
    self.features["down4"] = x5
    ...

字符串

def calc_gradients(self, score):

    for name in self.features:
        print(name)
        grad = torch.autograd.grad(score, self.features[name], grad_outputs=torch.ones_like(score), retain_graph=True, create_graph=True)
        self.gradients[name] = grad
        print(name, "grad_2")
        grad_2 = torch.autograd.grad(grad, self.features[name], grad_outputs=torch.ones_like(grad[0]), retain_graph=True, create_graph=True)
        self.gradients_2[name] = grad_2[0]
        print(name, "grad_3")
        try:
            grad_3 = torch.autograd.grad(grad_2, self.features[name], grad_outputs=torch.ones_like(grad_2[0]), retain_graph=True)
            self.gradients_3[name] = grad_3
        except:
            grad_3 = torch.autograd.grad(grad_2, self.features[name], grad_outputs=torch.ones_like(grad_2[0]), retain_graph=True, allow_unused=True)
            self.gradients_3[name] = (torch.zeros_like(grad_2[0]),)
        print(name, "Made it through")

相关问题