pytorch hook学习

register_hook

import torch
x = torch.Tensor([0,1,2,3]).requires_grad_()
y = torch.Tensor([4,5,6,7]).requires_grad_()
w = torch.Tensor([1,2,3,4]).requires_grad_()
z = x+y;
o = w.matmul(z) # o = w(x+y) 中间变量z
o.backward()
print(x.grad,y.grad,z.grad,w.grad,o.grad)

这里的o和z都是中间变量,不是通过指定值来定义的变量,所以是中间变量,所以pytorch并不存储这些变量的梯度。

对于中间变量z,hook的使用方式为: z.register_hook(hook_fn),其中 hook_fn为一个用户自定义的函数,其签名为:hook_fn(grad) -> Tensor or None。

它的输入为变量 z 的梯度,输出为一个 Tensor 或者是 None (None 一般用于直接打印梯度)。反向传播时,梯度传播到变量 z,再继续向前传播之前,将会传入 hook_fn。如果 hook_fn的返回值是 None,那么梯度将不改变,继续向前传播,如果 hook_fn的返回值是 Tensor 类型,则该 Tensor 将取代 z 原有的梯度,向前传播。

import torch
x = torch.Tensor([0,1,2,3]).requires_grad_()
y = torch.Tensor([4,5,6,7]).requires_grad_()
w = torch.Tensor([1,2,3,4]).requires_grad_()
z = x+y;
def hook_fn(grad):
print(grad)
return None z.register_hook(hook_fn)
o = w.matmul(z) # o = w(x+y) 中间变量z
o.backward()
print(x.grad,y.grad,w.grad,z.grad,o.grad)

register_forward_hook

register_forward_hook的作用是获取前向传播过程中,各个网络模块的输入和输出。对于模块 module,其使用方式为:module.register_forward_hook(hook_fn) 。其中 hook_fn的签名为:

hook_fn(module, input, output) -> None

eg

import torch
from torch import nn
class Model(nn.Module):
def __init__(self):
super(Model,self).__init__()
self.fc1 = nn.Linear(3,4) # WT * X + bias
self.relu1 = nn.ReLU()
self.fc2 = nn.Linear(4,1)
self.init()
def init(self):
with torch.no_grad():
# WT * X + bias,所以W为4*3的矩阵,bias为1*4
self.fc1.weight = torch.nn.Parameter(
torch.Tensor([[1., 2., 3.],
[-4., -5., -6.],
[7., 8., 9.],
[-10., -11., -12.]]))
self.fc1.bias = torch.nn.Parameter(torch.Tensor([1.0, 2.0, 3.0, 4.0]))
self.fc2.weight = torch.nn.Parameter(torch.Tensor([[1.0, 2.0, 3.0, 4.0]]))
self.fc2.bias = torch.nn.Parameter(torch.Tensor([1.0])) def forward(self,x):
o = self.fc1(x)
o = self.relu1(o)
o = self.fc2(o)
return o
def hook_fn_forward(module,input,output):
print(module)
print(input)
print(output) model = Model()
modules = model.named_children()
'''
named_children()
Returns an iterator over immediate children modules, yielding both the name of the module as well as the module itself.
'''
for name,module in modules:
# 这里的name就是自己定义的self.xx的xx。如上面的fc1,fc2.
# module代指的就是fc1代表的module等等
module.register_forward_hook(hook_fn_forward)
x = torch.Tensor([[1.0,1.0,1.0]]).requires_grad_()
o = model(x)
o.backward()
'''
Linear(in_features=3, out_features=4, bias=True)
(tensor([[1., 1., 1.]], requires_grad=True),)
tensor([[ 7., -13., 27., -29.]], grad_fn=<AddmmBackward>)
ReLU()
(tensor([[ 7., -13., 27., -29.]], grad_fn=<AddmmBackward>),)
tensor([[ 7., 0., 27., 0.]], grad_fn=<ReluBackward0>)
Linear(in_features=4, out_features=1, bias=True)
(tensor([[ 7., 0., 27., 0.]], grad_fn=<ReluBackward0>),)
tensor([[89.]], grad_fn=<AddmmBackward>) '''

register_backward_hook

理同前者。得到梯度值。

hook_fn(module, grad_input, grad_output) -> Tensor or None

上面的代码forward全部替换为backward,结果为:

'''
Linear(in_features=4, out_features=1, bias=True)
(tensor([1.]), tensor([[1., 2., 3., 4.]]), tensor([[ 7.],
[ 0.],
[27.],
[ 0.]]))
(tensor([[1.]]),)
ReLU()
(tensor([[1., 0., 3., 0.]]),)
(tensor([[1., 2., 3., 4.]]),)
Linear(in_features=3, out_features=4, bias=True)
(tensor([1., 0., 3., 0.]), tensor([[22., 26., 30.]]), tensor([[1., 0., 3., 0.],
[1., 0., 3., 0.],
[1., 0., 3., 0.]]))
(tensor([[1., 0., 3., 0.]]),)
'''

register_backward_hook只能操作简单模块,而不能操作包含多个子模块的复杂模块。 如果对复杂模块用了 backward hook,那么我们只能得到该模块最后一次简单操作的梯度信息。

可以这么用,可以得到一个模块的梯度。

