Pytorch中register_forward_hook的用法

本文介绍了PyTorch中钩子(hook)的概念,它允许用户在nn.Module对象的forward和backward方法执行前后插入自定义操作。通过示例展示了如何使用register_forward_hook注册一个hook来打印线性层的权重、偏置、输入和输出。此外,还提供了一个保存ResNet34前向过程中所有卷积层输出的示例,演示了hook在捕获中间结果方面的实用性。
Qwen3-32B-Chat 私有部署镜像 | RTX4090D 24G 显存 CUDA12.4 优化版

本镜像基于 RTX 4090D 24GB 显存 + CUDA 12.4 + 驱动 550.90.07 深度优化,内置完整运行环境与 Qwen3-32B 模型依赖,开箱即用。

一个hook是一个可调用对象,可以通过不同的方式注册到任意nn.Module对象上,当module的触发方法比如(forward()backward())被调用后,module本身以及其输入和输出被传递给hook并触发调用。

比如当一个hook通过torch.nn.Module.register_forward_hook()的方式注册到一个module上时,每次其forward函数计算出其输出之后紧接着调用hook。

hook的参数形式是固定的 hook(module, input, output) -> None or modified output,参数名是任意的,传入的参数分别是module本身对象、该module forward前的输入、该module forward后的输出。

hook常用于捕获中间过程,如下是一个简单的例子

import torch
from torch import nn


def forward_hook_fn(module, input, output):
    print('weight', module.weight.data)
    print('bias', module.bias.data)
    print('input', input)
    print('output', output)


class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.fc = nn.Linear(3, 1)
        self.fc.register_forward_hook(forward_hook_fn)
        if hasattr(self.fc, 'weight') and self.fc.weight is not None:
            nn.init.constant_(self.fc.weight, 1)
        if hasattr(self.fc, 'bias') and self.fc.bias is not None:
            nn.init.constant_(self.fc.bias, 0)

    def forward(self, x):
        o = self.fc(x)
        return o


if __name__ == '__main__':
    model = Model()
    x = torch.Tensor([[0.0, 1.0, 2.0]])
    y = model(x)

# 输出
weight: tensor([[1., 1., 1.]])
bias: tensor([0.])
input: (tensor([[0., 1., 2.]]),)
output: tensor([[3.]], grad_fn=<AddmmBackward0>)

下面是另一个例子,保存resnet34一次前向过程中所有卷积层的输出

import torch
from torchvision.models import resnet34


device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')

model = resnet34(pretrained=True)
model = model.to(device)


class SaveOutput:
    def __init__(self):
        self.outputs = []

    def __call__(self, module, module_in, module_out):
        self.outputs.append(module_out)

    def clear(self):
        self.outputs = []


save_output = SaveOutput()

hook_handles = []

for layer in model.modules():
    if isinstance(layer, torch.nn.modules.conv.Conv2d):
        handle = layer.register_forward_hook(save_output)
        hook_handles.append(handle)


from PIL import Image
from torchvision import transforms as T


image = Image.open('cat.jpg')
transform = T.Compose([T.Resize((224, 224)), T.ToTensor()])
X = transform(image).unsqueeze(dim=0).to(device)

out = model(X)
print(len(save_output.outputs))

# 输出
# 36

参考

How hooks can improve your workflow significantly 

Module — PyTorch 1.11.0 documentation

MMCV 核心组件分析(六): Hook - 知乎 

您可能感兴趣的与本文相关的镜像

Qwen3-32B-Chat 私有部署镜像 | RTX4090D 24G 显存 CUDA12.4 优化版

Qwen3-32B-Chat 私有部署镜像 | RTX4090D 24G 显存 CUDA12.4 优化版

Qwen
文本生成
Qwen3

本镜像基于 RTX 4090D 24GB 显存 + CUDA 12.4 + 驱动 550.90.07 深度优化,内置完整运行环境与 Qwen3-32B 模型依赖,开箱即用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

00000cj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值