Pytorch hook(钩子函数)

# example 
# 定义用于获取网络各层输入输出tensor的容器,并定义module_name用于记录相应的module名字
module_name = []
features_in_hook = []
features_out_hook = []

# hook函数负责将获取的输入输出添加到feature列表中,并提供相应的module名字
# fea_in当前forward 的输入,fea_out当前forward的输出
def hook(module, fea_in, fea_out):  # hook,自己定义钩子函数的名字
    print("hooker working")
    module_name.append(module.__class__)
    features_in_hook.append(fea_in)
    features_out_hook.append(fea_out)
    return None
# children()与modules()都是返回网络模型里的组成元素,
# 但是children()返回的是最外层的元素,modules()返回的是所有的元素,包括不同级别的子元素。
net = TestForHook()
net_chilren = net.children()
for child in net_chilren:
    if not isinstance(child, nn.ReLU6):
        # register_forward_hook, pytorch 提供钩子注册函数
        child.register_forward_hook(hook=hook)

 

### 如何在 PyTorch 中使用 Hooks 与 Transformer 模型进行交互或调试 Hooks 是一种强大的工具,允许开发者访问神经网络中的中间层输出以及梯度信息。这在调试模型行为、分析特征图或者实现自定义训练逻辑时非常有用。 #### 使用前向 Hook 获取激活值 可以通过注册 `forward_hook` 来捕获特定模块的输入和输出数据。以下是如何在一个简单的 Transformer 模型上应用 forward hook 的例子: ```python import torch.nn as nn from transformers import AutoModel, AutoTokenizer # 加载预训练的Transformer模型 model = AutoModel.from_pretrained("bert-base-uncased") def forward_hook(module, input, output): """定义一个钩子函数来记录每一层的输出""" print(f"Module Output Shape: {output.shape}") # 注册hook到指定层(例如BERT的第一层) first_layer = model.encoder.layer[0] handle = first_layer.register_forward_hook(forward_hook) # 准备一些输入数据 tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased") inputs = tokenizer("Hello world!", return_tensors="pt") # 前向传递并触发hook outputs = model(**inputs) ``` 上述代码展示了如何为 BERT 编码器的第一个变压器层设置一个 forward hook[^1]。每当该层被调用时,都会执行我们定义好的回调函数 `forward_hook` 并打印出它的输出张量形状。 #### 使用反向 Hook 访问梯度 除了监控正向传播外,还可以利用 backpropagation 过程中的 gradient information 。这里展示了一个简单的方法去获取某一层权重更新期间产生的梯度: ```python grad_outputs = None def backward_hook(module, grad_input, grad_output): global grad_outputs grad_outputs = grad_output last_layer = list(model.children())[-1].register_backward_hook(backward_hook) loss_fn = nn.CrossEntropyLoss() labels = torch.tensor([random.randint(0,9)]).unsqueeze(dim=0) # 随机标签作为示例 logits = outputs.logits loss = loss_fn(logits.view(-1, logits.size(-1)), labels.view(-1)) loss.backward() print(grad_outputs) ``` 此部分说明了怎样通过 backward hook 获得最后一层计算损失后的梯度情况。注意这里的 `global` 关键字仅用于演示目的,在实际项目里推荐采用更优雅的方式存储这些变量。 #### 结合 DeepSpeed 提升性能 当面对大规模 Transformer 模型时,可以考虑引入 **DeepSpeed** 库优化资源利用率及加速训练过程。它支持多种功能比如混合精度训练(Mixed Precision Training),ZeRO optimizer 等等[^2]。不过需要注意的是,如果要在启用零冗余优化器(ZeRO Optimizer Stage >=2 )的情况下操作参数,则需额外小心因为此时各进程间共享内存区域可能发生变化从而影响常规hooks的行为模式。 另外关于分布式推理方面也有提及[^3],虽然主要讨论的是不同GPU分配任务场景下的pipeline管理策略而非具体挂钩技术细节,但对于理解整体架构设计思路仍然有所帮助。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值