This release adds two forward-mode second-order optimizers — SOFO and SOFOScan — to braintools.optim, and hardens the braintools.cogtask task engine so that conditional combinators, categorical labels, and metadata batching behave correctly under brainstate.transform.jit and brainstate.transform.vmap2. The package now ships inline type information (PEP 561), test coverage is raised to ~92% (and several latent trainer/visualize bugs uncovered along the way are fixed), and documentation links and assets are migrated to the new brainx.chaobrain.com host.
Highlights
- New optimizers
SOFOandSOFOScan: Second-Order Forward-mode Optimization for feedforward and recurrent models. Both build a Generalised Gauss-Newton matrix in a random tangent subspace from forward-mode JVPs and apply the resulting direction through the standard optax update path, so learning-rate schedules, momentum, weight decay, and gradient clipping continue to work unchanged. - Hardened
cogtaskdispatch:Switchnow works in both eager and traced execution,Whilefails loudly on unsupported traced conditions, and a newnum_classesparameter decouples categorical-head sizing fromnum_outputs. - PEP 561 typing:
braintoolsships apy.typedmarker and inline annotations on its public API, so downstream static type checkers consume its types directly.
Added
braintools.optim — forward-mode second-order optimizers
SOFO: Second-Order Forward-mode Optimization for a modelmodel(inputs) -> predictionspaired withloss_fn(predictions, targets). It samples random tangent vectors, takes forward-mode JVPs through the model and loss, builds a damped Generalised Gauss-Newton system in the random subspace, solves it, and projects the solution back to parameter space. Supports'mse'and'ce'loss forms, a configurabletangent_sizeanddamping,momentum/nesterov, decoupledweight_decay, and norm/value gradient clipping.SOFOScan: a recurrent variant for a stateful one-step cellrnn_cell(latent, inputs) -> (new_latent, output). The cell is scanned over the input sequence withbrainstate.transform.scan, and forward-mode JVPs propagate the tangents throughlax.scan, accumulating the Gauss-Newton matrix over every(timestep, batch)sample before a single solve. Both optimizers are exported frombraintools.optimand documented in the API reference.
braintools.cogtask
Taskcategorical sizing: a newnum_classesargument, decoupled fromnum_outputs, sizes categorical output heads independently of the raw output dimension.Taskfeature ergonomics:Tasknow accepts a loneFeaturein place of aFeatureSet, and requires features to be supplied wheneverphasesare given.Tasktime step:Taskandmake_taskaccept an optionaldtargument. When set, it is pinned around trial generation viabrainstate.environ.context, so phase durations and buffer sizes are computed against thatdtand the reporteddtstays consistent regardless of the ambient environment. When omitted, the ambientbrainstate.environ.get_dt()is used (unchanged behaviour).
Typing
- PEP 561 support: a
braintools/py.typedmarker is shipped via package data, and the top-level public API — spike bitwise ops, spike encoders (with implicit-Optionaldefaults fixed), tree utilities, and_mischelpers — now carries resolvable inline annotations.
Changed
cogtaskconditional dispatch:Switchuses dual-mode packed dispatch — a concretekey in caseslookup in eager mode and alax.switchover ordered branches underjit/vmap— and coerces 0-d concrete array keys (e.g.ctx.rng.choice(...)selectors) so eagersample_trialno longer raisesunhashable type: 'ArrayImpl'.Whileraises a clearNotImplementedErrorfor data-dependent (traced) conditions underjit/vmapinstead of surfacing a crypticTracerBoolConversionError.
- Documentation links: chaobrain-ecosystem documentation URLs (
brainstate,brainunit,braincell,brainmass,brainevent,braintrace,braintools, and related packages) were rewritten from*.readthedocs.ioto the newbrainx.chaobrain.comhost, stripping/latest,/en/latest, and/en/stablepath prefixes and?badge=latestquery strings. Third-party ReadTheDocs links are left intact. - README logo: the project logo is now served from
brainx.chaobrain.comas WebP instead of a raw GitHub asset.
Fixed
braintools.cogtask:- Categorical labels that are statically out of range for the declared
num_classesare now validated and rejected up front. - Packed-mode phases expose
phase_start/phase_endbeforeon_enterruns, matching the contract already provided in fixed-length mode. - String leaves are dropped from batched metadata so
return_metaworks correctly underbrainstate.transform.vmap2. - Minor fixes to the input encoder and the working-memory task library.
- Added regression tests covering all of the above.
- Categorical labels that are statically out of range for the declared
braintools.trainer:LightningModule.deviceno longer raisesTypeError: 'set' object is not subscriptableon array-backed parameters;Array.devices()returns a set, which is now handled correctly (#92).ModelCheckpointsaves throughbraintools.file.msgpack_saveinstead of themsgpack_from_state_dictrestore helper, so checkpoints are actually written (#95).
braintools.visualize:animate_2Dreshapes the(num_step, num_neuron)values to the(height, width)grid before drawing the first frame, fixing apcolorcrash on the initial step (#93).correlation_matrix(method='kendall')builds the correlation matrix pairwise over feature columns instead of passing a 2-D array tokendalltau(#94).remove_axisusesax.spinesinstead of the non-existentax.spine, which previously raisedAttributeError(#96).create_neural_colormap/brain_colormapsregister withforce=True, making them idempotent rather than raising on re-use (#97).roc_curve/precision_recall_curveresolvenp.trapezoidwhen available (falling back tonp.trapz), fixing anAttributeErroron NumPy >= 2.4 wherenp.trapzwas removed (#99).
Infrastructure
- Publish workflow: reads the package version directly from
braintools/_version.py(the single source of truth) and verifies that the release tag matches before publishing. - Docs deployment: the
push: maintrigger was removed; documentation is now deployed only on a GitHub release (released) or via a manualworkflow_dispatch. - Type-check workflow: a new Type Check workflow runs
mypyover the annotated public surface, backed by a[tool.mypy]configuration and atype-checkoptional-dependency group. - Test coverage: new test suites cover the previously-untested trainer, visualize, file, and surrogate modules, raising overall coverage to ~92%. CI runs
pytestwith--covand uploads results to Codecov, and the README carries a coverage badge.tqdmandrichwere added to thetestingextra so the progress-bar callback tests run in CI.
Full changelog: v0.1.9...v0.1.10