Skip to content

Fix Transformed/Chain for pytree-valued bijectors#92

Open
gvcallen wants to merge 2 commits into
lockwo:mainfrom
gvcallen:transformed_pytree_shapes
Open

Fix Transformed/Chain for pytree-valued bijectors#92
gvcallen wants to merge 2 commits into
lockwo:mainfrom
gvcallen:transformed_pytree_shapes

Conversation

@gvcallen

@gvcallen gvcallen commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

AbstractTransformed._infer_shapes_and_dtype read .shape/.dtype directly off the traced output of bijector.forward, which only works if that output is a single array. For a bijector whose forward pass returns a pytree, jax.eval_shape instead returns a matching pytree of ShapeDtypeStructs, so .shape/.dtype need to be mapped over it leaf-wise.

Chain.forward/inverse/forward_and_log_det/inverse_and_log_det were also typed as Array -> Array, narrower than AbstractBijector's own PyTree -> PyTree, even though Chain just composes whatever bijectors it's given. This PR widens these, along with the Transformed/AbstractTransformed methods that carry values through a bijector (sample, sample_and_log_prob, log_prob, entropy, mean, mode).

`AbstractTransformed._infer_shapes_and_dtype` read `.shape`/`.dtype` directly
off the traced output of `bijector.forward`, which only works if that output
is a single array. For a bijector whose forward pass returns a pytree,
`jax.eval_shape` instead returns a matching pytree of `ShapeDtypeStruct`s, so
`.shape`/`.dtype` need to be mapped over it leaf-wise.

`Chain.forward`/`inverse`/`forward_and_log_det`/`inverse_and_log_det` were
also typed as `Array -> Array`, narrower than `AbstractBijector`'s own
`PyTree -> PyTree`, even though `Chain` just composes whatever bijectors it's
given. Widened these, along with the `Transformed`/`AbstractTransformed`
methods that carry values through a bijector (`sample`, `sample_and_log_prob`,
`log_prob`, `entropy`, `mean`, `mode`).
@gvcallen gvcallen force-pushed the transformed_pytree_shapes branch from 66a4b7d to e03ceb8 Compare July 6, 2026 11:14
Comment thread distreqx/distributions/_transformed.py Outdated
dummy = jnp.zeros(dummy_shape, dtype=self.distribution.dtype)
shape_dtype = jax.eval_shape(self.bijector.forward, dummy)
return shape_dtype.shape, shape_dtype.dtype
shapes = jax.tree_util.tree_map(lambda x: x.shape, shape_dtype)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do jax.tree.map over tree_util

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants