_register_hook

Escriba un título de catálogo personalizado aquí

1. Introducción

Dado que existen pasos para extraer la información de la capa intermedia del modelo en CAM y Grad-cam, es necesario utilizar el mecanismo de gancho.

Tipo de anzuelo:

  • nivel tensor
  • nivel de módulo

2 ganchos de nivel tensor

La función de register_hook: al derivar x, opere en la derivada de x, y los parámetros de register_hook solo se pueden pasar en forma de función.

Aquí hay una castaña:
# Situación de derivación normal

实验一:tensor.register_hook()可以改变反向传播梯度值,对导数进行2倍操作
v = torch.randn((1, 3), dtype=torch.float32, requires_grad=True)
z = v.sum()
z.backward()
print(v.grad)
实验一输出:
tensor([[1., 1., 1.]])
实验一对照组
v = torch.randn((1, 3), dtype=torch.float32, requires_grad=True)
z = v.sum()
v.register_hook(lambda grad: grad*2)
z.backward()
print(v.grad)
tensor([[2., 2., 2.]]) ##实验一对照组 新的改变
实验二:tensor级别的register_hook函数,影响了整个模型的grad
x=Variable(torch.FloatTensor([[1, 2, 3]]),requires_grad=True)
mod=nn.Linear(3, 1, bias=False)

out=mod(x)
out.register_hook(lambda grad: 0.1*grad) #在这里给variable注册了 hook
out.backward()
print('*'*20)
print("x.grad", x.grad)
print(mod.weight.grad)
实验二输出
********************
x.grad tensor([[ 0.0091, -0.0202, -0.0334]]) # 增加了0.1倍
tensor([[0.1000, 0.2000, 0.3000]]) #  增加了0.1倍
实验二对照实验:无hook
x=Variable(torch.FloatTensor([[1, 2, 3]]),requires_grad=True)
mod=nn.Linear(3, 1, bias=False)
# mod.register_backward_hook(bh) # 在这里给module注册了backward hook

out=mod(x)
# out.register_hook(lambda grad: 0.1*grad) #在这里给variable注册了 hook
out.backward()
print('*'*20)
print("x.grad", x.grad)
print(mod.weight.grad)
实验二对照实验输出
********************
x.grad tensor([[0.5737, 0.3620, 0.4793]]) # 正常梯度
tensor([[1., 2., 3.]])

Gancho de nivel de 3 módulos

实验三:module级别的register_hook函数,影响了整个模型的grad
import torch
from torch.autograd import Variable
from torch.nn import Parameter
import torch.nn as nn
import math
def bh(m,gi,go):
    print("Grad Input")
    print(gi)
    print("Grad Output")
    print(go)
    return gi[0]*0,gi[1]*0
x=Variable(torch.FloatTensor([[1, 2, 3]]),requires_grad=True)
mod=nn.Linear(3, 1, bias=False)
mod.register_backward_hook(bh) # 在这里给module注册了backward hook

out=mod(x)
#out.register_hook(lambda grad: 0.1*grad) #在这里给variable注册了 hook
out.backward()
print('*'*20)
print("x.grad", x.grad)
print(mod.weight.grad)
实验三输出:
Grad Input
(tensor([[ 0.4894, -0.0671,  0.1403]]), tensor([[1.],
        [2.],
        [3.]]))
Grad Output
(tensor([[1.]]),)
********************
x.grad tensor([[0., -0., 0.]]) # 梯度为0 ,因为bh函数的设置:return gi[0]*0,gi[1]*0
tensor([[0., 0., 0.]])

El experimento anterior afecta la propagación inversa del gradiente, o puede que no afecte:

实验三对照实验
def bh(m,gi,go):
    print("Grad Input")
    print(gi)
    print("Grad Output")
    print(go)

x=Variable(torch.FloatTensor([[1, 2, 3]]),requires_grad=True)
mod=nn.Linear(3, 1, bias=False)
mod.register_backward_hook(bh) # 在这里给module注册了backward hook

out=mod(x)
out.backward()
print('*'*20)
print("x.grad", x.grad)
print(mod.weight.grad)
Grad Input
(tensor([[-0.0587,  0.2710, -0.1430]]), tensor([[1.],
        [2.],
        [3.]]))
Grad Output
(tensor([[1.]]),)
********************
x.grad tensor([[-0.0587,  0.2710, -0.1430]])
tensor([[1., 2., 3.]])

Además, parece que cuando se utiliza un gancho de nivel de módulo, debe prestar atención a que este módulo no puede ser uno:
registre un gancho de bachward en el módulo. Este método solo se puede usar en el módulo en este momento, no en el contenedor. Cuando solo hay una función en la función de avance del módulo, se llama Módulo. Si el módulo contiene otros módulos, se llama contenedor. Ver
https: // blog .csdn.net/u012436149/article/details/69230136?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utmlog_source=dislebonevantte.pc.danlog_source=dislebonevantte.pc.dan_relevant

Supongo que te gusta

Origin blog.csdn.net/qq_43110298/article/details/109622916
Recomendado
Clasificación