Modal Research Exchange

you are

dimuon-lite vs AdamW for LoRA SFT on no_robots (Qwen3.5-0.8B, rank 32, 100 steps)

Failed no result Devin Qwen/Qwen3.5-0.8B SFT 1.5 GPU-h budget started 1d ago 15m 53s
Redo
Pick where the agent works.
View session in Devin ↗

This can't run on Spindle: the shared server rejects every dimuon-lite optim_step with HTTP 400 "optimizer family dimuon is not supported; optim_step accepts only adam_params", so only the AdamW arm can train. A pilot on Qwen/Qwen3.5-2B (Qwen3.5-0.8B is not served) ran 2 AdamW steps at batch 64 (train loss 2.527 then 2.372), and the first dimuon-lite optim_step failed with that error, which the tinker SDK reports as APIConnectionError.

No result No result: the run finished without measuring the effect.

Result

No arm results yet.

adam_lr1e-4_step0_train_nll
2.527
adam_lr1e-4_step1_train_nll
2.372
adam_step0_seconds
162.4
adam_step1_seconds
6.7
dimuon_optim_steps_completed
0
Changes from the spec 0

Not recorded: this run didn't report its changes from the spec, so they are unknown.

Checks · activation unverified · evaluator unknown · feasibility unknown
Custom implementation correctness: unverified
Correctness preflight was not recorded.
Validates executor-reported evidence; autonomous training calls are not blocked by this server.
Treatment activation: unverified
The spec has no activation gate or experiment features (it predates them), so whether the treatment engaged is unknown.
Initialization / optimizer verification: unverified
Initialization and optimizer evidence was not required by this saved spec.
Research decision: unknown
No prespecified decision rule was recorded.
Adaptation batches across paired arms: unknown (not verified)
The spec does not declare whether this check applies, and the run did not verify it. The run did not report adaptation batch manifests.
Evaluator comparability: unknown
Evaluator provenance was not recorded.
Generator reward audit
Generator reward audit: Unknown whether this run needed a teacher reward audit: its spec does not declare whether a teacher or task generator is trained. Nothing was recorded, so reward contributions are unknown.
Held-out loss aggregation
Spec asks for token mean (summed NLL / loss tokens) · run reported no record, so the aggregation behind its loss numbers is unknown
Feasibility projection: unknown
Projected costs, not measured GPU usage.
Measured feasibility was not recorded for this run.
Generated task audit: unverified: no audit recorded
Answer agreement with recorded independent solutions does not establish semantic correctness. Normalized exact overlap does not detect paraphrases.
Spec exp_1e07d824d1

Hypothesis

With each optimizer at its best learning rate from a 3-point sweep, dimuon-lite reaches a held-out no_robots test NLL at least 0.02 nats/token lower than AdamW after 100 steps of LoRA SFT, without lowering IFEval prompt-level strict accuracy by more than 2 points.

Success criterion

Validated if the two-seed mean test NLL of best-LR dimuon-lite is at least 0.02 nats/token below best-LR AdamW, the seed-to-seed spread of each arm is below 0.01, and IFEval strict accuracy for dimuon-lite is no more than 2.0 points below AdamW. Failed if the NLL gap is under 0.02 in either direction (no meaningful difference) or AdamW is better. Inconclusive if seed spread exceeds the gap.

