You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Hugging Face预训练LLM中获取特定注意力层与FFN层的梯度(类似CNN的Grad-CAM方式)?

如何在Hugging Face预训练LLM中获取特定注意力层与FFN层的梯度(类似CNN的Grad-CAM方式)?

当然可以做到!在Hugging Face的预训练LLM中获取特定注意力层或FFN层的梯度,进而实现类似CNN中Grad-CAM的效果,是完全可行的。下面我结合你提供的Phi-3代码,一步步给你讲清楚怎么做:

核心思路

要实现类似Grad-CAM的效果,我们需要:

  1. 开启PyTorch的梯度追踪模式(默认预训练模型在eval模式下会关闭梯度)
  2. 定位到目标层(特定注意力层/FFN层),用PyTorch的钩子机制捕获层的输出和梯度
  3. 定义一个明确的损失函数(梯度是基于损失反向传播得到的)
  4. 对梯度和层输出进行加权组合,得到类似热力图的结果

具体实现步骤(基于你的Phi-3代码)

1. 调整模型设置,开启梯度追踪

默认情况下,预训练模型加载后处于eval模式,梯度计算是关闭的。我们需要切换到train模式,但冻结所有参数(避免反向传播时不小心更新模型权重):

# 你的原有模型和tokenizer加载代码保持不变
tokenizer = AutoTokenizer.from_pretrained("microsoft/Phi-3-medium-4k-instruct")
model = AutoModelForCausalLM.from_pretrained(
    "microsoft/Phi-3-medium-4k-instruct",
    device_map="auto",
    torch_dtype=torch.float16,
    trust_remote_code=True
)

# 切换到train模式,开启梯度追踪
model.train()
# 冻结所有参数,只追踪梯度不更新权重
for param in model.parameters():
    param.requires_grad = False

2. 定位目标层并注册钩子

PyTorch的**钩子(Hook)**可以帮我们在模型前向/反向传播时,自动捕获目标层的输出和梯度。首先要确定你要关注的层的路径,Phi-3的每个Transformer层都包含:

  • 注意力模块:model.layers[N].self_attn(N是层索引,从0开始)
  • FFN(前馈网络)模块:model.layers[N].mlp

注册钩子保存层输出和梯度:

import torch.nn as nn

# 选择目标层:比如第5层的注意力层,你可以替换成任意层或FFN层
target_layer = model.layers[5].self_attn
# 如果要选FFN层,替换成:target_layer = model.layers[5].mlp

# 用于保存层输出和梯度的变量
layer_outputs = []
grads = []

# 前向钩子:保存层的输出特征
def forward_hook(module, input, output):
    # 注意力层的输出通常是元组(attn_output, attn_weights),我们取特征部分
    if isinstance(output, tuple):
        layer_outputs.append(output[0].detach())
    else:
        layer_outputs.append(output.detach())

# 反向钩子:保存层的梯度
def backward_hook(module, grad_input, grad_output):
    grads.append(grad_output[0].detach())

# 注册钩子
forward_handle = target_layer.register_forward_hook(forward_hook)
backward_handle = target_layer.register_backward_hook(backward_hook)

3. 准备输入并计算损失

梯度的方向完全由损失函数决定,我们需要根据需求定义损失。这里提供两种常用方式:

# 准备输入(和你原来的代码一致)
prompt = "Whats is the co-capital of Greece according to the country's public opinion?"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda:0")

# 运行模型获取logits
outputs = model(input_ids=inputs.input_ids, output_attentions=True)
logits = outputs.logits

# 方式1:用生成的token作为目标计算损失
# 先生成输出文本
generator = pipeline(
    "text-generation",
    model=model,
    tokenizer=tokenizer,
    return_full_text=False,
    max_new_tokens=100,
    do_sample=False
)
generated_output = generator(prompt)
generated_text = generated_output[0]["generated_text"]
# 把生成的文本转成token
generated_tokens = tokenizer(generated_text, return_tensors="pt").input_ids.to("cuda:0")

# 模型输入的长度是input_seq_len,我们取对应生成部分的logits
input_seq_len = inputs.input_ids.shape[1]
generated_logits = logits[:, input_seq_len-1:-1, :]  # 对应生成的每个token的logits
# 计算交叉熵损失
loss = nn.CrossEntropyLoss()(generated_logits.reshape(-1, logits.shape[-1]), generated_tokens.reshape(-1))

# 方式2:如果不需要生成,也可以直接针对输入最后一个token的logits计算损失(比如已知目标token)
# target_token = tokenizer.encode("Thessaloniki")[0]
# target_token = torch.tensor([target_token], device="cuda:0")
# last_logits = logits[:, -1, :]
# loss = nn.CrossEntropyLoss()(last_logits, target_token)

4. 反向传播获取梯度并生成类似Grad-CAM的热力图

# 反向传播计算梯度
loss.backward()

# 提取保存的梯度和层输出
grad = grads[0]
layer_out = layer_outputs[0]

# 类似Grad-CAM的处理:对梯度在序列维度做全局平均池化,得到权重alpha
# Phi-3的注意力层输出形状是(batch, seq_len, hidden_dim),所以对seq_len维度做平均
alpha = grad.mean(dim=1, keepdim=True)

# 用权重加权层输出,得到CAM热力图
cam = torch.sum(alpha * layer_out, dim=-1)
# 归一化到0-1区间,方便后续可视化
cam = torch.relu(cam)
cam = (cam - cam.min()) / (cam.max() - cam.min() + 1e-8)  # 加小值避免除零错误

# 现在可以把热力图和输入token对应起来可视化
input_tokens = tokenizer.convert_ids_to_tokens(inputs.input_ids[0])
cam_np = cam[0].cpu().numpy()  # 转成numpy数组用于画图

# 移除钩子,避免影响后续模型操作
forward_handle.remove()
backward_handle.remove()

关键注意事项

  • 模型结构适配:不同LLM(比如Llama、GPT-2)的层结构命名可能略有不同,你可以通过print(model)查看模型层级,找到正确的目标层路径。
  • 梯度追踪开关:必须确保模型在允许梯度计算的模式下(train模式或手动开启requires_grad),否则无法捕获梯度。
  • 损失的选择:梯度的方向完全由损失函数决定,你需要根据自己的需求定义损失(比如针对生成的某个token、输入的某个位置等)。
  • 钩子的移除:使用完钩子后记得移除,避免后续模型运行时重复捕获数据。

备注:内容来源于stack exchange,提问作者Jose Ramon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:39:35