HyperNetworks and compressed weight representations for JAX / Flax NNX.
Project description
🏗️ Synecdoche
HyperNetworks and compressed weight representations for JAX / Flax NNX.
Synecdoche (si-NEK-duh-kee) is the figure of speech in which a part stands in for the whole — "all hands on deck." Fittingly, this library lets a small, easy-to- manipulate set of parameters stand in for all the weights of a much larger network: you train or evolve the part, and it generates the whole.
import synecdoche as syn
from flax import nnx
model = nnx.Linear(256, 256, rngs=nnx.Rngs(0)) # 65 792 parameters
target = nnx.state(model, nnx.Param) # the template
hyper = syn.DCT(target, embedding_dim=32, rngs=nnx.Rngs(1))
syn.apply_to(model, hyper) # model now runs on generated weights
print(syn.compression_ratio(hyper, model)) # a much smaller description
Why
A hypernetwork replaces a network's weights with a generator. That buys you three things:
- Compression — describe many weights with few numbers.
- Structure / inductive bias — the generator constrains what kinds of weight matrices are reachable (smooth, low-rank, tied, …).
- Tractable search — evolution strategies and other black-box optimisers have variance that grows with the number of parameters, so they don't scale to full networks. Move the search into the hypernetwork's small latent space and they become viable again. (This is why synecdoche pairs naturally with spiking / non-differentiable networks trained by evolution.)
Everything is a plain flax.nnx.Module, so generated weights drop into any NNX
model, and the generator's parameters train by gradient or evolve by ES.
Generators
Build any of these from a target's nnx.state(model, nnx.Param); call it to get a
matching weight pytree.
| Generator | Idea | Learnable params |
|---|---|---|
RandomProjection |
fixed random basis · learnable embeddings (random-feature indirect encoding) | num_layers × embedding_dim |
DCT |
inverse-DCT of a few low-frequency coefficients — compressed weight search (Koutník, Gomez & Schmidhuber, 2010) | num_layers × embedding_dim |
LowRank |
left @ right factorisation of the stacked weights |
rank × (num_layers + max_size) |
MLPHyper |
a shared MLP decodes per-layer embeddings (Ha, Dai & Le, HyperNetworks, 2016) | embeddings + MLP |
experimental.DynamicHypernetwork |
weights conditioned on the input batch (fast-weights / meta-learning) | embeddings + MLP |
RandomProjection and DCT are the strong compressors; LowRank / MLPHyper are
more expressive but compress only when the target's layers are large relative to
their number (the generators pad to the largest layer — see the docstrings).
Training the compressed representation
Inside nnx.jit / nnx.grad / an ES loop, don't mutate the target model in place —
rebuild it functionally from generated weights with syn.functional:
apply = syn.functional(model) # capture structure once
def loss_fn(hyper):
return mse(apply(hyper, X), Y) # forward on generated weights
opt = nnx.Optimizer(hyper, optax.adam(3e-3), wrt=nnx.Param)
loss, grads = nnx.value_and_grad(loss_fn)(hyper) # grads w.r.t. the hypernetwork
opt.update(hyper, grads)
See examples/compress_and_train.py for a runnable
end-to-end fit (16× compression, trains to convergence).
Lazy weights (optional, via quax)
pip install synecdoche[quax] adds synecdoche.lazy: weights that keep their
compressed form all the way into the computation and never materialise in full,
using quax's multiple dispatch. A low-rank weight computes x @ (a @ b) as
(x @ a) @ b — the full matrix is never formed.
import quax, synecdoche.lazy as sl
w = sl.LowRankWeight.init((1024, 1024), rank=8, rngs=nnx.Rngs(0)) # 8·2048 params, not 1M
y = quax.quaxify(lambda W, x: x @ W)(w, x) # never forms 1024×1024
Install
pip install synecdoche # core (jax + flax)
pip install synecdoche[quax] # + lazy never-materialised weights
Roadmap
- Generative weight generators — sampling weights from a learned distribution (diffusion / VAE over checkpoints, after Neural Network Diffusion and G.pt), the stochastic counterpart to the deterministic generators here.
- Per-layer output heads so
LowRank/MLPHypercompress heterogeneous architectures without the pad-to-max-size overhead. - First-class
spyxadapter for evolving spiking networks in the compressed space.
References
- Koutník, Gomez & Schmidhuber. Evolving neural networks in compressed weight space. GECCO 2010.
- Ha, Dai & Le. HyperNetworks. ICLR 2017.
- Kidger et al. quax — JAX + multiple dispatch for custom array types.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file synecdoche-0.2.0.tar.gz.
File metadata
- Download URL: synecdoche-0.2.0.tar.gz
- Upload date:
- Size: 11.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8602c7cab7899d0c8909ca3891fcebcd9481b26cfa44db8612adede9ff9a4b0
|
|
| MD5 |
20f9912b31ec65a96a717b84cfd434dc
|
|
| BLAKE2b-256 |
37df40f4934028e7c75fa19e629545bb42ae4c5fd262134c6619088019d1273b
|
Provenance
The following attestation bundles were made for synecdoche-0.2.0.tar.gz:
Publisher:
python-publish.yml on kmheckel/synecdoche
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synecdoche-0.2.0.tar.gz -
Subject digest:
a8602c7cab7899d0c8909ca3891fcebcd9481b26cfa44db8612adede9ff9a4b0 - Sigstore transparency entry: 2089809495
- Sigstore integration time:
-
Permalink:
kmheckel/synecdoche@35c06225282aec0536febf1def6d258e888f56a6 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/kmheckel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@35c06225282aec0536febf1def6d258e888f56a6 -
Trigger Event:
release
-
Statement type:
File details
Details for the file synecdoche-0.2.0-py3-none-any.whl.
File metadata
- Download URL: synecdoche-0.2.0-py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c747a4cb6d23f2315cb81152673a72af82872e908bb4a2a2ed4be262088cb30
|
|
| MD5 |
cbc68003711c204f0f15230f2dca2484
|
|
| BLAKE2b-256 |
15136fd68229398bd47af9637b4acb93e17becac8163d22a4938955b67d35fc5
|
Provenance
The following attestation bundles were made for synecdoche-0.2.0-py3-none-any.whl:
Publisher:
python-publish.yml on kmheckel/synecdoche
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
synecdoche-0.2.0-py3-none-any.whl -
Subject digest:
2c747a4cb6d23f2315cb81152673a72af82872e908bb4a2a2ed4be262088cb30 - Sigstore transparency entry: 2089809839
- Sigstore integration time:
-
Permalink:
kmheckel/synecdoche@35c06225282aec0536febf1def6d258e888f56a6 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/kmheckel
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@35c06225282aec0536febf1def6d258e888f56a6 -
Trigger Event:
release
-
Statement type: