unparallelled commited on
Commit
614bed8
·
verified ·
1 Parent(s): 20d7333

Upload scripts/mk_p1_plots.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. scripts/mk_p1_plots.py +145 -0
scripts/mk_p1_plots.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Phase-1 (680M, 4k->16k) plots: training lineage + NIAH eval.
3
+
4
+ Every number is read from a file. The 1.06B reference points come from the
5
+ summary.csv files this project already published to HF (ref680/logs/...), not
6
+ from anything transcribed by hand.
7
+
8
+ fig 1 p1_lineage.png training loss across the 680M lineage
9
+ fig 2 p1_results.png niah_single accuracy vs prompt length, Wilson 95% CI
10
+ """
11
+ import csv, math, os, re, sys
12
+ import matplotlib; matplotlib.use("Agg")
13
+ import matplotlib.pyplot as plt
14
+
15
+ S = {"surface":"#fcfcfb","ink":"#0b0b0b","ink2":"#52514e","grid":"#e4e4e1"}
16
+ C680, CBASE = "#12508f", "#9dc3ea"
17
+ CPAR, CMIX, CPURE = "#eb6834", "#b3243b", "#8e8e88"
18
+ klab = lambda v: (f"{round(v/1024)}k" if v >= 1024 else str(int(v)))
19
+
20
+ def wilson(k, n, z=1.96):
21
+ if not n: return (0.0, 0.0, 0.0)
22
+ p = k/n; d = 1 + z*z/n
23
+ c = (p + z*z/(2*n))/d
24
+ h = z*math.sqrt(p*(1-p)/n + z*z/(4*n*n))/d
25
+ return (100*p, 100*max(0,c-h), 100*min(1,c+h))
26
+
27
+ def style(ax):
28
+ ax.set_facecolor(S["surface"])
29
+ for s in ax.spines.values(): s.set_color(S["grid"])
30
+ ax.grid(True, color=S["grid"], lw=.7, alpha=.9)
31
+ ax.tick_params(colors=S["ink2"], labelsize=9)
32
+
33
+ # ---------------------------------------------------------------- fig 1: loss
34
+ rows = []
35
+ CSVP = "CP_BluScreipt_Training_logs/CP_Training_log12.csv"
36
+ if os.path.exists(CSVP):
37
+ for r in csv.DictReader(open(CSVP)):
38
+ try: rows.append((int(r["step"]), float(r["train_loss"]), float(r["val_loss"] or 0)))
39
+ except Exception: pass
40
+ if not rows: # fall back to the text log
41
+ t = open("p1_logs/train.log", errors="ignore").read()
42
+ rows = [(int(a), float(b), 0.0) for a,b in
43
+ re.findall(r"^step +(\d+) \| loss: ([0-9.]+)", t, re.M)]
44
+ if not rows:
45
+ sys.exit("no training rows found -- nothing to plot")
46
+
47
+ xs = [r[0] for r in rows]; ys = [r[1] for r in rows]
48
+ d = {s:l for s,l,_ in rows}
49
+ rx, ry = [], []
50
+ for s in xs:
51
+ w = [d[j] for j in range(s-49, s+1) if j in d]
52
+ if len(w) == 50: rx.append(s); ry.append(sum(w)/50)
53
+ # val only where it CHANGES (the trainer carries the last value forward)
54
+ vx, vy, prev = [], [], None
55
+ for s,_,v in rows:
56
+ if v and v != prev: vx.append(s); vy.append(v); prev = v
57
+
58
+ fig, ax = plt.subplots(figsize=(11.5,5.6), facecolor=S["surface"])
59
+ ax.plot(xs, ys, color=C680, lw=.6, alpha=.30)
60
+ ax.plot(rx, ry, color=C680, lw=2.0, label="phase 1 4k -> 16k (50-step mean)")
61
+ if vx: ax.plot(vx, vy, "o--", color=CPAR, ms=4.5, lw=1.1, label="validation loss")
62
+ style(ax)
63
+ ax.set_xlabel("step", color=S["ink2"], fontsize=10)
64
+ ax.set_ylabel("loss (nats)", color=S["ink2"], fontsize=10)
65
+ ax.set_title("680M lineage -- phase 1 context extension, 4k -> 16k",
66
+ color=S["ink"], fontsize=13, loc="left", pad=12)
67
+ last = ry[-1] if ry else ys[-1]
68
+ ax.text(.995,.965, f"parent varybatch (10.5 tok/param)\nYaRN 4 x 4096 = 16384\n"
69
+ f"{len(xs)} steps | last 50-step mean {last:.4f}",
70
+ transform=ax.transAxes, ha="right", va="top", fontsize=8.4, color=S["ink2"],
71
+ bbox=dict(fc="white", ec=S["grid"]))
72
+ ax.text(.005,.02, "varybatch's own pretrain curve is not plotted: its training log was "
73
+ "not published with the checkpoint, so the segment is unrecoverable.",
74
+ transform=ax.transAxes, fontsize=7.6, color=S["ink2"], style="italic")
75
+ ax.legend(frameon=False, fontsize=9, labelcolor=S["ink2"], loc="upper right",
76
+ bbox_to_anchor=(.995,.80))
77
+ fig.tight_layout(); fig.savefig("plots_p1/p1_lineage.png", dpi=155)
78
+ print(" wrote plots_p1/p1_lineage.png")
79
+
80
+ # -------------------------------------------------------------- fig 2: evals
81
+ def read_sum(p, col=1):
82
+ if not os.path.exists(p): return None
83
+ for r in csv.reader(open(p)):
84
+ if r and r[0] == "niah_single":
85
+ try: return float(r[col])
86
+ except Exception: return None
87
+ return None
88
+
89
+ LENS = [8192, 16360, 32744, 65512]
90
+ REF = {
91
+ "1.06B ext64k parent (695)": (CPAR, "-", [read_sum(f"ref680/logs/ext64k_len_{L}/summary.csv") for L in LENS]),
92
+ "1.06B mix64k (1200), best": (CMIX, "-", [read_sum(f"ref680/logs/mix64k_1200_len_{L}/summary.csv") for L in LENS]),
93
+ "1.06B mixcont (1400), collapsed":(CPURE, "--", [read_sum(f"ref680/logs/mixcont/cliff1400_len_{L}/summary.csv") for L in LENS]),
94
+ }
95
+ P680 = {}
96
+ for name, key in (("680M phase 1 (1200)","p1final"), ("680M varybatch, zero-shot YaRN","base680")):
97
+ pts = []
98
+ for L in (8192, 16360):
99
+ v = None
100
+ for c in (1,2,3):
101
+ v = read_sum(f"p1_eval_len{L}/summary.csv", c)
102
+ if v is not None: break
103
+ # summary.csv columns are per-model; find this model's column by header
104
+ hp = f"p1_eval_len{L}/summary.csv"
105
+ if os.path.exists(hp):
106
+ hdr = next(csv.reader(open(hp)), [])
107
+ if key in hdr:
108
+ v = read_sum(hp, hdr.index(key))
109
+ pts.append(v)
110
+ P680[name] = pts
111
+
112
+ fig, ax = plt.subplots(figsize=(11.0,6.0), facecolor=S["surface"])
113
+ X = list(range(len(LENS)))
114
+ for name,(col,ls,vals) in REF.items():
115
+ xs_ = [i for i,v in zip(X,vals) if v is not None]
116
+ ys_ = [v for v in vals if v is not None]
117
+ if not ys_: continue
118
+ err = [[v-wilson(round(v),100)[1] for v in ys_],[wilson(round(v),100)[2]-v for v in ys_]]
119
+ ax.errorbar(xs_, ys_, yerr=err, color=col, ls=ls, lw=1.6, marker="o", ms=5,
120
+ capsize=3, alpha=.85, label=name)
121
+ for name,(col,mk) in zip(P680, ((C680,"s"),(CBASE,"^"))):
122
+ vals = P680[name]
123
+ xs_ = [i for i,v in zip(X,vals) if v is not None]
124
+ ys_ = [v for v in vals if v is not None]
125
+ if not ys_:
126
+ continue
127
+ err = [[v-wilson(round(v),100)[1] for v in ys_],[wilson(round(v),100)[2]-v for v in ys_]]
128
+ ax.errorbar(xs_, ys_, yerr=err, color=col, lw=2.4, marker=mk, ms=8, capsize=3, label=name)
129
+ ax.axvspan(1.5, 3.4, color="#f0f0ee", zorder=0)
130
+ ax.text(2.45,.5,"beyond phase 1's 16k window\n(680M not evaluated here)",
131
+ ha="center", fontsize=8.2, color=S["ink2"], style="italic")
132
+ style(ax)
133
+ ax.set_xticks(X); ax.set_xticklabels([klab(L) for L in LENS])
134
+ ax.set_xlim(-.3, 3.4); ax.set_ylim(0, 100)
135
+ ax.set_xlabel("prompt length (tokens)", color=S["ink2"], fontsize=10)
136
+ ax.set_ylabel("niah_single accuracy (%)", color=S["ink2"], fontsize=10)
137
+ ax.set_title("Needle-in-a-haystack retrieval -- 680M phase 1 vs the 1.06B lineage",
138
+ color=S["ink"], fontsize=13, loc="left", pad=12)
139
+ ax.text(.005,-.155,"N=100 per point, greedy, identical haystack (b2 val_shard_00000) and prompts "
140
+ "across every model. Bars are Wilson 95% CI (+/-9-13pp at N=100): "
141
+ "differences inside a bar are not differences.",
142
+ transform=ax.transAxes, fontsize=7.8, color=S["ink2"])
143
+ ax.legend(frameon=False, fontsize=9, labelcolor=S["ink2"], loc="upper right")
144
+ fig.tight_layout(); fig.savefig("plots_p1/p1_results.png", dpi=155, bbox_inches="tight")
145
+ print(" wrote plots_p1/p1_results.png")