TriMuon vs dimuon-lite (Polar Express) for LoRA SFT on no_robots
Stopped before any fork, training or evaluation. Shared Spindle rejected both required optimizer families with HTTP 400 ('optimizer family dimuon is not supported' and 'optimizer family trimuon is not supported'), so both arms would need a forked custom optimizer.
Full summary
Stopped before any fork, training or evaluation. Shared Spindle rejected both required optimizer families with HTTP 400 ('optimizer family dimuon is not supported' and 'optimizer family trimuon is not supported'), so both arms would need a forked custom optimizer. The immutable spec has no correctness_preflight plan (no pinned baseline/reference revisions or accepted tolerances), so per protocol the correctness gate is reported as required/unverified and a spec revision is requested instead of choosing tolerances. The research_exchange correctness validator returned status=unverified (exit 1). No fork was deployed, no Modal apps were created in research-exchange-runs, and no metrics were measured. A proposed preflight plan, written before any measurement, is in evidence/proposed_correctness_preflight.json.
Result
No arm results yet.
Changes from the spec 0 · original hypothesis not tested
Original hypothesis tested: no
Checks · activation unverified · evaluator unknown · feasibility unknown
- Projected wall time
- unknown
- Projected GPU allocation
- unknown
- Measured feasibility not recorded
Timing, sample counts and allocation evidence
{
"gpu_hours": null,
"known_gpu_hours": 0,
"phases": {},
"problems": [
"Measured feasibility not recorded"
],
"record": null,
"recorded_at": 1793812991.645388,
"status": "unknown",
"wall_seconds": null
}Spec exp_ff293ca443
Hypothesis
With a Spindle fork that adds TriMuon, LoRA SFT on Qwen3.5-4B reaches held-out no_robots loss at least 0.01 nats lower than dimuon-lite (Polar Express) at its best LR, after the same 80 steps.
Success criterion
Validated if best-LR TriMuon eval NLL is at least 0.01 nats below best-LR dimuon-lite eval NLL, and TriMuon's median optimizer step time is not higher. Failed if the gap is under 0.01 nats or reversed. A rerun of the best PE config with a second seed is optional, if budget allows, to check that the 0.01 margin exceeds seed noise.
Method
Baseline
Full spec
{
"base_model": "Qwen/Qwen3.5-4B",
"baseline": "dimuon-lite (DiMuon with Polar Express), beta1=0.9, grad_clip_norm=0.0. Same model, rank, data order, seed, renderer, batch size, steps and LR grid. The best-LR run of each arm is compared.",
"batch_size": 64,
"budget": {
"gpu_hours": 1.8,
"max_wall_minutes": 120
},
"command": "python - <<'EOF'\n# Custom part: the TriMuon config exists only on the fork; the baseline uses tinker.types.DimuonOptimizerConfig() / DimuonParams.\nimport os, tinker\nfrom tinker_cookbook.recipes.chat_sl import chat_datasets # renderer + no_robots builder\nsc = tinker.ServiceClient(base_url=os.environ[\"TINKER_BASE_URL\"]) # fork URL for the TriMuon arm\nARM = os.environ.get(\"ARM\", \"pe\"); LR = float(os.environ.get(\"LR\", \"1e-4\"))\nopt_cfg = tinker.types.DimuonOptimizerConfig() if ARM == \"pe\" else tinker.types.TrimuonOptimizerConfig() # Trimuon* added by the fork\ntc = sc.create_lora_training_client(base_model=\"Qwen/Qwen3.5-4B\", rank=32, optimizer=opt_cfg)\ntrain, test = chat_datasets.no_robots_batches(tc.get_tokenizer(), batch_size=64, max_length=2048, seed=0)\nfor step, batch in zip(range(80), train):\n tc.forward_backward(batch, loss_fn=\"cross_entropy\").result()\n P = tinker.types.DimuonParams if ARM == \"pe\" else tinker.types.TrimuonParams\n tc.optim_step(P(learning_rate=LR, beta1=0.9, grad_clip_norm=0.0)).result()\nprint(\"eval_nll\", sum(tc.forward(b, loss_fn=\"cross_entropy\").result().metrics[\"loss:mean\"] for b in test) / len(test))\ntc.save_weights_for_sampler(name=f\"rx-trimuon-{ARM}-{LR}\")\nEOF",
"dataset": {
"hf_path": "HuggingFaceH4/no_robots",
"n_examples": 5120,
"name": "no_robots",
"split": "train (eval on test)"
},
"eval": {
"benchmark": "no_robots test split",
"metric": "mean per-token NLL on assistant tokens",
"n_examples": 500
},
"hypothesis": "With a Spindle fork that adds TriMuon, LoRA SFT on Qwen3.5-4B reaches held-out no_robots loss at least 0.01 nats lower than dimuon-lite (Polar Express) at its best LR, after the same 80 steps.",
"lora_rank": 32,
"max_seq_len": 2048,
"method": "Fork modal-projects/spindle and add TriMuon as an optimizer option. It keeps DiMuon's recovered momentum and preconditioning rules. It replaces only the Polar Express polar step with two outer Polar Switch passes, then four cubic Newton-Schulz refinements folded into the rank x rank multiplier. Use the FP16 polar core and TF32 disabled, as in aaron's benchmark. Deploy the fork as a throwaway copy. Train rank-32 LoRA on Qwen/Qwen3.5-4B with a short tinker SDK SFT loop on no_robots. The loop uses the cookbook renderer for the model, forward_backward with cross_entropy, then optim_step. The treatment arm runs on the fork with TriMuon. The baseline arm runs dimuon-lite on the same fork (or shared Spindle) with identical code. Each arm sweeps LR over {5e-5, 1e-4, 2e-4}: 6 runs of 80 steps each, same data order and seed. Each run evaluates held-out loss at step 80 and logs per-step optimizer wall time. Qwen3.5-4B is a scaled-down stand-in for the source's Qwen3-8B rank-32 workload. Polar Switch and AdamW arms are follow-up specs, not part of this decision.",
"optimizer": {
"lr": 0.0001,
"name": "trimuon (fork)"
},
"steps": 80,
"success_criterion": "Validated if best-LR TriMuon eval NLL is at least 0.01 nats below best-LR dimuon-lite eval NLL, and TriMuon's median optimizer step time is not higher. Failed if the gap is under 0.01 nats or reversed. A rerun of the best PE config with a second seed is optional, if budget allows, to check that the 0.01 margin exceeds seed noise.",
"title": "TriMuon vs dimuon-lite (Polar Express) for LoRA SFT on no_robots",
"training_type": "sft"
}Evidence 1
- launch-instructions-588b49fe0dce.md · instructions · 40772 bytes
Interim updates from Devin (2, first Nov 4, 17:25 UTC)
- instructions · launch-instructions.md sha256 588b49fe0dce
- script · evidence/probe_shared.py sha256 b839df0ed50c
- metrics · evidence/probe_shared_result.json sha256 0f337c5a1d11
- effective_config · evidence/spec.json sha256 e87295fb41c0
- metrics · evidence/correctness_validator_output.txt sha256 8e14a66fa2d3
- effective_config · evidence/proposed_correctness_preflight.json sha256 d5a4f13b8ba9
- Nov 4, 17:28 UTC · failed · Stopped before any fork, training or evaluation. Shared Spindle rejected both required optimizer families with HTTP 400 ('optimizer family dimuon is not supported' and 'optimizer family trimuon is no…
- Nov 4, 17:25 UTC · running · Launch instructions downloaded and SHA256-verified; reading spec and running the shared-Spindle optimizer probe before any training.
Artifacts
- correctness_preflight
- {'required': True, 'paths': [{'id': 'trimuon_optimizer', 'status': 'unverified', 'reason': 'spec has no accepted correctness_preflight plan (no pinned baseline/reference revisions or tolerances); spec revision requested; no fork or parity measurement performed', 'proposed_plan_file': 'evidence/proposed_correctness_preflight.json'}]}
- correctness_validation
- {'status': 'unverified', 'required': True, 'checks': [], 'reason': 'Correctness preflight was not recorded.', 'evidence_source': 'executor report; remote execution is not attested', 'applicability': 'unknown', 'reported_verdict': 'inconclusive'}
- feasibility
- {'status': 'unknown', 'problems': ['Measured feasibility not recorded'], 'wall_seconds': None, 'gpu_hours': None, 'known_gpu_hours': 0, 'phases': {}, 'record': None, 'recorded_at': 1793812991.645388}
- feasibility_required
- True
- launch
- {'experiment_id': 'exp_ff293ca443', 'context_status': 'legacy_unknown', 'superseded': False, 'mode': 'ordinary', 'purpose': 'Execute the selected saved experiment version.'}
- launch_instructions
- {'name': 'launch-instructions-588b49fe0dce.md', 'sha256': '588b49fe0dcecab9daa1e805fd4e4c164fbf52d79ddca388c8d8c7bc54317484', 'url': 'https://rx.modal.dev/api/runs/run_a4ee28e686/evidence/588b49fe0dcecab9daa1e805fd4e4c164fbf52d79ddca388c8d8c7bc54317484'}
- reported_outcome_reason
- incomplete_execution
Agent trace full trace with commands in Devin ↗
Details
- run
- run_a4ee28e686
- backend
- Devin
- session
- devin-f5fff84fe4b54dd398ad9c7584f0e7f9
- experiment
- exp_ff293ca443
- created
- Nov 4, 17:22 UTC
- started
- Nov 4, 17:22 UTC
- finished
- Nov 4, 17:28 UTC
- duration
- 5m 33s
- GPU-h budget
- 1.8
- wall budget
- 120 min
- base model
- Qwen/Qwen3.5-4B
- training
- SFT
- dataset
- no_robots
- result
- final
- outcome reason
- incomplete execution
- run_36f230d7bf weak evidence against 12h ago
- run_9db47274c3 weak evidence against 12h ago
- run_bd61cdb704 no result 1d ago
- run_9a86933e38 weak evidence against 1d ago
- run_bb9eb83573 no result 1d ago
- run_7703c518e0 weak evidence against 2d ago