sweep#
- class braintools.fit.sweep(fn, grid, *, mode='product', batch_size=None)#
Evaluate a pure function over a grid of parameter values.
- Parameters:
fn (
Callable[[Dict[str,Any]],Any]) –fn(params) -> PyTree, a pure (vmap-able) function of a dict of scalar parameters.grid (
Dict[str,Any]) –{name: values}with 1-D arrays (orbrainunitQuantities) of candidate values.mode (
str) –'product'evaluates the cartesian product of the value arrays (grid shape(len(v1), len(v2), ...)in the order ofgrid);'zip'pairs equal-length arrays element-wise (grid shape(n,)).batch_size (
int|None) – Number of grid points evaluated together by onevmap-ped call. The chunks run one after another throughjax.lax.map(), so the peak memory is bounded bybatch_sizeevaluations; a final partial chunk is handled whenbatch_sizedoes not divide the grid size.Noneevaluates the whole grid in a singlevmap.
- Return type:
- Returns:
outputs (PyTree) – The outputs of
fnstacked over the grid: every leaf has shapegrid_shape + leaf_shape.table (dict) – The flattened parameter table
{name: values}; every entry has lengthprod(grid_shape)and rowiis the input of outputoutputs.reshape(-1, ...)[i].
- Raises:
ValueError – If
gridis empty, a value array is not 1-D or is empty,modeis unknown, the arrays have different lengths in'zip'mode, orbatch_sizeis not a positive integer.
See also
FitterOptimise the parameters instead of scanning them.
Notes
The grid shape is static, so
sweepcan be called insidejax.jit; it is differentiable with respect to valuesfncloses over.Examples
>>> import jax.numpy as jnp >>> from braintools.fit import sweep >>> out, table = sweep(lambda p: p['a'] * p['b'], ... {'a': jnp.array([1., 2.]), 'b': jnp.array([10., 20., 30.])}) >>> out Array([[10., 20., 30.], [20., 40., 60.]], dtype=float32) >>> table['b'] Array([10., 20., 30., 10., 20., 30.], dtype=float32) >>> >>> out, _ = sweep(lambda p: p['a'] + p['b'], ... {'a': jnp.arange(5.), 'b': jnp.ones(5)}, mode='zip', batch_size=2) >>> out Array([1., 2., 3., 4., 5.], dtype=float32)