| import torch
|
| import torch.nn.functional as F
|
| from transformers import AutoModelForCausalLM, AutoTokenizer
|
| from peft import PeftModel
|
|
|
|
|
| base_model_path = "./Qwen3-4B-Thinking-2507"
|
| lora_path = "./QiMing-Polaris-Qwen3-4B-Thinking-2507_burden_trained_lora"
|
|
|
|
|
| prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
|
|
|
| ### Instruction:
|
| What is the 'Burden-based Training' method?
|
|
|
| ### Input:
|
|
|
|
|
| ### Response:
|
| """
|
|
|
| print("🚀 启动残差流向量干涉对比审计工具...")
|
|
|
|
|
| tokenizer = AutoTokenizer.from_pretrained(base_model_path, trust_remote_code=True)
|
| inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
|
|
|
|
|
|
|
| def audit_model_interference(model):
|
| """通过注册 Hook 测量模型每一层的残差流变化量 Δh 以及夹角余弦 cos(h, Δh)"""
|
| residual_inputs = {}
|
| residual_outputs = {}
|
| hooks = []
|
|
|
| def make_hook(layer_idx):
|
| def hook(module, input_tensor, output_tensor):
|
| residual_inputs[layer_idx] = input_tensor[0].detach()
|
|
|
| out = output_tensor[0] if isinstance(output_tensor, tuple) else output_tensor
|
| residual_outputs[layer_idx] = out.detach()
|
| return hook
|
|
|
|
|
| if hasattr(model, "model") and hasattr(model.model, "layers"):
|
| layers = model.model.layers
|
| elif hasattr(model, "base_model"):
|
| layers = model.base_model.model.model.layers
|
| else:
|
| raise AttributeError("无法自动定位模型的 layers 结构")
|
|
|
|
|
| for i, layer in enumerate(layers):
|
| hooks.append(layer.register_forward_hook(make_hook(i)))
|
|
|
|
|
| with torch.no_grad():
|
| _ = model(**inputs)
|
|
|
|
|
| for h in hooks:
|
| h.remove()
|
|
|
|
|
| metrics = []
|
| for i in range(len(layers)):
|
| h_l = residual_inputs[i][0, -1, :].float()
|
| h_next = residual_outputs[i][0, -1, :].float()
|
| delta_h = h_next - h_l
|
|
|
| cos_sim = F.cosine_similarity(h_l, delta_h, dim=0).item()
|
| delta_norm = delta_h.norm().item()
|
|
|
| metrics.append({
|
| "layer": i,
|
| "norm": delta_norm,
|
| "cos_sim": cos_sim
|
| })
|
|
|
| return metrics
|
|
|
|
|
|
|
| print(f"\n🔍 正在测量 1/2: 原始模型 [{base_model_path}]...")
|
| base_model = AutoModelForCausalLM.from_pretrained(
|
| base_model_path,
|
| torch_dtype=torch.bfloat16,
|
| device_map="cuda",
|
| trust_remote_code=True
|
| )
|
| base_metrics = audit_model_interference(base_model)
|
|
|
|
|
|
|
| print(f"🔍 正在测量 2/2: FT 负重训练模型 [Base + {lora_path}]...")
|
| ft_model = PeftModel.from_pretrained(base_model, lora_path)
|
| ft_metrics = audit_model_interference(ft_model)
|
|
|
|
|
|
|
| print("\n" + "="*100)
|
| print(f"{'层数':<6} | {'[原始 Base] cos(h,Δh)':<22} | {'[FT 负重] cos(h,Δh)':<22} | {'余弦变化(Diff)':<14} | {'干涉趋势变化'}")
|
| print("="*100)
|
|
|
| for i in range(len(base_metrics)):
|
| b_cos = base_metrics[i]["cos_sim"]
|
| ft_cos = ft_metrics[i]["cos_sim"]
|
| diff = ft_cos - b_cos
|
|
|
| b_type = "🔴减法" if b_cos < 0 else "🟢加法"
|
| ft_type = "🔴减法" if ft_cos < 0 else "🟢加法"
|
|
|
|
|
| if ft_cos < b_cos:
|
| trend = "⬇️ 负向干涉增强 (做减法/抵消变强)"
|
| elif ft_cos > b_cos:
|
| trend = "⬆️ 正向叠加增强 (做加法)"
|
| else:
|
| trend = "➡️ 无变化"
|
|
|
| print(f"L-{i:<3} | {b_cos:<8.4f} ({b_type}) | {ft_cos:<8.4f} ({ft_type}) | {diff:<+10.4f} | {trend}")
|
|
|
| print("="*100)
|
| print("💡 结果解读指南:")
|
| print("1. [FT 负重] 的 cos(h,Δh) 数值越小或越负,说明 FT 训练在该层施加的‘相消干涉(减法/抵消)’越强。")
|
| print("2. 如果变化趋势显示 '⬇️ 负向干涉增强',证明挂载 FT LoRA 后,该层正在主动计算反向向量去抵消杂音噪声!")
|
| print("="*100) |