Skip to content

Commit a45dca6

Browse files
committed
transformerless_lm: scaled-up text sampling at d=384, n_blocks=6
Small-scale (d=128, 4 blocks, 2500 steps) produced gibberish from dense_crt too, so we couldn't read the FibGen output as "good" or "bad". To assess whether substrate compression preserves extrapolation quality we need dense to actually generate coherent Shakespeare first. sample_text_scaled.py runs at GPT-2-tiny-class parameters: d_model=384, n_blocks=6, seq_len=128, steps=6000 Estimated wall time (CPU): dense_crt ~20 min fibgen_K32_cross ~50 min composed_transformerless ~80 min Total: ~2.5 hours. Per-arch checkpoint of best-val state during training; sample from that checkpoint, not the final step (per the user's observation that substrate models snap to discrete attractor configurations and the last step is rarely the best). Saves partial results to results_samples_scaled.txt after each arch so we have outputs even if a later arch crashes.
1 parent a0cbbf4 commit a45dca6

1 file changed

Lines changed: 133 additions & 0 deletions

File tree

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""Scaled-up text sampling — d=384, n_blocks=6, longer training.
2+
3+
At d=128 / 4 blocks / 2500 steps, even dense produces gibberish, so the
4+
"is FibGen output usable?" question couldn't be answered. This script
5+
trains at GPT-2-tiny-class parameters (d=384, n_blocks=6) for enough
6+
steps to push dense into "barely-coherent Shakespeare" territory, then
7+
compares FibGen and composed at that scale.
8+
9+
Wall-time budget (rough CPU estimates):
10+
dense_crt d=384 6blk 6000 steps: ~20 min
11+
fibgen_K32_cross d=384 6blk 6000 steps: ~50 min
12+
composed d=384 6blk 6000 steps: ~80 min
13+
Total: ~2.5 hours.
14+
15+
Prints best-val checkpoints + generated text for each arch.
16+
"""
17+
18+
import argparse
19+
import sys
20+
import time
21+
from pathlib import Path
22+
23+
import torch
24+
import torch.nn.functional as F
25+
26+
sys.path.insert(0, str(Path(__file__).parent))
27+
from corpus import make_dataset
28+
from models import make_model
29+
from models_fibgen import FibGenLM, FibGenTransformerless
30+
from train_distractor_mix import build_distractor_stream
31+
from lazy_data import fib_positions_in_window, get_fib_strided_batch
32+
from sample_text import evaluate, train, generate_text
33+
34+
35+
def main():
36+
parser = argparse.ArgumentParser()
37+
parser.add_argument("--steps", type=int, default=6000)
38+
parser.add_argument("--batch-size", type=int, default=32)
39+
parser.add_argument("--seq-len", type=int, default=128)
40+
parser.add_argument("--d-model", type=int, default=384)
41+
parser.add_argument("--n-blocks", type=int, default=6)
42+
parser.add_argument("--lr", type=float, default=3e-4)
43+
parser.add_argument("--seed", type=int, default=42)
44+
parser.add_argument("--distractor-frac", type=float, default=0.20)
45+
parser.add_argument("--prompt", type=str,
46+
default="ROMEO:\nWhat light through")
47+
parser.add_argument("--n-new", type=int, default=600)
48+
parser.add_argument("--temperature", type=float, default=0.8)
49+
parser.add_argument("--top-k", type=int, default=10)
50+
parser.add_argument("--out", type=str, default="results_samples_scaled.txt")
51+
parser.add_argument("--archs", type=str,
52+
default="dense_crt,fibgen_K32_cross,composed_transformerless")
53+
args = parser.parse_args()
54+
55+
chars, stoi, itos, encoded = make_dataset(seq_len=args.seq_len,
56+
source="tinyshakespeare")
57+
vocab_size = len(chars)
58+
train_split, val_split = build_distractor_stream(
59+
encoded, args.distractor_frac, args.seq_len, args.seed,
60+
)
61+
fib_positions = fib_positions_in_window(args.seq_len)
62+
63+
arch_factories = {
64+
"dense_crt": lambda: make_model(
65+
"crt_only", vocab_size=vocab_size, seq_len=args.seq_len,
66+
d_model=args.d_model, n_blocks=args.n_blocks,
67+
),
68+
"fibgen_K32_cross": lambda: FibGenLM(
69+
vocab_size=vocab_size, d_model=args.d_model,
70+
n_blocks=args.n_blocks, seq_len=args.seq_len, K=32, mode="cross",
71+
),
72+
"composed_transformerless": lambda: FibGenTransformerless(
73+
vocab_size=vocab_size, d_model=args.d_model, n_blocks=args.n_blocks,
74+
seq_len=args.seq_len, K=32, mode="cross", n_specialists=5,
75+
),
76+
}
77+
78+
selected_archs = [a.strip() for a in args.archs.split(",")]
79+
80+
space_id = stoi.get(" ", 0)
81+
prompt_ids = torch.tensor(
82+
[[stoi.get(c, space_id) for c in args.prompt]], dtype=torch.long,
83+
)
84+
85+
print(f"Scaled-up sampling: d={args.d_model}, n_blocks={args.n_blocks}, "
86+
f"steps={args.steps}", flush=True)
87+
print(f"Archs: {selected_archs}", flush=True)
88+
89+
samples = {}
90+
meta = {}
91+
for name in selected_archs:
92+
if name not in arch_factories:
93+
print(f" skipping unknown arch: {name}", flush=True)
94+
continue
95+
t_arch = time.time()
96+
model = arch_factories[name]()
97+
model, best_val, best_step = train(name, model, train_split, val_split,
98+
args, fib_positions)
99+
wall = time.time() - t_arch
100+
meta[name] = {"best_val": best_val, "best_step": best_step,
101+
"n_params": sum(p.numel() for p in model.parameters()),
102+
"wall_seconds": wall}
103+
out_ids = generate_text(model, prompt_ids, args.n_new, args.seq_len,
104+
itos, temperature=args.temperature,
105+
top_k=args.top_k)
106+
text = "".join(itos[int(i)] for i in out_ids[0].tolist())
107+
samples[name] = text
108+
print(f"\n{'=' * 70}")
109+
print(f"SAMPLE from {name} best_val={best_val:.4f} @ step {best_step} "
110+
f"wall={wall:.0f}s")
111+
print('=' * 70)
112+
print(text)
113+
print('=' * 70, flush=True)
114+
115+
# Save partial result after each arch so we have results even if a later one crashes.
116+
out_path = Path(__file__).parent / args.out
117+
with open(out_path, "w") as f:
118+
f.write(f"# Scaled-up samples (d={args.d_model}, n_blocks={args.n_blocks}, "
119+
f"steps={args.steps}, temperature={args.temperature}, "
120+
f"top_k={args.top_k})\n")
121+
f.write(f"# Prompt: {args.prompt!r}\n\n")
122+
for n, s in samples.items():
123+
m = meta[n]
124+
f.write(f"\n{'=' * 70}\n{n} best_val={m['best_val']:.4f} "
125+
f"@ step {m['best_step']} params={m['n_params']:,} "
126+
f"wall={m['wall_seconds']:.0f}s\n"
127+
f"{'=' * 70}\n{s}\n")
128+
129+
print(f"\nWrote {out_path}")
130+
131+
132+
if __name__ == "__main__":
133+
main()

0 commit comments

Comments
 (0)