Skip to content

Commit b82129c

Browse files
author
semantic-release
committed
0.13.1
Automatically generated by python-semantic-release
1 parent 4b9b255 commit b82129c

3 files changed

Lines changed: 92 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,96 @@
11
# CHANGELOG
22

33

4+
## v0.13.1 (2026-07-22)
5+
6+
### Bug Fixes
7+
8+
- Scale random projections by 1/sqrt(p) (Johnson-Lindenstrauss)
9+
([#346](https://github.com/EleutherAI/bergson/pull/346),
10+
[`4b9b255`](https://github.com/EleutherAI/bergson/commit/4b9b255b332d6efb15452873a41afcd57a2ca26e))
11+
12+
* Scale random projections by 1/sqrt(p) (Johnson-Lindenstrauss)
13+
14+
create_projection_matrix normalized each row over its n entries, giving entry variance 1/n. JL
15+
requires 1/p (p = projected dim) so that E[A^T A] = I and projected inner products are unbiased.
16+
The consequence is not the overall scale — a constant cancels from any ranking — but that the
17+
factor p/n depends on the module's SHAPE, so modules are silently reweighted against each other in
18+
the summed score. Attention (d x d) and MLP (d x 4d) blocks differ by 4x.
19+
20+
Measured E[proj]/true, 3000 draws per shape:
21+
22+
shape p before predicted p^2/(o*i) after 32x32 16 0.24972 0.25000 0.99889 64x64 32 0.25042 0.25000
23+
1.00167 128x128 32 0.06247 0.06250 0.99949 256x64 32 0.06253 0.06250 1.00045
24+
25+
This matches the TrackStar paper (arXiv 2410.17413 §A.1.2), which specifies the same two-sided
26+
per-block projection and states "Projection matrix entries are sampled i.i.d. from N(0, 1/d)" —
27+
variance 1/(number of rows), exactly A /= sqrt(m). It also matches docs/preprocessing.rst's claim
28+
that projections preserve inner products, which the old scaling did not.
29+
30+
Existing tests could not catch this: they compare the collector against L @ G @ R^T using the SAME
31+
matrices, so they are invariant to how those are scaled. test_global_projection_linearity uses one
32+
R sliced into blocks — the paper's construction, not the code's.
33+
tests/test_projection_inner_products.py now pins projected against unprojected (12 tests, all 12
34+
fail without this fix), including that the scale does not depend on module shape.
35+
36+
BREAKING: changes all stored index scales. Existing indices built with projection_dim > 0 must be
37+
regenerated, and any published numbers re-run. runs/test_build_cache.npy is regenerated here; the
38+
measured ratio is exactly 0.5000, matching theory (sqrt(o*i)/p = 8/16 for tiny-Phi3).
39+
40+
THREE TESTS FAIL ON THIS BRANCH AND ARE LEFT FAILING, PENDING A DECISION:
41+
42+
tests/test_batch_size_invariance.py::test_gradient_scale_invariance[100-100]
43+
tests/test_batch_size_invariance.py::test_gradient_scale_invariance[50-150] Relative error is
44+
UNCHANGED by this fix (6.83e-06 on main vs 7.58e-06 here) and already exceeds the assert_close
45+
default rtol=1.3e-06 on main. It passes on main only because the values are ~150x smaller, so the
46+
absolute difference stays under atol=1e-05. Restoring the correct scale trips atol. The test is
47+
magnitude-sensitive rather than wrong about the invariant.
48+
49+
tests/test_gradients.py::test_gradient_collector_proj_norm 1 of 256 elements, greatest relative
50+
difference 2.46e-04 against the test's explicit 1e-4 tolerance. Probably a near-cancelling element
51+
landing differently at the new scale — the test already carries a comment about accumulating
52+
numerical error — but this is NOT proven.
53+
54+
These are regression guards; loosening them is a call for a human, not something to do to make a
55+
branch green.
56+
57+
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58+
59+
* Make two projection tests independent of gradient magnitude
60+
61+
test_gradient_scale_invariance compared std separately-vs-combined with assert_close's defaults. The
62+
invariant is scale-free, but the default atol=1e-5 let a relative disagreement pass whenever the
63+
operands were small enough: on main the relative error is already 6.83e-06 against rtol=1.3e-06,
64+
and the test passes only because the values are ~150x smaller than the correctly-scaled ones. Use
65+
rtol=1e-4 with atol=0 so the check tracks the invariant rather than the magnitude.
66+
67+
test_gradient_collector_proj_norm compares A @ normalize(g) @ B.T against the collector, which
68+
projects activations and output grads separately. The two orderings are mathematically identical
69+
and differ only in fp32 rounding; at the corrected scale that noise reached 2.46e-04 relative on
70+
an O(1) element, over the existing 1e-4. Widen to 1e-3 and say what the tolerance is measuring.
71+
72+
* Add projection_scale to read indexes built with the old scaling
73+
74+
Indexes store their projected gradients, so changing the projection scaling makes existing ones
75+
unreadable at the correct weighting. projection_scale selects the convention: "jl" (default,
76+
variance 1/projection_dim) or "row_norm".
77+
78+
GradientProcessor.load resolves a missing projection_scale key to "row_norm", so existing indexes
79+
keep working with no user action, and new ones record "jl" in processor_config.yaml. Threaded
80+
through IndexConfig, create_processor and EkfacConfig, which builds matching matrices to compress
81+
the IVHP output.
82+
83+
* [pre-commit.ci] auto fixes from pre-commit.com hooks
84+
85+
for more information, see https://pre-commit.ci
86+
87+
---------
88+
89+
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
90+
91+
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
92+
93+
494
## v0.13.0 (2026-07-19)
595

696
### Features

bergson/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "0.13.0"
1+
__version__ = "0.13.1"
22

33
import logging
44

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ dependencies = [
3737
"bitsandbytes",
3838
"huggingface-hub>=1.13.0",
3939
]
40-
version = "0.13.0"
40+
version = "0.13.1"
4141
[project.optional-dependencies]
4242
dev = [
4343
"pre-commit",

0 commit comments

Comments
 (0)