Registry / ai-ml / equinox

equinox

JSON →
library0.13.8pypypi✓ verified 24d ago

Equinox is a Python library that simplifies building and training neural networks and performing scientific computing within JAX. It provides a PyTorch-like class-based API while maintaining compatibility with JAX's functional programming paradigm and its ecosystem. Equinox isn't a framework; instead, it offers tools for filtered transformations and PyTree manipulation, allowing for fine-grained control over models. It is currently at version 0.13.6 and is actively maintained.

pip install equinox
INSTALL
IMPORT
SIG · EQUINOX
E
equinox
ai-mlpythonv0.13.8
Install
12.5s avg
Import
2944ms
Disk
590MB
Pass rate
5/ 10
Env Coverage5 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v0.13.8 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
build_error
glibc
py 3.103.95 runs
installs and imports cleanly · install 12.5s · import 2.944s · 564MB
590MB installed
● package 590MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

equinox
import equinox as eqx
jax
import jax
jax.nn
import jax.nn as jnn
jax.numpy
import jax.numpy as jnp
jax.random
import jax.random as jrandom
eqx.Module
from equinox import Module
Commonly imported directly or accessed via `eqx.Module`
eqx.nn.Linear
from equinox.nn import Linear
Commonly imported directly or accessed via `eqx.nn.Linear`

This quickstart defines a simple Multi-Layer Perceptron (MLP) using `eqx.Module` and `eqx.nn.Linear`. It demonstrates how to build a neural network with a PyTorch-like class syntax and then use it for inference. The model's parameters are initialized using JAX random keys.

import equinox as eqx import jax import jax.numpy as jnp import jax.random as jrandom class MLP(eqx.Module): layers: list def __init__(self, key): key1, key2, key3 = jrandom.split(key, 3) self.layers = [ eqx.nn.Linear(2, 4, key=key1), jax.nn.relu, eqx.nn.Linear(4, 1, key=key2), ] def __call__(self, x): for layer in self.layers: x = layer(x) return x key = jrandom.PRNGKey(0) model = MLP(key) x_input = jnp.array([1., 2.]) output = model(x_input) print(f"Model output for input {x_input}: {output}")
Debug
Known issues
gotchaEquinox models (subclasses of `eqx.Module`) are JAX PyTrees. While Equinox allows arbitrary Python objects as leaves, standard JAX transformations like `jax.jit` or `jax.grad` usually expect PyTrees of arrays. Using `eqx.filter_jit` and `eqx.filter_grad` is crucial for correctly handling non-array leaves and selectively applying transformations only to relevant parts (e.g., trainable parameters).
fix
Always use `eqx.filter_jit` and `eqx.filter_grad` for transformations on Equinox models, or explicitly `eqx.partition` your model into `(trainable, nontrainable)` parts before applying raw JAX transformations.
affects: All versions
gotchaJAX, and by extension Equinox, emphasizes immutable data structures. Direct in-place modification of model attributes outside of `__init__` or explicit functional updates (e.g., via `eqx.tree_at`) can lead to unexpected behavior, JIT compilation errors, or silently incorrect computations. Model updates should typically involve creating new model instances.
fix
Embrace functional programming paradigms. To update parts of a model, use functional approaches like `eqx.tree_at` to create a new model with updated values rather than modifying attributes directly. For example: `model = eqx.tree_at(lambda m: m.attribute, model, new_value)`.
affects: All versions
gotchaStochastic layers like `eqx.nn.Dropout` often have a `deterministic` argument. This argument can be provided at both initialization time (`__init__`) and call time (`__call__`). The call-time `deterministic` argument takes precedence over the initialization-time argument, which can be a source of confusion if not understood.
fix
Be mindful of the `deterministic` argument's precedence. Explicitly pass `deterministic=True` or `deterministic=False` at call time for clarity, especially during inference or training phases, if you want to override the default behavior set at initialization.
affects: All versions
Errors
Common errors & fixes
TypeError: not a valid JAX type.
This error occurs because standard JAX transformations (like `jax.jit` or `jax.vmap`) only trace and handle JAX arrays, but an `equinox.Module` often contains non-JAX types (such as Python functions or `None`) as leaves within its PyTree structure.
fix
Use Equinox's filtered transformations, such as `equinox.filter_jit` or `equinox.filter_vmap`, instead of their `jax` counterparts. These filtered versions automatically treat non-array leaves as static.
TypeError: __init__() got an unexpected keyword argument 'key'
Many `equinox.nn` modules, like `equinox.nn.Linear` or `equinox.nn.MLP`, require a `jax.random.PRNGKey` for initialization, but this argument was either omitted or passed incorrectly.
fix
Ensure that a `jax.random.PRNGKey` is passed as the `key` argument when instantiating such modules: `linear = eqx.nn.Linear(in_size, out_size, key=jax.random.PRNGKey(0))`.
AttributeError: Cannot set attribute layers
This error typically occurs within an `equinox.Module`'s `__init__` method when attempting to assign to an attribute that is already part of the module's PyTree structure. Equinox modules define their attributes via class annotations and are designed to be immutable after their initial setup.
fix
Define all attributes of an `equinox.Module` using class annotations. For initialization, use `eqx.field` for default values or metadata, or set them directly in `__init__` for values dependent on constructor arguments, without reassigning attributes that are already part of the module's PyTree.
TypeError: unhashable type: 'ArrayImpl' when trying to use Equinox module with jax.lax.scan
This error arises when an `equinox.Module` instance is directly passed as an argument that JAX implicitly treats as 'static' to JAX control-flow primitives like `jax.lax.scan` or `jax.lax.while_loop`. JAX requires static arguments to be hashable, but `jax.ArrayImpl` (the internal type for JAX arrays contained within an Equinox module) is not hashable.
fix
When using `jax.lax.scan` with an `equinox.Module`, wrap the module function in a `lambda` to ensure it is treated correctly, for example: `jax.lax.scan(lambda carry, x: module(carry, x), initial_carry, xs)`. Alternatively, consider using `equinox.filter_scan` if available, which is designed to handle Equinox modules.
Upgrade
Version history
0.13.8latest on PyPI · released May 5, 2026
Audit
Dependencies
jaxrequiredCore dependency for numerical computation and automatic differentiation.
jaxlibrequiredJAX's compiled XLA operations library, required for JAX functionality.
Agent activity
18 hits · last 30 days
node
16
OpenAI (training)
1
Resources