File size: 37,209 Bytes
83112d8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 | #!/usr/bin/env python3
"""
BabyLM Challenge 2026 - Experiment Generator
Generates experiments.csv with ~380 experiments across 22 phases.
Matches the phased plan in notes/experiment_plan.md.
Run: python generate_experiments.py
"""
import csv
import itertools
# ββ Output ββ
OUTPUT = "experiments.csv"
# ββ CSV columns ββ
COLUMNS = [
"id", "name", "phase",
# Architecture
"arch", "objective", "hidden_size", "num_layers", "num_heads", "intermediate_size",
"use_rope", "use_geglu", "use_pre_norm", "use_attention_gate", "use_dwa",
"use_moe", "moe_num_experts", "moe_top_k", "moe_expert_size", "moe_freq_penalty",
"use_attn_res", "attn_res_num_blocks",
"position_bucket_size", "z_loss_weight", "rope_theta",
"rtd_lambda", "gen_size_ratio",
# Data
"data", "tokenizer", "embedding", "embedding_init",
# Masking
"masking", "mask_ratio", "mask_ratio_end", "mntp_ratio",
"amlm_lambda", "amlm_update_interval", "amlm_min_ratio", "amlm_max_ratio",
# Optimizer
"optimizer", "lr", "optimizer_betas", "weight_decay", "forgetter",
# Training
"epochs", "batch_size", "grad_accum", "seq_len",
"dropout", "warmup_ratio", "max_grad_norm",
# KD
"kd_enabled", "kd_teacher", "kd_temperature", "kd_alpha",
# Checkpoint
"ckpt_averaging", "ckpt_avg_last_k",
# Meta
"seed", "status", "notes",
]
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Baseline defaults
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
BASELINE = dict(
arch="gpt_bert", objective="gpt_bert",
hidden_size=384, num_layers=12, num_heads=6, intermediate_size=1280,
use_rope=False, use_geglu=True, use_pre_norm=True,
use_attention_gate=False, use_dwa=False,
use_moe=False, moe_num_experts=32, moe_top_k=4, moe_expert_size=48, moe_freq_penalty=0.01,
use_attn_res=False, attn_res_num_blocks=4,
position_bucket_size=32, z_loss_weight=0.0001, rope_theta=10000.0,
rtd_lambda=50.0, gen_size_ratio=0.33,
data="sample_B", tokenizer="bpe", embedding="standard", embedding_init="random",
masking="standard", mask_ratio=0.30, mask_ratio_end=0.15, mntp_ratio=15,
amlm_lambda=0.2, amlm_update_interval=200, amlm_min_ratio=0.05, amlm_max_ratio=0.50,
optimizer="LAMB", lr=0.0141, optimizer_betas="(0.9,0.98)", weight_decay=0.1, forgetter=False,
epochs=10, batch_size=64, grad_accum=1, seq_len=128,
dropout=0.1, warmup_ratio=0.06, max_grad_norm=2.0,
kd_enabled=False, kd_teacher="", kd_temperature=4.0, kd_alpha=0.5,
ckpt_averaging=False, ckpt_avg_last_k=3,
seed=42, status="planned", notes="",
)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Architecture presets
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ARCH_PRESETS = {
"gpt_bert": dict(arch="gpt_bert", objective="gpt_bert", optimizer="LAMB", masking="standard", mntp_ratio=15, mask_ratio=0.30, mask_ratio_end=0.15, lr=0.005),
"gpt2": dict(arch="gpt2", objective="clm", optimizer="AdamW", masking="none", mntp_ratio=0, mask_ratio=0, mask_ratio_end=0, lr=0.0005),
"modernbert": dict(arch="modernized_bert", objective="mlm", optimizer="AdamW", masking="standard", mntp_ratio=0, mask_ratio=0.30, mask_ratio_end=0.15, lr=0.0005),
"xlstm": dict(arch="xlstm", objective="clm", optimizer="AdamW", masking="none", mntp_ratio=0, mask_ratio=0, mask_ratio_end=0, lr=0.0005),
"rtd": dict(arch="rtd", objective="rtd", optimizer="LAMB", masking="standard", mntp_ratio=0, mask_ratio=0.15, mask_ratio_end=0.15, lr=0.005),
}
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Sweep values
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Learning rates
LRS_LAMB = [0.003, 0.005, 0.007, 0.008, 0.009, 0.010, 0.012, 0.015, 0.018, 0.020, 0.025, 0.030]
LRS_ADAMW = [0.0003, 0.0005, 0.001, 0.002, 0.003, 0.005]
LRS_MUON = [0.005, 0.008, 0.014, 0.020, 0.030]
# Regularization
DROPOUTS = [0.00, 0.02, 0.05, 0.08, 0.10, 0.15, 0.20]
WDS = [0.01, 0.03, 0.05, 0.08, 0.15, 0.20, 1.00]
WARMUPS = [0.00, 0.03, 0.10, 0.15, 0.20]
GRAD_NORMS = [0.5, 1.0, 3.0, 5.0]
# Masking
MASK_SCHEDULES = [
(0.15, 0.15), (0.20, 0.15), (0.25, 0.15), (0.35, 0.15),
(0.40, 0.15), (0.40, 0.20), (0.45, 0.15), (0.30, 0.10),
]
MNTP_RATIOS = [1, 3, 5, 7, 10, 20]
# Batch / Sequence
BATCH_CONFIGS = [ # (batch_size, grad_accum, effective)
(16, 1, 16), (32, 1, 32), (64, 2, 128), (64, 4, 256),
(64, 8, 512), (128, 1, 128), (128, 2, 256), (256, 1, 256),
]
SEQ_LENS = [64, 96, 192, 256, 384, 512]
# Model shapes: (hidden, layers, heads, intermediate)
MODEL_SHAPES = [
(256, 16, 4, 854), (256, 18, 4, 854), (320, 12, 5, 1067),
(384, 16, 6, 1280), (448, 10, 7, 1494), (512, 8, 8, 1706),
(512, 10, 8, 1706), (576, 8, 9, 1920),
]
# MoE configs: (num_experts, top_k, expert_size)
MOE_CONFIGS = [
(16, 2, 96), (16, 4, 96), (32, 2, 48), (32, 8, 48),
(64, 4, 24), (32, 4, 84),
]
MOE_FREQ_PENALTIES = [0.001, 0.10]
# Data construction methods (id, description)
DATA_CONFIGS = [
("champion_replica", "BabyLM33+FineWeb33+Cosmo34"),
("sample_A", "Strategy A pure quality"),
("sample_B", "Strategy B task quota"),
("sample_C", "Strategy C weighted random"),
("sample_D", "Strategy D embedding similarity"),
("B_paraphrase", "sample_B + Paraphrase ~2M"),
("B_variation_sets", "sample_B + Variation Sets ~1M"),
("B_recombitext", "sample_B + RecombiText ~5M"),
("B_cd_synth", "sample_B + Contrastive Decoding ~3M"),
("B_mattr", "sample_B + MATTR ordering"),
("eval_mixed", "eval data mixed into sampling pool"),
("no_eval", "no eval data"),
("full_augment", "Para + VS + MATTR"),
("B_fineweb33", "sample_B + FineWeb 33%"),
("B_fineweb67", "sample_B + FineWeb 67%"),
("B_knowledge", "sample_B + ConceptNet + GenericsKB"),
("B_para_fineweb", "sample_B + Para25% + FineWeb25%"),
("3way_equal", "1:1:1 official + FineWeb + Cosmo"),
]
# KD teachers
KD_TEACHERS = [
("qwen3.5-1.5B", "Qwen/Qwen3.5-1.5B"),
("qwen3.5-3B", "Qwen/Qwen3.5-3B"),
("qwen3.5-9B", "Qwen/Qwen3.5-9B"),
]
KD_TEMPS = [2.0, 4.0, 6.0, 8.0]
KD_ALPHAS = [0.2, 0.3, 0.5, 0.7, 0.9]
# Misc
BETAS = ["(0.8,0.95)", "(0.9,0.95)", "(0.9,0.999)", "(0.95,0.999)"]
Z_LOSSES = [0.0, 0.00005, 0.0005, 0.001]
BUCKET_SIZES = [8, 16, 64, 128]
SEEDS = [7, 42, 123, 2024, 2026, 9999, 31415, 54321]
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Experiment generation
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
experiments = []
phase_counter = {}
def add(phase: int | str, name: str, notes: str = "", **overrides):
"""Add one experiment with overrides on top of baseline."""
p = str(phase)
if p not in phase_counter:
phase_counter[p] = 0
phase_counter[p] += 1
idx = phase_counter[p]
exp = dict(BASELINE)
exp.update(overrides)
exp["id"] = f"P{p}.{idx}"
exp["name"] = name
exp["phase"] = p
exp["notes"] = notes
experiments.append(exp)
def comment(text):
experiments.append({"_comment": text})
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 1: Architecture Comparison (5 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 1: Architecture Comparison (5 exp) βββ")
for arch_name, preset in ARCH_PRESETS.items():
add(1, f"{arch_name}-baseline", f"Base {arch_name}", **preset)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 2: Core Feature Ablations (9 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 2: Core Feature Ablations (9 exp) βββ")
add(2, "gptbert-amlm", "adaptive masking", masking="amlm")
add(2, "gptbert-nhot", "N-hot morphological emb", embedding="nhot")
add(2, "gptbert-forgetter", "FORGETTER reset per epoch", forgetter=True)
add(2, "gptbert-fasttext", "FastText init", embedding_init="fasttext")
add(2, "gptbert-morfessor", "Morfessor+BPE tokenizer", tokenizer="morfessor_bpe")
add(2, "gptbert-moe", "MoE 32exp k=4 s=48", use_moe=True)
add(2, "gptbert-attnres", "AttnRes 4 blocks", use_attn_res=True)
add(2, "gptbert-moe-attnres", "MoE + AttnRes combined", use_moe=True, use_attn_res=True)
add(2, "gptbert-sampleC", "Strategy C data", data="sample_C")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 3: Learning Rate Sweep (17 experiments)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 3: Learning Rate Sweep β 3A quick filter (12Γ3ep) + 3B promote (5Γ10ep) βββ")
# 3A: 3-epoch quick filter
for lr in LRS_LAMB:
add("3A", f"lr-{lr}", f"LAMB lr={lr}", lr=lr, epochs=3)
# 3B: placeholders β top 3 + 2 interpolations promoted to 10ep
for i in range(1, 6):
add("3B", f"lr-promote{i}", f"Top {i} from 3A β 10ep", epochs=10)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 4: Regularization Sweeps (25 experiments, mostly 3ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 4: Regularization Sweeps (25 exp) βββ")
# 4A: Dropout (7Γ3ep)
comment("ββ 4A: Dropout ββ")
for d in DROPOUTS:
add("4A", f"drop-{d}", f"dropout={d}", dropout=d, epochs=3)
# 4B: Weight decay (7Γ3ep)
comment("ββ 4B: Weight Decay ββ")
for wd in WDS:
add("4B", f"wd-{wd}", f"weight_decay={wd}", weight_decay=wd, epochs=3)
# 4C: Warmup (5Γ3ep)
comment("ββ 4C: Warmup Ratio ββ")
for w in WARMUPS:
add("4C", f"warmup-{w}", f"warmup_ratio={w}", warmup_ratio=w, epochs=3)
# 4D: Grad norm (4Γ3ep)
comment("ββ 4D: Grad Norm ββ")
for gn in GRAD_NORMS:
add("4D", f"gradnorm-{gn}", f"max_grad_norm={gn}", max_grad_norm=gn, epochs=3)
# 4E: Best combo verification (2Γ10ep)
comment("ββ 4E: Best Regularization Combo ββ")
add("4E", "reg-best-combo1", "Best dropout+wd+warmup+gradnorm", epochs=10)
add("4E", "reg-best-combo2", "2nd best dropout variant", epochs=10)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 5: Feature Combinations (20 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 5: Feature Combinations (20 exp, using TUNED_BASELINE) βββ")
# Features: amlm(A), nhot(N), forgetter(F), moe(M), attnres(R)
feature_combos = [
("tuned-baseline", {}),
# Singles
("tuned-amlm", dict(masking="amlm")),
("tuned-nhot", dict(embedding="nhot")),
("tuned-fgt", dict(forgetter=True)),
("tuned-moe", dict(use_moe=True)),
("tuned-attnres", dict(use_attn_res=True)),
# Pairs
("tuned-AN", dict(masking="amlm", embedding="nhot")),
("tuned-AF", dict(masking="amlm", forgetter=True)),
("tuned-AM", dict(masking="amlm", use_moe=True)),
("tuned-NF", dict(embedding="nhot", forgetter=True)),
("tuned-NM", dict(embedding="nhot", use_moe=True)),
("tuned-FM", dict(forgetter=True, use_moe=True)),
("tuned-MR", dict(use_moe=True, use_attn_res=True)),
# Triples
("tuned-ANF", dict(masking="amlm", embedding="nhot", forgetter=True)),
("tuned-ANM", dict(masking="amlm", embedding="nhot", use_moe=True)),
("tuned-AFM", dict(masking="amlm", forgetter=True, use_moe=True)),
("tuned-NFM", dict(embedding="nhot", forgetter=True, use_moe=True)),
# Quads
("tuned-ANFM", dict(masking="amlm", embedding="nhot", forgetter=True, use_moe=True)),
("tuned-ANFR", dict(masking="amlm", embedding="nhot", forgetter=True, use_attn_res=True)),
# All five
("tuned-ANFMR", dict(masking="amlm", embedding="nhot", forgetter=True, use_moe=True, use_attn_res=True)),
]
for combo_name, combo_overrides in feature_combos:
add(5, combo_name, combo_name, **combo_overrides)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 6: Masking & Training Objective Tuning (20 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 6: Masking & Objective Tuning (20 exp) βββ")
# 6A: Mask schedule (8)
comment("ββ 6A: Mask Rate Schedule ββ")
for mr_start, mr_end in MASK_SCHEDULES:
add("6A", f"mask-{mr_start}to{mr_end}", f"mask {mr_start}->{mr_end}",
mask_ratio=mr_start, mask_ratio_end=mr_end)
# 6B: MNTP:CLM ratio (6)
comment("ββ 6B: MNTP:CLM Ratio ββ")
for ratio in MNTP_RATIOS:
add("6B", f"mntp-{ratio}to1", f"MNTP:CLM={ratio}:1", mntp_ratio=ratio)
# 6C: AMLM parameters (6)
comment("ββ 6C: AMLM Parameters ββ")
for lam in [0.05, 0.10, 0.30]:
add("6C", f"amlm-lam{lam}", f"amlm_lambda={lam}", masking="amlm", amlm_lambda=lam)
add("6C", "amlm-ui50", "fast update", masking="amlm", amlm_update_interval=50)
add("6C", "amlm-ui500", "slow update", masking="amlm", amlm_update_interval=500)
add("6C", "amlm-wide", "wider range", masking="amlm", amlm_min_ratio=0.10, amlm_max_ratio=0.60)
# 6D: Frequency masking (3)
comment("ββ 6D: Frequency Masking ββ")
for alpha in [0.2, 0.3, 0.5]:
add("6D", f"freq-alpha{alpha}", f"frequency masking alpha={alpha}", masking="frequency")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 7: Batch Size & Sequence Length (14 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 7: Batch Size & Sequence Length (14 exp) βββ")
# 7A: Effective batch size (8)
comment("ββ 7A: Batch Size ββ")
for bs, ga, eff in BATCH_CONFIGS:
add("7A", f"batch-{eff}", f"bs={bs} ga={ga} eff={eff}", batch_size=bs, grad_accum=ga)
# 7B: Sequence length (6)
comment("ββ 7B: Sequence Length ββ")
for sl in SEQ_LENS:
add("7B", f"seqlen-{sl}", f"seq_len={sl}", seq_len=sl)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 8: Optimizer Exploration (16 experiments)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 8: Optimizer Exploration (16 exp) βββ")
# 8A: AdamW LR sweep (6Γ3ep)
comment("ββ 8A: AdamW LR Sweep (3ep) ββ")
for lr in LRS_ADAMW:
add("8A", f"adamw-lr{lr}", f"AdamW lr={lr}", optimizer="AdamW", lr=lr, epochs=3)
# 8B: Muon LR sweep (5Γ3ep)
comment("ββ 8B: Muon LR Sweep (3ep) ββ")
for lr in LRS_MUON:
add("8B", f"muon-lr{lr}", f"Muon lr={lr}", optimizer="Muon", lr=lr, epochs=3)
# 8C: Best alternative + FORGETTER (5Γ10ep)
comment("ββ 8C: Best Optimizer + FORGETTER (10ep) ββ")
add("8C", "adamw-best", "AdamW best LR from 8A", optimizer="AdamW", epochs=10)
add("8C", "adamw-best-fgt", "AdamW + FORGETTER", optimizer="AdamW", forgetter=True, epochs=10)
add("8C", "muon-best", "Muon best LR from 8B", optimizer="Muon", epochs=10)
add("8C", "muon-best-fgt", "Muon + FORGETTER", optimizer="Muon", forgetter=True, epochs=10)
add("8C", "lamb-fgt-recheck", "LAMB+FGT with tuned cfg", forgetter=True, epochs=10)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 9: Architecture Modifications (15 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 9: Architecture Modifications (15 exp) βββ")
# 9A: Toggles (7)
comment("ββ 9A: Feature Toggles ββ")
add("9A", "rope", "RoPE position encoding", use_rope=True)
add("9A", "no-geglu", "Standard GELU FFN", use_geglu=False)
add("9A", "post-norm", "Post-LayerNorm", use_pre_norm=False)
add("9A", "attn-gate", "GELU gate on V", use_attention_gate=True)
add("9A", "dwa", "DenseFormer", use_dwa=True)
add("9A", "rope-attn-gate", "RoPE + attn gate", use_rope=True, use_attention_gate=True)
add("9A", "rope-dwa", "RoPE + DWA", use_rope=True, use_dwa=True)
# 9B: Model shape (8)
comment("ββ 9B: Model Shape ββ")
for h, l, nh, inter in MODEL_SHAPES:
add("9B", f"shape-{h}x{l}", f"h={h} l={l} nh={nh} i={inter}",
hidden_size=h, num_layers=l, num_heads=nh, intermediate_size=inter)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 10: MoE Hyperparameter Tuning (8 experiments, conditional)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 10: MoE Tuning (8 exp, conditional on P5) βββ")
for ne, tk, es in MOE_CONFIGS:
add(10, f"moe-e{ne}k{tk}s{es}", f"{ne} experts top-{tk} size={es}",
use_moe=True, moe_num_experts=ne, moe_top_k=tk, moe_expert_size=es)
for fp in MOE_FREQ_PENALTIES:
add(10, f"moe-fp{fp}", f"freq_penalty={fp}",
use_moe=True, moe_freq_penalty=fp)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 11: Tokenizer Γ Embedding Cross (6 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 11: Tokenizer Γ Embedding Γ Vocab Size (9 exp) βββ")
for tok in ["bpe", "morfessor_bpe"]:
for emb, init in [("standard", "random"), ("nhot", "random"), ("standard", "fasttext")]:
tok_short = "bpe" if tok == "bpe" else "morf"
add(11, f"{tok_short}-{emb}-{init}", f"tok={tok} emb={emb} init={init}",
tokenizer=tok, embedding=emb, embedding_init=init)
# Vocab size sweep (BPE only, standard embedding)
comment("ββ 11B: Vocab Size Sweep ββ")
for vs in [4096, 16384]:
add("11B", f"vocab-{vs}", f"BPE vocab_size={vs}", tokenizer="bpe")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 12: Dataset Construction Methods (18 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 12: Dataset Construction (18 exp) βββ")
for data_id, data_desc in DATA_CONFIGS:
add(12, f"data-{data_id}", data_desc, data=data_id)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 13: Cross-Architecture Verification (15 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 13: Cross-Architecture Verification (15 exp) βββ")
for arch_name in ["gpt2", "modernbert", "xlstm", "rtd"]:
preset = ARCH_PRESETS[arch_name]
add(13, f"{arch_name}-tuned", f"{arch_name} with tuned config", **preset)
# + MoE / AttnRes variants for non-RTD
for arch_name in ["gpt2", "modernbert", "xlstm"]:
preset = ARCH_PRESETS[arch_name]
add(13, f"{arch_name}-moe", f"{arch_name} + MoE", **preset, use_moe=True)
for arch_name in ["gpt2", "modernbert", "xlstm"]:
preset = ARCH_PRESETS[arch_name]
add(13, f"{arch_name}-attnres", f"{arch_name} + AttnRes", **preset, use_attn_res=True)
# RTD + MoE (AttnRes not supported for RTD)
add(13, "rtd-moe", "RTD + MoE", **ARCH_PRESETS["rtd"], use_moe=True)
# Wide variants
for arch_name in ["gpt2", "modernbert", "xlstm"]:
preset = ARCH_PRESETS[arch_name]
add(13, f"{arch_name}-wide", f"{arch_name} 512Γ8",
**preset, hidden_size=512, num_layers=8, num_heads=8, intermediate_size=1706)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 14: LR Γ Dropout Interaction Grid (27 experiments)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 14: LR Γ Dropout Grid (24Γ3ep + 3Γ10ep) βββ")
# 14A: 6 LR Γ 4 dropout = 24 (3ep)
lr_mults = [0.7, 0.85, 1.0, 1.15, 1.3, 1.5]
drop_mults = ["0.0", "half", "best", "1.5x"] # actual values filled at runtime
for lm in lr_mults:
for dm in drop_mults:
add("14A", f"grid-lr{lm}x-d{dm}", f"lrΓ{lm} drop={dm}", epochs=3)
# 14B: Top 3 promoted (10ep)
for i in range(1, 4):
add("14B", f"grid-promote{i}", f"Top {i} from 14A β 10ep", epochs=10)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 15: Miscellaneous Hyperparameters (12 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 15: Misc Hyperparameters (12 exp) βββ")
for zl in Z_LOSSES:
add(15, f"zloss-{zl}", f"z_loss_weight={zl}", z_loss_weight=zl)
for bs in BUCKET_SIZES:
add(15, f"bucket-{bs}", f"position_bucket_size={bs}", position_bucket_size=bs)
for b in BETAS:
b_short = b.replace("(", "").replace(")", "").replace(",", "-")
add(15, f"betas-{b_short}", f"betas={b}", optimizer_betas=b)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 16: Knowledge Distillation (14 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 16: Knowledge Distillation (14 exp) βββ")
default_teacher = KD_TEACHERS[0][1]
# Temperature sweep (4)
for t in KD_TEMPS:
add(16, f"kd-t{t}", f"KD temp={t}", kd_enabled=True, kd_teacher=default_teacher, kd_temperature=t)
# Alpha sweep (5, fix t=4)
for a in KD_ALPHAS:
add(16, f"kd-a{a}", f"KD alpha={a}", kd_enabled=True, kd_teacher=default_teacher, kd_alpha=a)
# Larger teachers (2)
for teacher_name, teacher_path in KD_TEACHERS[1:]:
add(16, f"kd-{teacher_name}", f"teacher={teacher_name}",
kd_enabled=True, kd_teacher=teacher_path)
# Interaction tests (2)
add(16, "kd-no-fgt", "KD without FORGETTER", kd_enabled=True, kd_teacher=default_teacher, forgetter=False)
add(16, "kd-no-amlm", "KD without AMLM", kd_enabled=True, kd_teacher=default_teacher, masking="standard")
# Control
add(16, "no-kd-control", "No KD (control)")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 17: Epoch Count & Checkpoint Strategy (12 experiments)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 17: Epoch & Checkpoint (12 exp) βββ")
for ep in [3, 5, 7, 8]:
add(17, f"epoch-{ep}", f"epochs={ep}", epochs=ep)
# Baseline 10ep already tested; test ckpt averaging
for k in [2, 3, 5, 7]:
add(17, f"ckptavg-{k}", f"avg last {k}", ckpt_averaging=True, ckpt_avg_last_k=k)
# Early stop + averaging combos
for ep in [5, 7, 8]:
add(17, f"epoch{ep}-avg3", f"epoch={ep} + avg last 3", epochs=ep, ckpt_averaging=True, ckpt_avg_last_k=3)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 18: Seed Variance (8 experiments)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 18: Seed Variance (8 exp) βββ")
for s in SEEDS:
add(18, f"seed-{s}", f"seed={s}", seed=s)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 19: Data Γ Feature Interaction (24 experiments, 10ep)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 19: Data Γ Feature Interaction (24 exp) βββ")
# Top 3 data Γ {none, partial, full} features Γ {base, alt} shapes
feat_configs = {
"fnone": {},
"fpart": dict(masking="amlm", embedding="nhot"),
"ffull": dict(masking="amlm", embedding="nhot", forgetter=True, use_moe=True),
}
shape_configs = {
"sbase": {},
"salt": dict(hidden_size=512, num_layers=8, num_heads=8, intermediate_size=1706),
}
# 3 data Γ 3 features Γ 2 shapes = 18
for di in range(1, 4):
for fname, foverrides in feat_configs.items():
for sname, soverrides in shape_configs.items():
add(19, f"d{di}-{fname}-{sname}", f"TOP_DATA_{di} {fname} {sname}",
**foverrides, **soverrides)
# Extra variants: +Morfessor, +FastText, +KD (6)
for di in range(1, 3):
add(19, f"d{di}-ffull-morf", f"TOP_DATA_{di} full+Morfessor",
masking="amlm", embedding="nhot", forgetter=True, use_moe=True, tokenizer="morfessor_bpe")
add(19, f"d{di}-ffull-fasttext", f"TOP_DATA_{di} full+FastText",
masking="amlm", embedding="nhot", forgetter=True, use_moe=True, embedding_init="fasttext")
add(19, f"d{di}-ffull-kd", f"TOP_DATA_{di} full+KD",
masking="amlm", embedding="nhot", forgetter=True, use_moe=True,
kd_enabled=True, kd_teacher=default_teacher)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 20: Final Candidates & Ablation Insurance (20 experiments)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 20: Final Candidates & Ablation (20 exp) βββ")
# 20A: Candidate variants (10)
comment("ββ 20A: Candidates ββ")
for i in range(1, 11):
add("20A", f"final-v{i}", f"Final candidate variant {i}")
# 20B: Ablation (10 β remove one component each)
comment("ββ 20B: Ablation Insurance ββ")
ablations = [
"no-amlm", "no-nhot", "no-fgt", "no-moe", "no-attnres",
"no-kd", "no-ckptavg", "baseline-lr", "baseline-drop", "baseline-data",
]
for ab in ablations:
add("20B", f"ablate-{ab}", f"Remove {ab} from CONFIG_FINAL")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 21: Submission Seeds & Full Eval (16 experiments)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 21: Submission & Full Eval (16 exp) βββ")
# CONFIG_FINAL Γ 5 seeds
for s in [42, 7, 123, 2026, 9999]:
add(21, f"submit-seed{s}", f"FINAL seed={s}", seed=s)
# 2nd/3rd candidates Γ 3 seeds
for cand in [2, 3]:
for s in [42, 7, 123]:
add(21, f"submit-v{cand}-seed{s}", f"Candidate {cand} seed={s}", seed=s)
# Special runs
add(21, "submit-ensemble-avg", "Cross-seed checkpoint average")
add(21, "submit-ckptavg3", "Best seed ckpt avg last 3", ckpt_averaging=True, ckpt_avg_last_k=3)
add(21, "submit-ckptavg5", "Best seed ckpt avg last 5", ckpt_averaging=True, ckpt_avg_last_k=5)
add(21, "submit-glue-ft", "Full eval + GLUE fine-tuning")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Phase 22: Reserve / Exploratory (61 experiments)
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
comment("βββ Phase 22: Reserve / Exploratory (61 exp) βββ")
# 22A: Second-architecture deep dive (10)
comment("ββ 22A: Alt Architecture Deep Dive ββ")
for i in range(1, 11):
add("22A", f"alt-arch-{i}", f"Alt architecture tuning {i}")
# 22B: Augmentation ratio tuning (10)
comment("ββ 22B: Augmentation Ratio Tuning ββ")
for pct in [10, 15, 20, 30, 40, 50]:
add("22B", f"aug-para{pct}", f"Paraphrase {pct}% mix")
for pct in [25, 50, 75]:
add("22B", f"aug-recombi{pct}", f"RecombiText {pct}%")
add("22B", "aug-para-recombi", "Para 20% + RecombiText 30%")
# 22C: MoE alternatives (5)
comment("ββ 22C: MoE Alternatives ββ")
for i in range(1, 6):
add("22C", f"moe-alt-{i}", f"MoE alternative config {i}")
# 22D: Interpolation fine-tuning (10)
comment("ββ 22D: Parameter Interpolation ββ")
for i in range(1, 11):
add("22D", f"interp-{i}", f"Interpolation between best configs {i}")
# 22E: Debug / re-runs (6)
comment("ββ 22E: Debug / Re-runs ββ")
for i in range(1, 7):
add("22E", f"debug-{i}", f"Debug slot {i}")
# 22F: Late-breaking ideas (20)
comment("ββ 22F: Exploratory ββ")
for i in range(1, 21):
add("22F", f"explore-{i}", f"Exploratory slot {i}")
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Write CSV
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def write_csv():
with open(OUTPUT, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=COLUMNS, extrasaction="ignore")
writer.writeheader()
for exp in experiments:
if "_comment" in exp:
row = {col: "" for col in COLUMNS}
row["id"] = f"## {exp['_comment']}"
writer.writerow(row)
else:
writer.writerow(exp)
n = sum(1 for e in experiments if "_comment" not in e)
print(f"Generated {n} experiments across {len(phase_counter)} phases β {OUTPUT}")
print()
for phase, count in sorted(phase_counter.items(), key=lambda x: (len(str(x[0])), str(x[0]))):
print(f" Phase {phase:>4s}: {count:>3d} experiments")
print(f" {'TOTAL':>10s}: {n:>3d} experiments")
print()
# Estimate: 3ep ~15min, 10ep ~40min
quick = sum(1 for e in experiments if "_comment" not in e and e.get("epochs") == 3)
full = n - quick
hours = (quick * 15 + full * 40) / 60
print(f" Quick (3ep): {quick} experiments Γ ~15 min")
print(f" Full (10ep): {full} experiments Γ ~40 min")
print(f" Estimated total: ~{hours:.0f} GPU-hours")
print(f" With 3 GPUs parallel: ~{hours/3:.0f} hours wall time ({hours/3/24:.1f} days)")
if __name__ == "__main__":
write_csv()
|