用于衡量令牌重要性的 DistilBERT 损失梯度

Gradient of the loss of DistilBERT for measuring token importance

我正在尝试访问 DistilBERT 中关于第一层中每个注意力权重的损失梯度。当 requires_grad=True

时,我可以通过以下代码访问输出权重矩阵的计算梯度值
loss.backward()
for name, param in model.named_parameters():
    if name == 'transformer.layer.0.attention.out_lin.weight':
       print(param.grad)  #shape is [768,768]

其中 model 是加载的 distilbert 模型。 我的问题是如何获得关于 [SEP] 或 [CLS] 或其他令牌注意力的梯度?我需要它来重现下面 link 中关于 "Gradient-based feature importance estimates for attention to [SEP]" 的数字: https://medium.com/analytics-vidhya/explainability-of-bert-through-attention-7dbbab8a7062

下面有人问过同样目的的类似问题,但这不是我的问题: BERT token importance measuring issue. Grad is none

默认只为参数保留梯度,基本上只是为了节省内存。如果你需要计算图内部节点的梯度,你需要在调用之前有各自的张量 backward() 并添加一个将在向后传递时执行的钩子。

来自PyTorch forum的最小解:

yGrad = torch.zeros(1,1)
def extract(xVar):
    global yGrad
    yGrad = xVar    

xx = Variable(torch.randn(1,1), requires_grad=True)
yy = 3*xx
zz = yy**2

yy.register_hook(extract)

#### Run the backprop:
print (yGrad) # Shows 0.
zz.backward()
print (yGrad) # Show the correct dzdy

在这种情况下,梯度存储在一个全局变量中,在 PyTorch 将它们从图形本身中去除后,它们仍然存在。