class Mymodel(nn.Module):
...... model = Mymodel()
model.register_backward_hook(hook_fn_backward)

[torch] pytorch hook学习的更多相关文章

  1. pytorch例子学习-DATA LOADING AND PROCESSING TUTORIAL

    参考:https://pytorch.org/tutorials/beginner/data_loading_tutorial.html DATA LOADING AND PROCESSING TUT ...

  2. [pytorch] PyTorch Hook

      PyTorch Hook¶ 为什么要引入hook? -> hook可以做什么? 都有哪些hook? 如何使用hook?   1. 为什么引入hook?¶ 参考:Pytorch中autogra ...

  3. 【pytorch】学习笔记(三)-激励函数

    [pytorch]学习笔记-激励函数 学习自:莫烦python 什么是激励函数 一句话概括 Activation: 就是让神经网络可以描述非线性问题的步骤, 是神经网络变得更强大 1.激活函数是用来加 ...

  4. 【pytorch】学习笔记(二)- Variable

    [pytorch]学习笔记(二)- Variable 学习链接自莫烦python 什么是Variable Variable就好像一个篮子,里面装着鸡蛋(Torch 的 Tensor),里面的鸡蛋数不断 ...

  5. PyTorch迁移学习-私人数据集上的蚂蚁蜜蜂分类

    迁移学习的两个主要场景 微调CNN:使用预训练的网络来初始化自己的网络,而不是随机初始化,然后训练即可 将CNN看成固定的特征提取器:固定前面的层,重写最后的全连接层,只有这个新的层会被训练 下面修改 ...

  6. PyTorch深度学习实践——反向传播

    反向传播 课程来源:PyTorch深度学习实践--河北工业大学 <PyTorch深度学习实践>完结合集_哔哩哔哩_bilibili 目录 反向传播 笔记 作业 笔记 在之前课程中介绍的线性 ...

  7. PyTorch深度学习实践——多分类问题

    多分类问题 目录 多分类问题 Softmax 在Minist数据集上实现多分类问题 作业 课程来源:PyTorch深度学习实践--河北工业大学 <PyTorch深度学习实践>完结合集_哔哩 ...

  8. PyTorch深度学习实践——处理多维特征的输入

    处理多维特征的输入 课程来源:PyTorch深度学习实践--河北工业大学 <PyTorch深度学习实践>完结合集_哔哩哔哩_bilibili 这一讲介绍输入为多维数据时的分类. 一个数据集 ...

  9. 对比学习:《深度学习之Pytorch》《PyTorch深度学习实战》+代码

    PyTorch是一个基于Python的深度学习平台,该平台简单易用上手快,从计算机视觉.自然语言处理再到强化学习,PyTorch的功能强大,支持PyTorch的工具包有用于自然语言处理的Allen N ...

随机推荐

  1. CF1090H Linearization

    传送门 先考虑什么样的串才符合条件.\(s_i=P(x\&i)\oplus b\),其实这里的\(b\)只能使得整体是否取反,所以可以先不管.然后考虑\(x\)的每个二进制位的对\(s_0\) ...

  2. Echarts-数据的视觉映射

    来源:官网,自己整理 数据可视化是 数据 到 视觉元素 的映射过程(这个过程也可称为视觉编码,视觉元素也可称为视觉通道). ECharts 的每种图表本身就内置了这种映射过程,比如折线图把数据映射到『 ...

  3. XXE漏洞攻击与防御

    转自https://www.jianshu.com/p/7325b2ef8fc9 0x01 XML基础 在聊XXE之前,先说说相关的XML知识吧. 定义 XML用于标记电子文件使其具有结构性的标记语言 ...

  4. 十三、LaTex中的参考文献BibTex

    将默认文献工具设置为bibtex

  5. 2019-11-29-git无法pull仓库refusing-to-merge-unrelated-histories

    title author date CreateTime categories git无法pull仓库refusing to merge unrelated histories lindexi 201 ...

  6. 这才是最完美SSD:性能满血发挥 万里挑一

    固态硬盘同质化日益严重,不同品牌的固态盘想要一决高下就只有靠品牌口碑与做工硬实力了. 最近影驰对他们的ONE系列固态硬盘产品进行了一波更新,推出了多种容量的ONE PCIe M.2 SSD,今天我们就 ...

  7. 如何在 Visual C# 中执行基本的文件 I/O

    演示文件 I/O 操作 本文中的示例讲述基本的文件 I/O 操作.“分步示例”部分说明如何创建一个演示下列六种文件 I/O 操作的示例程序: 注意:如果要直接使用下列示例代码,请注意下列事项: 必须包 ...

  8. web框架-(五)Ajax

    Ajax即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术,AJAX = 异步 JavaScript和X ...

  9. 【学习】024 springCloud

    单点系统架构 传统项目架构 传统项目分为三层架构,将业务逻辑层.数据库访问层.控制层放入在一个项目中. 优点:适合于个人或者小团队开发,不适合大团队开发. 分布式项目架构 根据业务需求进行拆分成N个子 ...

  10. AI应该享有与动物一样的权利吗?

    全世界的大学都在进行人工智能(AI)的重大研究,艾伦研究所(Allen Institute)等组织以及Google和Facebook等高科技公司.可能的结果是,我们很快将拥有与小鼠或狗一样高的认知能力 ...