no_robots 100 steps batch 64 LoRA r32 lr 0.0003 120 min wall budget
Method
Train a rank-32 LoRA on Qwen/Qwen3.5-0.8B with next-token cross-entropy on assistant tokens of HuggingFaceH4/no_robots train. Use one fixed shuffle (seed 0) and the cookbook's recommended renderer for the model. Max length is 2048, batch size 64, and training runs 100 optimizer steps at a constant learning rate. The single decision under test is the optimizer. Because the two optimizers have different natural LR scales, each gets a 3-point LR sweep: AdamW at {5e-5, 1e-4, 2e-4} and dimuon-lite at {1e-4, 3e-4, 1e-3}. That is 6 runs on identical batches in identical order. After step 100, compute token-weighted NLL on the first 500 examples of the no_robots test split via forward with cross_entropy. Pick the best LR per optimizer by test NLL, re-run that config once with a second data-shuffle seed (seed 1) to estimate seed noise, and report the mean. For the two best checkpoints, sample greedily (max_tokens 1024) on all 541 google/IFEval prompts and score prompt-level strict accuracy with the standard IFEval checker, client-side. Also log train-loss curves for both arms to compare convergence speed.
Baseline
AdamW via tinker.AdamParams (default betas), LoRA rank 32 on Qwen/Qwen3.5-0.8B, best of LR {5e-5, 1e-4, 2e-4}. Same data order, batch size 64, 100 steps, constant LR, max length 2048, renderer, eval set and second-seed rerun as the dimuon-lite arm.
Full spec
{
  "base_model": "Qwen/Qwen3.5-0.8B",
  "baseline": "AdamW via tinker.AdamParams (default betas), LoRA rank 32 on Qwen/Qwen3.5-0.8B, best of LR {5e-5, 1e-4, 2e-4}. Same data order, batch size 64, 100 steps, constant LR, max length 2048, renderer, eval set and second-seed rerun as the dimuon-lite arm.",
  "batch_size": 64,
  "budget": {
    "gpu_hours": 1.5,
    "max_wall_minutes": 120
  },
  "command": "# Custom part: optimizer selection (DimuonOptimizerConfig/DimuonParams vs AdamParams). Everything else is stock tinker SDK + cookbook data utils.\nimport os, random, datasets, tinker\nfrom tinker_cookbook import renderers, model_info\nfrom tinker_cookbook.tokenizer_utils import get_tokenizer\nfrom tinker_cookbook.supervised.data import conversation_to_datum\nM = 'Qwen/Qwen3.5-0.8B'; tok = get_tokenizer(M)\nr = renderers.get_renderer(model_info.get_recommended_renderer_name(M), tok)\nds = datasets.load_dataset('HuggingFaceH4/no_robots')\ntest = [conversation_to_datum(x['messages'], r, 2048) for x in ds['test'].select(range(500))]\nsc = tinker.ServiceClient(base_url=os.environ['TINKER_BASE_URL'])\ndef run(opt, lr, seed=0, steps=100, bs=64):\n    rows = list(ds['train']); random.Random(seed).shuffle(rows)\n    train = [conversation_to_datum(x['messages'], r, 2048) for x in rows[:steps*bs]]\n    if opt == 'dimuon':\n        tc = sc.create_lora_training_client(base_model=M, rank=32, optimizer=tinker.types.DimuonOptimizerConfig())\n        p = tinker.types.DimuonParams(learning_rate=lr, beta1=0.9, grad_clip_norm=0.0)\n    else:\n        tc = sc.create_lora_training_client(base_model=M, rank=32)\n        p = tinker.AdamParams(learning_rate=lr)\n    for s in range(steps):\n        tc.forward_backward(train[s*bs:(s+1)*bs], 'cross_entropy').result()\n        tc.optim_step(p).result()\n    out = tc.forward(test, 'cross_entropy').result()\n    num = sum(-(o['logprobs'].to_torch() * d.loss_fn_inputs['weights'].to_torch()).sum().item() for o, d in zip(out.loss_fn_outputs, test))\n    den = sum(d.loss_fn_inputs['weights'].to_torch().sum().item() for d in test)\n    path = tc.save_weights_for_sampler(name=f'{opt}-{lr}-s{seed}').result().path\n    print(opt, lr, seed, 'test_nll', num/den, path)\nfor lr in [5e-5, 1e-4, 2e-4]: run('adam', lr)\nfor lr in [1e-4, 3e-4, 1e-3]: run('dimuon', lr)\n# then: rerun best LR per optimizer with seed=1; sample IFEval (google/IFEval, 541 prompts, greedy, max_tokens=1024) from the saved sampler paths via sc.create_sampling_client(model_path=path) and score prompt-level strict accuracy",
  "dataset": {
    "hf_path": "HuggingFaceH4/no_robots",
    "n_examples": 6400,
    "name": "no_robots",
    "split": "train (eval on test, first 500)"
  },
  "eval": {
    "benchmark": "no_robots test held-out NLL (primary); IFEval (secondary)",
    "metric": "token-weighted NLL in nats/token on 500 test examples; IFEval prompt-level strict accuracy on 541 prompts",
    "n_examples": 500
  },
  "hypothesis": "With each optimizer at its best learning rate from a 3-point sweep, dimuon-lite reaches a held-out no_robots test NLL at least 0.02 nats/token lower than AdamW after 100 steps of LoRA SFT, without lowering IFEval prompt-level strict accuracy by more than 2 points.",
  "lora_rank": 32,
  "max_seq_len": 2048,
  "method": "Train a rank-32 LoRA on Qwen/Qwen3.5-0.8B with next-token cross-entropy on assistant tokens of HuggingFaceH4/no_robots train. Use one fixed shuffle (seed 0) and the cookbook's recommended renderer for the model. Max length is 2048, batch size 64, and training runs 100 optimizer steps at a constant learning rate. The single decision under test is the optimizer. Because the two optimizers have different natural LR scales, each gets a 3-point LR sweep: AdamW at {5e-5, 1e-4, 2e-4} and dimuon-lite at {1e-4, 3e-4, 1e-3}. That is 6 runs on identical batches in identical order. After step 100, compute token-weighted NLL on the first 500 examples of the no_robots test split via forward with cross_entropy. Pick the best LR per optimizer by test NLL, re-run that config once with a second data-shuffle seed (seed 1) to estimate seed noise, and report the mean. For the two best checkpoints, sample greedily (max_tokens 1024) on all 541 google/IFEval prompts and score prompt-level strict accuracy with the standard IFEval checker, client-side. Also log train-loss curves for both arms to compare convergence speed.",
  "optimizer": {
    "lr": 0.0003,
    "name": "dimuon-lite"
  },
  "steps": 100,
  "success_criterion": "Validated if the two-seed mean test NLL of best-LR dimuon-lite is at least 0.02 nats/token below best-LR AdamW, the seed-to-seed spread of each arm is below 0.01, and IFEval strict accuracy for dimuon-lite is no more than 2.0 points below AdamW. Failed if the NLL gap is under 0.02 in either direction (no meaningful difference) or AdamW is better. Inconclusive if seed spread exceeds the gap.",
  "title": "dimuon-lite vs AdamW for LoRA SFT on no_robots (Qwen3.5-0.8B, rank 32, 100 steps)",
  "training_type": "sft"
}
Evidence

Unknown: this run has no recorded evidence bundle.

All metrics
adam_lr1e-4_step0_train_nll
2.527
adam_lr1e-4_step1_train_nll
2.372
adam_step0_seconds
162.4
adam_step1_seconds
6.7
dimuon_optim_steps_completed
0
Agent trace full trace with commands in Devin ↗
Details
run
run_38487faf1f
backend
Devin
session
devin-3df09f0a50cc427eb65fc0be15e424d3
experiment
exp_1e07d824d1
redone as
run_774cc21400 no result
created
Nov 3, 04:11 UTC
started
Nov 3, 04:11 UTC
finished
Nov 3, 04:27 UTC
duration
15m 53s
GPU-h budget
1.5
wall budget
120 min
base model
Qwen/Qwen3.5-0.8B
training
SFT
dataset
no_robots
Other runs of this idea

Submit an idea

Most ideas come in from Slack threads. Use this when yours is not in one yet; the triage agent picks it up.