~/fba-lab/lab/speedrun/journey/keller-62-lab

FBALab

Code · architecture · study mode

AboutRoadmapSpeedrun
FBALab

Study mode — no GPU required.

Interactive LLM training & inference lab.

Qwen CAboutContactTermsPrivacyCookiesCommunity

© 2026 FBA Lab

Contact · contact@bubblspace.com · +91 75061 55016

Speedrun›Speedrun milestones›#62 · Bigram Hash
Act 1Model Training FundamentalsAct 2AI Systems OptimizationAct 3World-Record Training Optimization
Step 27 of 28Skill: World-Record Training Optimization
← #54 · Logit Rescale#84 · FP8 Precision →
TRAINING SIMULATION

#62 · Bigram Hash

running
◷train_gpt.py▸bigram_embed initialization◎learner$no GPU
1/2
Blocks
Quick summary

A 251,519-entry embedding table (one slot per hashed bigram pair) is added alongside the standard token embedding. It…

Full explanation below the code →

fba-lab — train_gpt.py · bigram_embed initializationexecuting
// block: bigram_embed initialization · lines 1175–1178$ study train_gpt.py --block bigram-embed-initA 251,519-entry embedding table (one slot per hashed bigram pair) is added alongside the standard to… ✓
Explanation

A 251,519-entry embedding table (one slot per hashed bigram pair) is added alongside the standard token embedding. It starts at zeros — the model must learn from scratch which bigram pairs are informative. The label marks it for special optimizer treatment (no beta smoothing in Muon).

Think about

Why initialize bigram embeddings to zero rather than a small random value?

// architecture

Live diagram

100%
Record #62 · PR #201 · Bigram Hash Embedding · −5.6 s, −165 steps
Input representation

A hash table bakes token-pair knowledge into every embedding lookup

Standard transformers look up one embedding per token. But language is full of bigram patterns — "New York", "don't", "machine learning" — where the meaning of a token depends strongly on the token before it. The model can learn these eventually through attention, but it costs depth and compute.

PR #201 adds a second embedding table indexed by hashed (previous token, current token) pairs. At every position, the model gets both the token embedding and a bigram signal for free, before the first attention layer. The hash maps 2.5 billion possible bigram pairs into 251,519 buckets using XOR of two large multipliers. Collisions are handled by a sign trick that gives each pair a near-orthogonal direction even from the same bucket.

token t-1 token t XOR hash bucket mod 251,519 bigram vector ±sign per pair + token embed
# lines 1406–1421 — XOR hash maps bigram pair to bucket
def get_bigram_hash(prev, curr):
    h = (prev * 1_000_003) ^ (curr * 999_983)
    return h % 251_519 # prime → minimal clustering

# embedding: token + bigram signal combined at input
x = token_embed[tokens] + bigram_embed[bigram_hash] * bigram_sign
What does the sign trick solve?

About 10,000 different bigram pairs hash to the same bucket. Without the sign trick, they would all pull the same embedding in the same direction and interfere with each other. Each pair gets a unique ±1 per-dimension mask. Colliding pairs end up with nearly orthogonal effective vectors from the same row — a kind of locality-sensitive encoding.

Why does this save 165 training steps?

The model no longer needs to learn bigram statistics from scratch through attention layers. Common patterns — contractions, compound words, common phrases — are available at the input layer from step 1. This frees attention depth to learn higher-order syntax and semantics, reaching the same loss in fewer steps.

What changed vs #54

Select a change to view diff hunks.