Delete convert_to_3b.py
Browse files- convert_to_3b.py +0 -111
convert_to_3b.py
DELETED
|
@@ -1,111 +0,0 @@
|
|
| 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()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|