Repository navigation
fix: sync model vocab_size to actual tokenizer vocab; bump default LR to 5e-3 - #5
Merged
Merged
Conversation
Bug: cmd_train_stage1 built model_cfg with vocab_size=2000 (from
ModelConfig::nano), then trained a BPE tokenizer that produced only 669
tokens on the 640-sentence corpus. The model's 2000-slot output head had
1331 dead logits that never received a positive gradient signal but still
participated in the softmax denominator, artificially inflating CE loss.
Fix (src/main.rs):
- Make model_cfg mutable after preset selection.
- After BpeTokenizer::train returns, read tokenizer.vocab_size() and
sync model_cfg.vocab_size to that value when they differ.
- Print a clear message explaining the sync so users understand why the
saved config.json shows a different vocab_size than the preset.
Tuning (src/config.rs):
- TrainConfig::default lr: 3e-3 → 5e-3
The ~669-token synthetic task is small; 5e-3 converges noticeably
faster with no instability observed.
- TrainConfig::default warmup_steps: 100 → 200
Longer warmup stabilises early steps at the higher LR.
Before / after (200-step smoke test):
initial loss : 41.78 → 35.30 (-15% — fewer dead logits at init)
final loss : 10.44 → 9.57 ( -8%)
smooth-10% : 13.81 → 10.52 (-24%)
model size : 5.1 MB → 4.4 MB (smaller output projection)
32/32 tests pass · 0 clippy warnings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
After Phase 4 merged, the initial training loss was ~41.78 — much higher than expected.
Root cause:
cmd_train_stage1built the model withvocab_size=2000(fromModelConfig::nano()), but then trained a BPE tokenizer that only produced 669 tokens on the 640-sentence corpus. The model's output head had 1,331 dead logits that:Expected initial loss for 669 tokens:
ln(669) ≈ 6.5. Actual was 41.78 — the dead logits were adding ~35 nats of noise.Fix
src/main.rsAfter
BpeTokenizer::trainreturns, compare the actual vocab size tomodel_cfg.vocab_sizeand sync them:The saved
config.jsonnow records the actual vocab size soload_checkpointreconstructs the model with the correct output head.src/config.rslr3e-35e-3warmup_steps100200Before / After (200-step smoke test)
CI
cargo fmt --check✅cargo clippy --all-targets -- -D warnings✅ (0 warnings)cargo test --no-fail-fast✅ 32/32 pass