Skip to content

Commit f07a6fd

Browse files
authored
Merge pull request #51 from SethTS/exp/grokfast-v2
exp: GrokFast v2 — WIN on k=5 (2.5x speedup)
2 parents 3f49958 + 989eb91 commit f07a6fd

6 files changed

Lines changed: 1122 additions & 1 deletion

File tree

DISCOVERIES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
- **Hidden progress is real**: ||w_t - w_0||_1 grows steadily even when accuracy is flat. This is a useful leading indicator. [exp1]
2121
- **With correct hyperparams, grokking is fast**: 5 epochs to 100% with single-sample SGD (LR=0.1, n_train=500). [exp4 baseline]
2222
- **GrokFast is counterproductive** when hyperparams are already correct. It amplifies gradients that don't need amplifying, causing 83x more weight movement and slower convergence. [exp4]
23+
- **GrokFast helps when k is large**: On n=20/k=5, aggressive GrokFast (a=0.98, l=2.0) gives 2.5x fewer epochs (29 vs 73) and 2.3x faster wall time than SGD. The EMA accumulates the exponentially weak k-th order gradient signal. But on n=30/k=3, it hurts (40% solve rate) because it amplifies noise dimensions. The critical variable is interaction order, not input dimension. [exp_grokfast_v2]
2324

2425
### Training Variants & ARD
2526

TODO.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ the grokking plateau.
125125
### Gradient manipulation
126126

127127
- [x] Egalitarian Gradient Descent (EGD): normalize gradients so all principal directions evolve at same speed. Halves epoch count (14 vs 36 to 90%) but SVD overhead makes wall time 12% worse. Does not break 10ms. Robust to gradient scale (solves sum where SGD diverges). [exp_egd]
128-
- [ ] Grokfast with corrected config: amplify slow gradient components. Phase 1 test (exp4) used broken config (lr=0.5 overshooting). Retest with lr=0.1 and correct setup. Ref: https://arxiv.org/abs/2405.20233
128+
- [x] Grokfast v2: tested across 3 regimes (n20k3, n30k3, n20k5) with 3 hyperparameter settings, 5 seeds each. WIN on k=5 (2.5x speedup), LOSS on n=30/k=3, neutral on n=20/k=3. [exp_grokfast_v2]
129129
- [ ] GrokTransfer: train small model (n=5/k=3) first, transfer embedding to full model (n=20/k=3). Should eliminate phase transition. Ref: https://arxiv.org/abs/2504.13292
130130

131131
### Initialization

