unparallelled commited on
Commit
0da00ec
·
verified ·
1 Parent(s): 24df459

Upload scripts/mk_lineage.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. scripts/mk_lineage.py +94 -0
scripts/mk_lineage.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Standalone lineage loss plot: every training stage this 1.06B model has been
3
+ through, forking at ext64k step 695 into the two 64k runs.
4
+
5
+ 100% b5 -> collapsed (cliff at step 1199, ended 45/17/2/1)
6
+ MIX 50/30/20 -> this run
7
+
8
+ Loss curves come from each stage's own training log; nothing is transcribed.
9
+ """
10
+ import json, math, os, re, statistics as st
11
+ import matplotlib; matplotlib.use("Agg")
12
+ import matplotlib.pyplot as plt
13
+
14
+ S={"surface":"#fcfcfb","ink":"#0b0b0b","ink2":"#52514e","grid":"#e4e4e1"}
15
+ PURE="#b3243b"; MIX="#12508f"; PARENT="#eb6834"
16
+ R="mix64k_ref"
17
+ klab=lambda v:(f"{round(v/1024)}k" if v>=1024 else str(int(v)))
18
+
19
+ def rows_of(p):
20
+ try: t=open(p,errors="ignore").read()
21
+ except Exception: return []
22
+ return [(int(a),float(b)) for a,b in re.findall(r"^step +(\d+) \| loss: ([0-9.]+)",t,re.M)]
23
+
24
+ def roll(rows,k=50):
25
+ d=dict(rows); xs=[];ys=[]
26
+ for s,_ in rows:
27
+ w=[d[j] for j in range(s-k+1,s+1) if j in d]
28
+ if len(w)==k: xs.append(s); ys.append(sum(w)/k)
29
+ return xs,ys
30
+
31
+ stages=json.load(open(f"{R}/lineage/stages.json"))
32
+ ORDER=[("base pretrain",4096,"#8e8e88"),("l2 16k bucket",16384,"#9dc3ea"),
33
+ ("ext32k",32768,"#4a8fd4"),("b4 full epoch",32768,"#12508f"),("ext64k",65536,PARENT)]
34
+ pr=rows_of(f"{R}/cont64k_purec5.log"); mr=rows_of("mix64k_logs/train.log")
35
+
36
+ fig,(axA,axB)=plt.subplots(2,1,figsize=(11.5,9.2),facecolor=S["surface"],
37
+ gridspec_kw={"height_ratios":[1.2,1],"hspace":0.26},sharex=True)
38
+ off=0; spans=[]
39
+ for name,ctx,col in ORDER:
40
+ stg=stages.get(name)
41
+ if not stg: continue
42
+ rw=stg["rows"]; b=rw[0][0]
43
+ xs=[off+(r[0]-b) for r in rw]; ys=[r[1] for r in rw]
44
+ for ax in (axA,axB):
45
+ ax.plot(xs,ys,color=col,lw=.8,alpha=.85,zorder=3,
46
+ label=(f"{name} ({klab(ctx)})" if ax is axA else None))
47
+ spans.append((off,xs[-1],name,col)); off=xs[-1]
48
+ fork=off
49
+ for rw,col,lab,lw in ((pr,PURE,"100% b5 -> COLLAPSED",1.5),(mr,MIX,"MIX 50/30/20 -> this run",1.9)):
50
+ if not rw: continue
51
+ xs=[fork+s for s,_ in rw]; ys=[l for _,l in rw]
52
+ for ax in (axA,axB): ax.plot(xs,ys,color=col,lw=.45,alpha=.22,zorder=2)
53
+ rx,ry=roll(rw)
54
+ for ax in (axA,axB):
55
+ ax.plot([fork+x for x in rx],ry,color=col,lw=lw,zorder=5,
56
+ label=(lab+" (50-step mean)" if ax is axA else None))
57
+ spans.append((fork,fork+rw[-1][0],lab.split(" ->")[0],col))
58
+
59
+ ends=[stages[n]["rows"][-1][1] for n,_,_ in ORDER if n in stages]
60
+ lo,hi=min(ends),max(ends)
61
+ for ax in (axA,axB):
62
+ ax.axvline(fork,color=S["ink2"],lw=1.1,ls="--",alpha=.75,zorder=4)
63
+ ax.set_facecolor(S["surface"]); ax.grid(True,color=S["grid"],lw=.8,zorder=0); ax.set_axisbelow(True)
64
+ for k,sp in ax.spines.items(): sp.set_visible(k in ("left","bottom")); sp.set_color(S["grid"])
65
+ ax.tick_params(colors=S["ink2"],labelsize=9)
66
+ axA.set_yscale("log"); axA.set_ylim(0.9,13)
67
+ axA.set_yticks([1,2,3,5,10]); axA.set_yticklabels(["1","2","3","5","10"])
68
+ axA.set_ylabel("loss (nats, log)",color=S["ink2"],fontsize=10)
69
+ # axA.set_title("Every stage this 1.06B model has been through -- and where the two 64k runs diverge",
70
+ # color=S["ink"],fontsize=12.5,loc="left",pad=12)
71
+ # axA.annotate("both 64k runs fork here\n(ext64k step 695, 67/65/52/29)",xy=(fork,8.2),
72
+ # xytext=(fork*0.50,8.6),fontsize=8.8,color=S["ink2"],
73
+ # arrowprops=dict(arrowstyle="->",color=S["ink2"],lw=.9))
74
+ axA.legend(frameon=False,fontsize=8.2,labelcolor=S["ink2"],loc="lower left",ncol=2)
75
+ axB.axhspan(lo,hi,color="#7a9a3a",alpha=.13,zorder=1)
76
+ # axB.annotate(f"every stage before the fork ends in {lo:.2f}-{hi:.2f}\nthe MIX stays in the band; 100% b5 leaves it and never returns",
77
+ # xy=(fork+1300,1.30),xytext=(off*0.06,1.18),fontsize=8.8,color="#5d7a22",
78
+ # arrowprops=dict(arrowstyle="->",color="#7a9a3a",lw=1.0,alpha=.85))
79
+ axB.set_ylim(1.0,3.5); axB.set_ylabel("loss (nats)",color=S["ink2"],fontsize=10)
80
+ axB.set_xlabel("cumulative training step across the lineage",color=S["ink2"],fontsize=10)
81
+ for s,e,name,col in spans:
82
+ axB.text((s+e)/2,3.38,name,ha="center",fontsize=7.4,color=col)
83
+ fig.savefig("mix64k_lineage.png",dpi=140,facecolor=S["surface"],bbox_inches="tight")
84
+ print(f" wrote mix64k_lineage.png ({os.path.getsize('mix64k_lineage.png')//1024} KB)")
85
+ print(f"\n {'stage':<26}{'window':>8}{'steps':>7}{'first':>9}{'last':>8}")
86
+ for n,c,_ in ORDER:
87
+ if n in stages:
88
+ rw=stages[n]["rows"]; print(f" {n:<26}{klab(c):>8}{len(rw):>7}{rw[0][1]:>9.3f}{rw[-1][1]:>8.3f}")
89
+ for rw,n in ((pr,"100% b5 (collapsed)"),(mr,"MIX (this run)")):
90
+ if rw: print(f" {n:<26}{'64k':>8}{len(rw):>7}{rw[0][1]:>9.3f}{rw[-1][1]:>8.3f}")
91
+ print(f"\n pre-fork stages end in {lo:.3f}-{hi:.3f}")
92
+ if mr:
93
+ d=dict(mr); mx=max(d); w=[d[k] for k in range(mx-49,mx+1) if k in d]
94
+ print(f" MIX rolling-50 at step {mx}: {st.mean(w):.3f} (pure-b5 was 1.80 by here)")