Robotics
multilingual
ternary
multimodal
pretraining
jirack
ternarytransformer
kgrabko commited on
Commit
dd3c34c
·
verified ·
1 Parent(s): 9516dab

Create convert_to_3b.py

Browse files
Files changed (1) hide show
  1. convert_to_3b.py +111 -0
convert_to_3b.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ==============================================================================
2
+ # COPYRIGHT (C) 2026 KONSTANTIN VLADIMIROVICH GRABKO. ALL RIGHTS RESERVED.
3
+ # PATENT PENDING | CMS MANHATTAN JIRACK TECHNOLOGY
4
+ # ==============================================================================
5
+ #
6
+ # expand_3b.py
7
+ # ------------
8
+ # Widen a trained JiRackNative_3b checkpoint's FFN from INTERMEDIATE=4096 (~2B)
9
+ # to INTERMEDIATE=8192 (~3B) so the NEW neurons are actually alive.
10
+ #
11
+ # Because hidden_size is unchanged (only the FFN width grows), this is a CLEAN,
12
+ # function-preserving expansion:
13
+ # * ffn_w1 / ffn_w3 (shape [I, H]) : new ROWS = small random (input side)
14
+ # * ffn_w2 (shape [H, I]) : new COLS = ZERO (output side)
15
+ # At init the new neurons contribute 0 to the output (loss is unchanged), but
16
+ # their input weights are non-zero, so gradient flows and they start learning
17
+ # from ~step 2. No dead neurons, no loss spike. (Net2Net, Chen et al. 2016.)
18
+ #
19
+ # After running this:
20
+ # 1) set INTERMEDIATE_SIZE = 8192 in JiRackNative_3b.py
21
+ # 2) load the new checkpoint and continue training (keep your normal LR)
22
+ #
23
+ # Usage:
24
+ # python expand_3b.py --in jirack_2b.safetensors --out jirack_3b.safetensors
25
+ # python expand_3b.py --in ckpt/ --out jirack_3b.safetensors # dir of shards
26
+ # ==============================================================================
27
+
28
+ import argparse
29
+ import glob
30
+ import os
31
+ import torch
32
+ from safetensors.torch import load_file, save_file
33
+
34
+ OLD_I = 4096 # current intermediate size (~2B)
35
+ NEW_I = 8192 # target intermediate size (~3B)
36
+ INIT_STD = 0.02 # std for the new input-side weights
37
+ torch.manual_seed(0) # reproducible expansion
38
+
39
+
40
+ def expand_ffn_in(w):
41
+ """ffn_w1 / ffn_w3, shape [I, H]: add new ROWS (new neurons' input) = random."""
42
+ I, H = w.shape
43
+ if I >= NEW_I:
44
+ return w
45
+ new_rows = torch.randn(NEW_I - I, H, dtype=w.dtype, device=w.device) * INIT_STD
46
+ return torch.cat([w, new_rows], dim=0)
47
+
48
+
49
+ def expand_ffn_out(w):
50
+ """ffn_w2, shape [H, I]: add new COLS (new neurons' output) = ZERO."""
51
+ H, I = w.shape
52
+ if I >= NEW_I:
53
+ return w
54
+ new_cols = torch.zeros(H, NEW_I - I, dtype=w.dtype, device=w.device)
55
+ return torch.cat([w, new_cols], dim=1)
56
+
57
+
58
+ def load_state(path):
59
+ if os.path.isdir(path):
60
+ sd = {}
61
+ files = sorted(glob.glob(os.path.join(path, "*.safetensors")))
62
+ if not files:
63
+ raise FileNotFoundError(f"No .safetensors in {path}")
64
+ for f in files:
65
+ sd.update(load_file(f))
66
+ return sd
67
+ return load_file(path)
68
+
69
+
70
+ def main():
71
+ ap = argparse.ArgumentParser()
72
+ ap.add_argument("--in", dest="inp", required=True,
73
+ help="input .safetensors file OR directory of shards")
74
+ ap.add_argument("--out", dest="out", required=True,
75
+ help="output .safetensors path")
76
+ args = ap.parse_args()
77
+
78
+ print(f"Loading checkpoint from {args.inp} ...")
79
+ sd = load_state(args.inp)
80
+
81
+ new_sd = {}
82
+ n_w1 = n_w3 = n_w2 = 0
83
+
84
+ for k, v in sd.items():
85
+ if k.endswith("ffn_w1.weight"):
86
+ new_sd[k] = expand_ffn_in(v); n_w1 += 1
87
+ elif k.endswith("ffn_w3.weight"):
88
+ new_sd[k] = expand_ffn_in(v); n_w3 += 1
89
+ elif k.endswith("ffn_w2.weight"):
90
+ new_sd[k] = expand_ffn_out(v); n_w2 += 1
91
+ else:
92
+ new_sd[k] = v # embeddings, attention, norms, lm_head unchanged
93
+
94
+ print(f"Expanded: ffn_w1={n_w1} ffn_w3={n_w3} ffn_w2={n_w2} "
95
+ f"({OLD_I} -> {NEW_I})")
96
+
97
+ # --- sanity check: confirm new neurons are "alive" (nonzero input side) ---
98
+ sample = next(k for k in new_sd if k.endswith("ffn_w1.weight"))
99
+ w1 = new_sd[sample]
100
+ new_block = w1[OLD_I:NEW_I]
101
+ live = (new_block.abs().sum(dim=1) > 0).sum().item()
102
+ print(f"Sanity ({sample}): {live}/{NEW_I - OLD_I} new neurons have "
103
+ f"nonzero input weights (should be all).")
104
+
105
+ print(f"Saving to {args.out} ...")
106
+ save_file(new_sd, args.out)
107
+ print("Done. Now set INTERMEDIATE_SIZE = 8192 and continue training.")
108
+
109
+
110
+ if __name__ == "__main__":
111
+ main()