findings/exp_grokfast_v2.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# Experiment: GrokFast v2 — Hard Regime Testing
2+
3+
**Date**: 2026-03-23
4+
**Status**: COMPLETED — WIN on k=5, LOSS on n=30/k=3, NEUTRAL on n=20/k=3
5+
**Researcher**: Seth Stafford
6+
7+
## Question
8+
9+
Does GrokFast accelerate grokking on harder sparse parity configurations where the
10+
phase transition is genuinely delayed? (exp4 showed it was counterproductive on the
11+
easy n=20/k=3 regime.)
12+
13+
## Hypothesis
14+
15+
GrokFast amplifies slow gradient components via EMA filtering. It should help when
16+
the grokking plateau is long (high-k problems with k-th order interactions), even
17+
if it hurts on easy problems where SGD already converges fast.
18+
19+
## What was performed
20+
21+
Tested SGD vs GrokFast with 3 hyperparameter settings across 3 difficulty regimes,
22+
5 seeds each (75 total runs). All use numpy-accelerated mini-batch SGD (batch_size=32).
23+
24+
| Parameter | easy_n20_k3 | hard_n30_k3 | hard_n20_k5 |
25+
|-----------|-------------|-------------|-------------|
26+
| n_bits | 20 | 30 | 20 |
27+
| k_sparse | 3 | 3 | 5 |
28+
| hidden | 200 | 200 | 200 |
29+
| lr | 0.1 | 0.1 | 0.1 |
30+
| wd | 0.01 | 0.01 | 0.01 |
31+
| max_epochs | 200 | 200 | 500 |
32+
| n_train | 1000 | 1000 | 2000 |
33+
| batch_size | 32 | 32 | 32 |
34+
35+
GrokFast settings tested:
36+
- **(a=0.98, l=2.0)**: Original paper defaults — aggressive
37+
- **(a=0.95, l=1.0)**: Less aggressive smoothing and amplification
38+
- **(a=0.99, l=0.5)**: High smoothing, gentle amplification
39+
40+
## What was produced
41+
42+
### n=20, k=3 (easy — confirms exp4)
43+
44+
| Method | Solve Rate | Avg Epoch | Avg Time |
45+
|--------|-----------|-----------|----------|
46+
| SGD | 100% | 39 | 0.08s |
47+
| GrokFast(0.98, 2.0) | **80%** | 200 | 0.17s |
48+
| GrokFast(0.95, 1.0) | 100% | 34 | 0.07s |
49+
| GrokFast(0.99, 0.5) | 100% | 37 | 0.12s |
50+
51+
Aggressive GrokFast hurts. Mild settings are neutral.
52+
53+
### n=30, k=3 (more noise dimensions)
54+
55+
| Method | Solve Rate | Avg Epoch | Avg Time |
56+
|--------|-----------|-----------|----------|
57+
| SGD | 100% | 91 | 0.19s |
58+
| GrokFast(0.98, 2.0) | **40%** | 200 | 0.25s |
59+
| GrokFast(0.95, 1.0) | 100% | 85 | 0.20s |
60+
| GrokFast(0.99, 0.5) | 100% | 95 | 0.24s |
61+
62+
Aggressive GrokFast is even worse with more noise dimensions (40% solve rate).
63+
Mild settings are again neutral — slightly fewer epochs but similar or worse wall time.
64+
65+
### n=20, k=5 (higher-order interactions)
66+
67+
| Method | Solve Rate | Avg Epoch | Avg Time |
68+
|--------|-----------|-----------|----------|
69+
| SGD | 100% | 73 | 0.35s |
70+
| **GrokFast(0.98, 2.0)** | **100%** | **29** | **0.15s** |
71+
| GrokFast(0.95, 1.0) | 100% | 37 | 0.19s |
72+
| GrokFast(0.99, 0.5) | 100% | 54 | 0.29s |
73+
74+
**GrokFast wins decisively.** The aggressive setting (a=0.98, l=2.0) gives 2.5x
75+
fewer epochs and 2.3x faster wall time. All three GrokFast settings outperform SGD.
76+
77+
## Can it be reproduced?
78+
79+
Yes. 5 seeds per configuration, all 100% solve rate on the winning regime.
80+
Script: `src/sparse_parity/experiments/exp_grokfast_v2.py`
81+
Results: `results/exp_grokfast_v2/results.json`
82+
83+
## Finding
84+
85+
**GrokFast accelerates grokking when k is large (higher-order interactions create a
86+
genuinely long plateau) but is harmful or neutral when n is large (more noise
87+
dimensions to amplify).** The critical variable is interaction order, not input
88+
dimension. On n=20/k=5, aggressive GrokFast (a=0.98, l=2.0) gives a 2.5x epoch
89+
reduction and 2.3x wall-time speedup over vanilla SGD.
90+
91+
## Analysis
92+
93+
### Why k matters more than n
94+
95+
GrokFast amplifies slowly-evolving gradient components. For sparse parity:
96+
- **High k**: The network must discover a k-th order interaction. The gradient signal
97+
for the correct feature combination is exponentially weak early in training
98+
(proportional to 1/2^k). GrokFast accumulates this weak signal over time via the
99+
EMA, effectively boosting signal-to-noise.
100+
- **High n with low k**: More noise dimensions means the EMA accumulates noise too.
101+
With k=3, the gradient signal is already strong enough that amplification adds
102+
more noise than signal.
103+
104+
### The aggressive setting is polarized
105+
106+
(a=0.98, l=2.0) is either the best or worst setting depending on the regime. This
107+
makes sense: strong amplification helps when the signal is genuinely weak (k=5) but
108+
causes instability when the signal is already adequate (k=3).
109+
110+
### Mild GrokFast is never worse than SGD
111+
112+
(a=0.95, l=1.0) matches or slightly beats SGD across all regimes. This could be a
113+
safe default for unknown problem difficulty.
114+
115+
## Open questions
116+
117+
- Does GrokFast + curriculum compound? Curriculum shortens the plateau from the
118+
input-dimension side; GrokFast shortens it from the interaction-order side.
119+
- What happens at k=7 or k=10? The speedup may grow with k.
120+
- Can we adaptively tune lambda based on gradient variance during training?
121+
122+
## Files
123+
124+
- Experiment script: `src/sparse_parity/experiments/exp_grokfast_v2.py`
125+
- Results JSON: `results/exp_grokfast_v2/results.json`
126+
127+
## References
128+
129+
- Lee et al. 2024, "GrokFast: Accelerated Grokking by Amplifying Slow Gradients" — https://arxiv.org/abs/2405.20233
130+
- exp4 (previous GrokFast test on easy regime): `findings/exp4_grokfast.md`

