Rhett1 commited on
Commit
c8e4c66
·
verified ·
1 Parent(s): cc520ea

Upload asvd_llm/heal/llama2-13b-base/lowrank_linear.py with huggingface_hub

Browse files
asvd_llm/heal/llama2-13b-base/lowrank_linear.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Minimal standalone loader for the SVD-baseline compressed LLaMA-2-7B checkpoints.
2
+
3
+ No dependency beyond torch + transformers. The state_dict stores every compressed
4
+ projection as two factors of a LowRankLinear (A: out x k, B: k x in); ranks.json
5
+ holds the per-layer integer rank of each projection. Untouched parameters
6
+ (embeddings, norms) keep their stock transformers names.
7
+
8
+ Usage:
9
+ import json, torch
10
+ from lowrank_linear import build
11
+ model = build(
12
+ base_id="NousResearch/Llama-2-7b-chat-hf",
13
+ ranks=json.load(open("ranks.json")),
14
+ state_dict_path="state_dict_fp16.pt",
15
+ device="cuda", dtype=torch.float16,
16
+ )
17
+ tokenizer = AutoTokenizer.from_pretrained("NousResearch/Llama-2-7b-chat-hf")
18
+ out = model.generate(tokenizer("2+2=", return_tensors="pt").to("cuda").input_ids,
19
+ max_new_tokens=16, do_sample=False)
20
+ print(tokenizer.decode(out[0]))
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import torch
26
+ import torch.nn as nn
27
+ import torch.nn.functional as F
28
+
29
+
30
+ class LowRankLinear(nn.Module):
31
+ """y = A (B x). A: out x r, B: r x in. (LLaMA projections carry no bias.)"""
32
+
33
+ def __init__(self, A: torch.Tensor, B: torch.Tensor):
34
+ super().__init__()
35
+ self.A = nn.Parameter(A)
36
+ self.B = nn.Parameter(B)
37
+
38
+ def forward(self, x):
39
+ return F.linear(F.linear(x, self.B), self.A)
40
+
41
+ @torch.no_grad()
42
+ def materialize_(self) -> nn.Linear:
43
+ """Replace this module with the dense W = A @ B (inference only; never call
44
+ while training -- it cuts the gradient path)."""
45
+ W = (self.A @ self.B).to(self.A.dtype)
46
+ dense = nn.Linear(self.B.shape[1], self.A.shape[0], bias=False,
47
+ device=W.device, dtype=W.dtype)
48
+ dense.weight.data = W
49
+ return dense
50
+
51
+
52
+ def build(base_id: str, ranks: dict, state_dict_path: str,
53
+ device: str = "cuda", dtype=torch.float16):
54
+ from transformers import AutoModelForCausalLM
55
+
56
+ model = AutoModelForCausalLM.from_pretrained(base_id, torch_dtype=dtype)
57
+ search = {}
58
+ for name, mod in model.named_modules():
59
+ if isinstance(mod, nn.Linear):
60
+ search[name] = mod
61
+ for path, k in ranks.items():
62
+ out_f, in_f = search[path].weight.shape
63
+ model_mod = model
64
+ for p in path.split(".")[:-1]:
65
+ model_mod = getattr(model_mod, p)
66
+ setattr(model_mod, path.split(".")[-1],
67
+ LowRankLinear(torch.zeros(out_f, int(k), dtype=dtype),
68
+ torch.zeros(int(k), in_f, dtype=dtype)))
69
+ sd = torch.load(state_dict_path, map_location="cpu", weights_only=True)
70
+ model.load_state_dict(sd, strict=True)
71
+ del sd
72
+ return model.to(device)
73
+
74
+
75
+ def materialize_all(model):
76
+ """Fuse every LowRankLinear back into a dense nn.Linear in place."""
77
+ for name, mod in list(model.named_modules()):
78
+ if isinstance(mod, LowRankLinear):
79
+ parent = model
80
+ for p in name.split(".")[:-1]:
81
+ parent = getattr(parent, p)
82
+ setattr(parent, name.split(".")[-1], mod.materialize_())
83
+ return model