Skip to content

Commit 2e0bcc7

Browse files
Ryan McKennaOptaxDev
authored andcommitted
Fix up microbatching documentation.
PiperOrigin-RevId: 842799825
1 parent 0755580 commit 2e0bcc7

3 files changed

Lines changed: 40 additions & 23 deletions

File tree

docs/api/experimental.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
🧪 Experimental
22
===============
33

4-
Experimental features subject to changes before being graduated of `optax`.
4+
Experimental features subject to changes before being graduated into `optax`.
55

66
.. currentmodule:: optax.experimental
77

88
.. autosummary::
9-
microbatch
9+
microbatching.microbatch
10+
microbatching.micro_vmap
11+
microbatching.micro_grad
12+
microbatching.AccumulationType
13+
microbatching.Accumulator
1014

15+
.. currentmodule:: optax.experimental.microbatching
1116

1217
Microbatching
1318
~~~~~~~~~~~~~
19+
.. autoclass:: AccumulationType
20+
:members:
1421
.. autofunction:: microbatch
22+
.. autofunction:: micro_vmap
23+
.. autofunction:: micro_grad
24+
.. autofunction:: reshape_batch_axis

optax/experimental/microbatching.py

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
AccumulatorTree: TypeAlias = Any
3030
Function: TypeAlias = Callable[..., Any]
3131
VmapFn: TypeAlias = Callable[[Function, int | Sequence[int], int], Function]
32+
PyTreeFn: TypeAlias = Callable[[chex.ArrayTree], chex.ArrayTree]
33+
UpdateFn = Callable[[chex.ArrayTree, chex.ArrayTree, int], chex.ArrayTree]
3234
IndividualOutputs = collections.namedtuple('Aux', ['values', 'metrics', 'aux'])
3335
ValueAndGradFn: TypeAlias = Callable[..., tuple[Any, IndividualOutputs]]
3436

@@ -40,28 +42,28 @@ class Accumulator:
4042
Given a list of microbatch function evaluations [x_0, ..., x_{n-1}], this
4143
object represents the program.
4244
43-
```
45+
.. code-block:: python
46+
4447
carry = init(x_0)
4548
for i in range(1, n):
4649
carry = update(carry, x_i, i)
4750
return finalize(carry)
48-
```
4951
5052
Attributes:
51-
init: A function f(value, num_microbatches) that initializes the microbatch
52-
state from the function evaluation of the fist microbatch.
53-
update: A function f(carry, value, index, num_microbatches) that updates the
54-
microbatch state with the function evaluation of the current microbatch.
55-
finalize: A function f(carry, num_microbatches) that returns the final
56-
result from the final state.
53+
init: A function f(value) that initializes the microbatch state from the
54+
function evaluation of the fist microbatch.
55+
update: A function f(carry, value, index) that updates the microbatch state
56+
with the function evaluation of the current microbatch.
57+
finalize: A function f(carry) that returns the final result from the final
58+
state.
5759
aggregate: A function f(per_microbatch_value) that aggregates
58-
per-microbatch values into a single value. Used by `gvmap`.
60+
per-microbatch values into a single value. Used by `micro_vmap`.
5961
"""
6062

61-
init: Callable[[chex.ArrayTree], chex.ArrayTree]
62-
update: Callable[[chex.ArrayTree, chex.ArrayTree, int], chex.ArrayTree]
63-
finalize: Callable[[chex.ArrayTree], chex.ArrayTree]
64-
aggregate: Callable[[chex.ArrayTree], chex.ArrayTree]
63+
init: PyTreeFn
64+
update: UpdateFn
65+
finalize: PyTreeFn
66+
aggregate: PyTreeFn
6567

6668

6769
def _with_floating_check(fn: Function) -> Function:
@@ -79,7 +81,7 @@ def _identity(value: Any) -> Any:
7981
return value
8082

8183

82-
def reshape_batch_axis(tree: Any, microbatch_size: int, axis: int = 0):
84+
def reshape_batch_axis(tree: Any, microbatch_size: int, axis: int = 0) -> Any:
8385
"""Reshape batch axis of pytree leaves for use with microbatching.
8486
8587
This function reshapes the batch axis of each leaf into a shape
@@ -252,9 +254,13 @@ def finalize(carry):
252254
class AccumulationType(enum.Enum):
253255
"""The type of accumulation to perform."""
254256
MEAN = enum.auto()
257+
"""Average the microbatch outputs."""
255258
SUM = enum.auto()
259+
"""Sum the microbatch outputs."""
256260
RUNNING_MEAN = enum.auto()
261+
"""Average the microbatch outputs over `num_real_microbatches`."""
257262
CONCAT = enum.auto()
263+
"""Concatenate the microbatch outputs along axis 0."""
258264

