有两种方法可以解决这个问题:
第一
for name, param in model.named_parameters():
if 'weight' in name:
temp = torch.zeros(param.grad.shape)
temp[param.grad != 0] += 1
count_dict[name] += temp
此步骤在您在培训模块中的loss.backward() 步骤之后进行。 count_dict[name] 字典跟踪梯度更新。你可以在训练开始之前这样初始化它:
for name, param in model.named_parameters():
if 'weight' in name:
count_dict[name] = torch.zeros(param.grad.shape)
现在还有一种方法是注册一个钩子函数,然后创建钩子函数,您甚至可以在其中更新或修改渐变(如果需要)。这不是跟踪权重更新所必需的,但是如果你想对梯度做一些事情,它就派上用场了。
假设,我在这里随机稀疏渐变。
def hook_fn(grad):
'''
Randomly sparsify the gradients
:param grad: Input gradient of the layer
:return: grad_clone - the sparsified FC layer gradients
'''
grad_clone = grad.clone()
temp = torch.cuda.FloatTensor(grad_clone.shape).uniform_()
grad_clone[temp < 0.8] = 0
return grad_clone
在这里我给模型一个钩子。
for name, param in model.named_parameters():
if 'weight' in name:
param.register_hook(hook_fn)
所以,这可能只是为您稀疏渐变,您可以通过这种方式在挂钩函数本身中跟踪渐变:
def hook_func(module, input, output):
temp = torch.zeros(output.shape)
temp[output != 0] += 1
count_dict[module] += temp
虽然,我不建议这样做。这在可视化前向传递特征/激活的情况下通常很有用。而且,输入和输出可能会混淆,因为梯度和参数输入和输出是相反的。