research/log.jsonl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,4 @@
3131
{"id": "yad-031", "researcher": "yad", "date": "2026-03-06", "challenge": "sparse-parity", "hypothesis": "RL learns to query only the relevant bits", "method": "rl", "changed": {"method": "rl"}, "baseline": {"method": "sgd", "ard": 17976}, "result": {"accuracy": 1.0, "ard": 1, "time_s": null}, "delta_pct": {"ard": -99.99}, "class": "WIN", "notes": "Reads exactly k=3 bits per prediction. ARD=1 at inference. Value-blind state was key to making Q-learning converge."}
3232
{"id": "yad-032", "researcher": "yad", "date": "2026-03-06", "challenge": "sparse-parity", "hypothesis": "MDL finds secret via compression", "method": "mdl", "changed": {"method": "mdl"}, "baseline": {"method": "fourier", "time_s": 0.009}, "result": {"accuracy": 1.0, "ard": null, "time_s": 0.012}, "delta_pct": {"time_s": 33.3}, "class": "LOSS", "notes": "Works and is noise-robust (5% label noise ok). True subset compresses to 0 bits, wrong subsets ~499 bits. 30% slower than Fourier."}
3333
{"id": "yad-033", "researcher": "yad", "date": "2026-03-11", "challenge": "sparse-parity", "hypothesis": "Germain's hidden=64 is a locality win", "method": "sgd", "changed": {"hidden": 64}, "baseline": {"method": "sgd", "hidden": 200, "ard": 17976}, "result": {"accuracy": 1.0, "ard": 2129, "time_s": null}, "delta_pct": {"ard": -88.2}, "class": "LOSS", "notes": "ARD per float accessed is identical (0.367 vs 0.368). The improvement is the model being 68% smaller, not better locality."}
34+
{"id":"SethTS-001","researcher":"SethTS","date":"2026-03-23","challenge":"sparse-parity","hypothesis":"GrokFast helps when grokking plateau is genuinely long (high k)","method":"grokfast-v2","changed":{"regimes":"n20k3,n30k3,n20k5","alpha":[0.95,0.98,0.99],"lambda":[0.5,1.0,2.0],"seeds":5},"result":{"n20k5_sgd_epochs":73,"n20k5_grokfast_epochs":29,"n20k5_speedup":"2.5x","n30k3_grokfast_solve_rate":0.4,"n20k3_grokfast_solve_rate":0.8},"class":"PARTIAL","notes":"WIN on k=5 (2.5x speedup), LOSS on n=30/k=3 (40% solve rate), NEUTRAL on n=20/k=3. Interaction order is the critical variable, not input dimension."}

0 commit comments

Comments
 (0)