259265

260266
# In order to construct some accumulators (MEAN, CONCAT), we need to know the
@@ -444,7 +450,7 @@ def body_fun(index, carry):
444450

445451

446452
# TODO(mckennar): Create a notebook demonstrating useful use-cases.
447-
def gvmap(
453+
def micro_vmap(
448454
fun: Function,
449455
in_axes: int | Sequence[int] = 0,
450456
out_axes: Any = 0,
@@ -467,8 +473,8 @@ def gvmap(
467473
Example Usage:
468474
>>> from optax.experimental import microbatching
469475
>>> import jax.numpy as jnp
470-
>>> microbatching.gvmap(lambda x: x**2)(jnp.arange(8))
471-
>>> Array([ 0, 1, 4, 9, 16, 25, 36, 49], dtype=int32)
476+
>>> microbatching.micro_vmap(lambda x: x**2)(jnp.arange(8))
477+
Array([ 0, 1, 4, 9, 16, 25, 36, 49], dtype=int32)
472478
473479
Args:
474480
fun: Function to be mapped over additional axes.
@@ -573,18 +579,19 @@ def micro_grad(
573579
native jax.value_and_grad due to the built-in microbatching.
574580
575581
Example Usage (see https://arxiv.org/abs/2510.00236):
582+
>>> from optax.experimental import microbatching
576583
>>> def mean_squared_loss(params, features, targets):
577584
... preds = features @ params
578585
... diff = preds - targets
579586
... return 0.5 * jnp.mean(diff**2)
580587
>>> params = jnp.zeros(1)
581588
>>> features = jnp.ones((4, 1))
582589
>>> targets = jnp.array([0, 2, 4, 6])
583-
>>> (grads, squared_grads), aux = micro_grad(
590+
>>> (grads, squared_grads), aux = microbatching.micro_grad(
584591
... mean_squared_loss,
585592
... argnums=0,
586593
... batch_argnums=(1,2),
587-
... accumulator=AccumulationType.MEAN,
594+
... accumulator=microbatching.AccumulationType.MEAN,
588595
... transform_fn=lambda x: (x, x**2),
589596
... metrics_fn=jnp.linalg.norm
590597
... )(params, features, targets)
@@ -637,7 +644,7 @@ def grad_fn(*args, **kwargs):
637644
in_axes = [None]*(max(batch_argnums) + 1)
638645
for i in batch_argnums:
639646
in_axes[i] = 0
640-
micro_fun = gvmap(
647+
micro_fun = micro_vmap(
641648
grad_fn,
642649
in_axes=in_axes,
643650
accumulator=(accumulator, AccumulationType.CONCAT),

optax/experimental/microbatching_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ def fun(a, b, c, *, d, e, f):
252252

253253
def test_vmap(self):
254254
x = jnp.arange(2*4*8).reshape(2, 4, 8)
255-
custom_vmap = microbatching.gvmap(
255+
custom_vmap = microbatching.micro_vmap(
256256
jnp.sum,
257257
in_axes=1,
258258
microbatch_size=2,

0 commit comments

Comments
 (0)