Three findings from 106 training runs on a Fourier KAN, all rerun from scratch in October 2026 with the code this site exports. Every number on this page is computed from the run log when the site is built.
What ran, and where
Every run fits the same target, the chirp g(x) = sin(2πx) + cos(πx²) + cos(πx³)·sin(πx³) on [-2, 2]. A Fourier KAN is trained on a CPU in float32 with AdamW, fresh batches of 128 samples per step, and Gaussian training noise. Each trained model is then scored on 500 evenly spaced points, three ways:
Path
What it is
CPU float32
The trained weights in full precision.
bfloat16, emulated
Inputs, weights and outputs rounded to bfloat16 in PyTorch. Rounding only.
Toolkit CPU emulator, bfloat16
The same weights through the Q.ANT toolkit, version 2.3.1.
No result on this page comes from photonic hardware. The toolkit reports what it runs on, and every run recorded its answer: driver cpu-backend;commit:none;, which is the toolkit’s CPU emulator. The emulator computes an exact cosine in bfloat16. A real card computes the optical tcos shape and adds analog effects, so hardware numbers will differ. When someone runs the bundle on a card, the result will say so.
106 runs, 33 minutes of training, on a Linux x86_64 machine with Python 3.13.16 and PyTorch 2.14.1+cpu. A model that predicts zero everywhere scores 1.1556.
1. The precision floor
The best long run: [1, 16, 1], grid 16, 1,041 parameters, learning rate 0.002, 60,000 steps with a cosine schedule. The same weights, three ways:
Path
MSE
CPU float32
0.0000200
bfloat16, emulated
0.000962
Toolkit CPU emulator, bfloat16
0.00128
Toolkit vs float32
64x
Same weights, three number paths
measured · log scale
CPU float32bfloat16 rounding, emulated in PyTorchToolkit CPU emulator, bfloat16
Across the 4 long runs, float32 scores range from 0.0000200 to 0.0000891. On the toolkit path they all land between 0.00128 and 0.00195. Better float32 training barely moves the bfloat16 result, because the limit is the number format rather than the model.
Rounding alone, emulated in PyTorch, accounts for about 75% of the gap on the best run. The rest comes from how the toolkit computes in bfloat16 internally.
If you deploy to bfloat16 hardware: stop training once float32 loss is well under the format’s floor. Past that point you pay for accuracy the device cannot represent.
2. Learning rate beats architecture
The largest network in the sweep, [1, 16, 16, 16, 1] with grid 16 on every layer, 17,457 parameters, 8,000 steps, no schedule. Identical apart from one setting.
Learning rate
MSE, float32
MSE, toolkit emulator
0.005
1.1649
1.1777
0.001
0.00332
0.00536
Swing
220x
[1, 16, 16, 16, 1], grid 16, 8,000 steps
measured · toolkit emulator
targetlr 0.005, MSE 1.1777lr 0.001, MSE 0.00536predicting zero everywhere: 1.1556
At 0.005 the network scored 1.1777, worse than predicting zero everywhere (1.1556). It did not train at all. Dropping the rate to 0.001 fixed it. The big first grid network also failed at 0.005.
3. Past a low threshold, size stops mattering
64 runs, all at 8,000 steps, sweeping width, depth, grid and two learning rates.
Parameters against error, 64 runs
measured · toolkit emulator · log scales
lr 0.003lr 0.005within 25% of the best run (16 of 64)
Hover a point for its configuration. Every run trained for 8,000 steps.
A 393 parameter model scored 0.00273. A 4,057 parameter model, 10 times larger, scored 0.00301.
The runs do not all cluster. 16 of the 64 runs landed within 25% of the best, and the full range ran from 0.00263 to 0.0117. The claim is about the paired configurations above and the early ceiling, not about every run.
Repeat it yourself
Everything needed to reproduce this page is public.