aifeifei798 commited on
Commit
2b783dc
·
verified ·
1 Parent(s): dbc6f16

Upload compare_interference.py

Browse files
Files changed (1) hide show
  1. compare_interference.py +127 -0
compare_interference.py ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn.functional as F
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer
4
+ from peft import PeftModel
5
+
6
+ # ==================== 1. 本地路径配置 ====================
7
+ base_model_path = "./Qwen3-4B-Thinking-2507"
8
+ lora_path = "./QiMing-Polaris-Qwen3-4B-Thinking-2507_burden_trained_lora"
9
+
10
+ # 测试 Prompt(使用你的 Alpaca 标准格式)
11
+ 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.
12
+
13
+ ### Instruction:
14
+ What is the 'Burden-based Training' method?
15
+
16
+ ### Input:
17
+
18
+
19
+ ### Response:
20
+ """
21
+
22
+ print("🚀 启动残差流向量干涉对比审计工具...")
23
+
24
+ # 2. 加载分词器和准备 Input
25
+ tokenizer = AutoTokenizer.from_pretrained(base_model_path, trust_remote_code=True)
26
+ inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
27
+
28
+
29
+ # ==================== 审计核心 Hook 函数 ====================
30
+ def audit_model_interference(model):
31
+ """通过注册 Hook 测量模型每一层的残差流变化量 Δh 以及夹角余弦 cos(h, Δh)"""
32
+ residual_inputs = {}
33
+ residual_outputs = {}
34
+ hooks = []
35
+
36
+ def make_hook(layer_idx):
37
+ def hook(module, input_tensor, output_tensor):
38
+ residual_inputs[layer_idx] = input_tensor[0].detach()
39
+ # 如果输出是 tuple(如 Qwen 架构),取第 0 项向量
40
+ out = output_tensor[0] if isinstance(output_tensor, tuple) else output_tensor
41
+ residual_outputs[layer_idx] = out.detach()
42
+ return hook
43
+
44
+ # 兼容 PEFT 挂载前后的模型层获取
45
+ if hasattr(model, "model") and hasattr(model.model, "layers"):
46
+ layers = model.model.layers
47
+ elif hasattr(model, "base_model"):
48
+ layers = model.base_model.model.model.layers
49
+ else:
50
+ raise AttributeError("无法自动定位模型的 layers 结构")
51
+
52
+ # 注册 Hook
53
+ for i, layer in enumerate(layers):
54
+ hooks.append(layer.register_forward_hook(make_hook(i)))
55
+
56
+ # 前向传播捕获向量
57
+ with torch.no_grad():
58
+ _ = model(**inputs)
59
+
60
+ # 及时清理 Hook 防止内存泄漏
61
+ for h in hooks:
62
+ h.remove()
63
+
64
+ # 计算各层干涉数据
65
+ metrics = []
66
+ for i in range(len(layers)):
67
+ h_l = residual_inputs[i][0, -1, :].float() # 当前层最后一个 Token 的向量
68
+ h_next = residual_outputs[i][0, -1, :].float() # 下一层向量
69
+ delta_h = h_next - h_l # 本层新增的向量变化量 Δh_l
70
+
71
+ cos_sim = F.cosine_similarity(h_l, delta_h, dim=0).item()
72
+ delta_norm = delta_h.norm().item()
73
+
74
+ metrics.append({
75
+ "layer": i,
76
+ "norm": delta_norm,
77
+ "cos_sim": cos_sim
78
+ })
79
+
80
+ return metrics
81
+
82
+
83
+ # ==================== 3. 测量 Base 模型 ====================
84
+ print(f"\n🔍 正在测量 1/2: 原始模型 [{base_model_path}]...")
85
+ base_model = AutoModelForCausalLM.from_pretrained(
86
+ base_model_path,
87
+ torch_dtype=torch.bfloat16,
88
+ device_map="cuda",
89
+ trust_remote_code=True
90
+ )
91
+ base_metrics = audit_model_interference(base_model)
92
+
93
+
94
+ # ==================== 4. 挂载 FT LoRA 并测量 ====================
95
+ print(f"🔍 正在测量 2/2: FT 负重训练模型 [Base + {lora_path}]...")
96
+ ft_model = PeftModel.from_pretrained(base_model, lora_path)
97
+ ft_metrics = audit_model_interference(ft_model)
98
+
99
+
100
+ # ==================== 5. 打印对比报告 ====================
101
+ print("\n" + "="*100)
102
+ print(f"{'层数':<6} | {'[原始 Base] cos(h,Δh)':<22} | {'[FT 负重] cos(h,Δh)':<22} | {'余弦变化(Diff)':<14} | {'干涉趋势变化'}")
103
+ print("="*100)
104
+
105
+ for i in range(len(base_metrics)):
106
+ b_cos = base_metrics[i]["cos_sim"]
107
+ ft_cos = ft_metrics[i]["cos_sim"]
108
+ diff = ft_cos - b_cos
109
+
110
+ b_type = "🔴减法" if b_cos < 0 else "🟢加法"
111
+ ft_type = "🔴减法" if ft_cos < 0 else "🟢加法"
112
+
113
+ # 判断趋势变化
114
+ if ft_cos < b_cos:
115
+ trend = "⬇️ 负向干涉增强 (做减法/抵消变强)"
116
+ elif ft_cos > b_cos:
117
+ trend = "⬆️ 正向叠加增强 (做加法)"
118
+ else:
119
+ trend = "➡️ 无变化"
120
+
121
+ print(f"L-{i:<3} | {b_cos:<8.4f} ({b_type}) | {ft_cos:<8.4f} ({ft_type}) | {diff:<+10.4f} | {trend}")
122
+
123
+ print("="*100)
124
+ print("💡 结果解读指南:")
125
+ print("1. [FT 负重] 的 cos(h,Δh) 数值越小或越负,说明 FT 训练在该层施加的‘相消干涉(减法/抵消)’越强。")
126
+ print("2. 如果变化趋势显示 '⬇️ 负向干涉增强',证明挂载 FT LoRA 后,该层正在主动计算反向向量去抵消杂音噪声!")
127
+ print("="*100)