eqxbatch
Batched evaluation of Equinox modules: a
vmap that lives in the PyTree.
pip install eqxbatch
Why
Equinox's position is that a Module is a PyTree, so you batch by transforming
functions — eqx.filter_vmap at the call site — rather than by wrapping modules. That is
the right answer whenever the module is the outermost object you call, and you should keep
doing it.
It stops being available when the batched module has to remain a node inside a larger tree that is driven through one generic entry point:
Sum(Batched(inner_a), inner_b) # no call site to hang a filter_vmap on
Here the vmap has to live in the tree itself. Batched is that node.
Usage
import equinox as eqx
import jax
from eqxbatch import Batched, broadcast, stack
keys = jax.random.split(jax.random.key(0), 8)
mlps = [eqx.nn.MLP(2, 2, 8, 2, key=k) for k in keys]
ensemble = Batched(stack(*mlps)) # list[Module] -> one batched Module
x = jax.random.normal(jax.random.key(1), (2,))
ensemble(x).shape # (8, 2) -- one shared input, eight models
ensemble[3] # mlps[3], as an ordinary module again
len(ensemble) # 8
One input per batch element instead of a shared one:
per_member = Batched(stack(*mlps), arg_axes=eqx.if_array(0))
xs = jax.random.normal(jax.random.key(1), (8, 2))
per_member(xs).shape # (8, 2)
Same starting parameters, diverging during training:
ensemble = Batched(broadcast(eqx.nn.MLP(2, 2, 8, 2, key=keys[0]), 8))
Or build it the idiomatic Equinox way and wrap the result:
ensemble = Batched(eqx.filter_vmap(lambda k: eqx.nn.MLP(2, 2, 8, 2, key=k))(keys))
Attribute forwarding
Any public attribute of the wrapped module is re-evaluated under the same vmap, so a module only has to implement a method once, unbatched, for it to work through any number of batch layers:
ensemble.some_method(y) # (8, ...) -- called per batch element
ensemble.some_property # (8, ...) -- evaluated per batch element
Arguments are shared across the batch by default; pass arg_axes to override:
ensemble.some_method(ys, arg_axes=(eqx.if_array(0),))
For anything that spans several attributes at once, drop to the primitive:
ensemble.map(lambda m: (m.weight @ m.bias, m.activation_count))
Unlike a raw jax.vmap, map tolerates non-array leaves in the output: they are
partitioned out and returned unbatched.
Nesting and composition
Batched is an eqx.Module, so it nests and is transparent to jit, grad and outer
vmaps:
Batched(Batched(broadcast(broadcast(model, 2), 3)))(x).shape # (3, 2, ...)
eqx.filter_grad(loss)(ensemble, x) # gradients keep the batch axis
API
Batched(inner, *, in_axes, arg_axes, axis_size) |
the batched node |
Batched.map(fn, *args, arg_axes=...) |
run fn(inner, *args) per batch element |
Batched[i], len(Batched) |
unstack one element, batch size |
stack(*modules) |
list[Module] -> Module with a leading axis |
broadcast(module, size) |
one module repeated size times |
in_axes and arg_axes take eqx.filter_vmap specs: an int, None, a callable such as
eqx.if_array(0), or a pytree prefix for per-leaf control.
Caveats
eqx.filter_vmapdoes not accept keyword arguments in the vmapped function.Batchedcloses over any**kwargsyou pass, so they are shared across the batch and cannot be given an axis spec.- Under
jitthe wrapper is free — it compiles to exactly the program a hand-writtenvmapwould produce. In eager mode it costs a fixed overhead per call plus one copy of the output, sincefilter_vmapalways applies amoveaxisthat XLA elides but the op-by-op path does not. __getitem__and__len__address the outermost batch axis only.
License
MIT
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 eqxbatch-0.1.0.tar.gz.
File metadata
- Download URL: eqxbatch-0.1.0.tar.gz
- Upload date:
- Size: 6.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0bfc8d43dc1b62fefb669ac1bdaec6c4426379cccdecc85c0bbaceab3f2e05a8
|
|
| MD5 |
1f235d599c866199f89b991d705a0b15
|
|
| BLAKE2b-256 |
147f76eab59f9f12ef1ae7c9680702ab9303f62fc5807a9f5896c149663f87d8
|
Provenance
The following attestation bundles were made for eqxbatch-0.1.0.tar.gz:
Publisher:
publish.yml on SimLej18/eqxbatch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
eqxbatch-0.1.0.tar.gz -
Subject digest:
0bfc8d43dc1b62fefb669ac1bdaec6c4426379cccdecc85c0bbaceab3f2e05a8 - Sigstore transparency entry: 2272342299
- Sigstore integration time:
-
Permalink:
SimLej18/eqxbatch@ba4e896e7536d1124443b4281298ab14de5e312a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/SimLej18
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ba4e896e7536d1124443b4281298ab14de5e312a -
Trigger Event:
push
-
Statement type:
File details
Details for the file eqxbatch-0.1.0-py3-none-any.whl.
File metadata
- Download URL: eqxbatch-0.1.0-py3-none-any.whl
- Upload date:
- Size: 6.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ff9c07c68ab7d1d39574ddcb8b84fd96db233d2c66cbb44486c83710d01010d5
|
|
| MD5 |
88f1d5ea83db1434129e69057887e372
|
|
| BLAKE2b-256 |
d4475cb41796e6614c2fafaee9062afa4f93b5bcf9c6e49b7d520aacc2ab6276
|
Provenance
The following attestation bundles were made for eqxbatch-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on SimLej18/eqxbatch
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
eqxbatch-0.1.0-py3-none-any.whl -
Subject digest:
ff9c07c68ab7d1d39574ddcb8b84fd96db233d2c66cbb44486c83710d01010d5 - Sigstore transparency entry: 2272342484
- Sigstore integration time:
-
Permalink:
SimLej18/eqxbatch@ba4e896e7536d1124443b4281298ab14de5e312a -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/SimLej18
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ba4e896e7536d1124443b4281298ab14de5e312a -
Trigger Event:
push
-
Statement type: