From ee7a8a309e47073241fd6d94b9f472402c59f57c Mon Sep 17 00:00:00 2001 From: Alex Ororbia Date: Fri, 1 May 2026 12:09:39 -0400 Subject: [PATCH 1/7] Final nudge to v3.1.0 (#149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * implemented raw classical instantaneous stdp * mod to classical stdp * mod to classical stdp syn * mod to stdp syn * mod to stdp syn * mod to stdp syn * mod to stdp syn * mod to stdp syn * minor mod of syn * cleaned up stdp syn * cleaned up stdp syn * Sync up of main with release (#131) * Minor nudge to v3.0.1 (#129) * minor edit to math in hh-lesson doc * Fix workflow, numpy install, and pytest bug in github action workflows (#117) * Update pyproject.toml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * minor nudge/cleanup to minor patched version 2.0.1 * minor nudge/cleanup to minor patched version 2.0.3 * Merged back minor doc fix back to main (for syncing purposes) (#119) * Nudge of release to minor patched version 2.0.3 (#118) * nudge of doc to 2.0.2 (#115) Co-authored-by: Alexander Ororbia * minor edit to math in hh-lesson doc * Fix workflow, numpy install, and pytest bug in github action workflows (#117) * Update pyproject.toml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * Update python-package-conda.yml * minor nudge/cleanup to minor patched version 2.0.1 * minor nudge/cleanup to minor patched version 2.0.3 --------- Co-authored-by: Alexander Ororbia Co-authored-by: Viet Dung Nguyen <60036798+rxng8@users.noreply.github.com> * fixed typo/error in doc evolving_synapses.md --------- Co-authored-by: Alexander Ororbia Co-authored-by: Viet Dung Nguyen <60036798+rxng8@users.noreply.github.com> * minor clean-up in model_basics docs * minor fixes/cleanup of docs * fixed typo in integration tutorial doc * updated papers/talk page for ngclearn * Merging over v3 to main (for roll-out of v3 upgrade) (#125) * Working v3 * Undid fixed compartemts Undid the fixed compartments to work with new global constant tracking * Fixed an execution bug * ported over quad-lif to v3 - needs testing * ported over IF/quadLIF cells, minor revision to LIF cell * Start util cleanup * refactored/ported RAFCell to v3 * ported over/refactored WTASCell for v3 * wrote successful unit-test of WTASCell * put back in init-structure/pointers * fixed minor error in LIFCell, got unit-test for LIFCell to run * quad-lif test sketched * sketch of ifcell test * fixed minor bugs and tests locally pass for if, quad-lif, and lif-cells now, with minor patches to help fun and doc-strings * refactored raf-cell and test passed * refactored adex/test passed; minor cleanup in lif, raf, and wtas cells * refactored fn-cell and test passed * cleaned up lif, raf, wtas, fn, and quad-lif cells repr method * refactored and tests passed for izh and h-h cells * JaxProcess update * cleaned up dunder repr method, moved to JaxComponent parent; fixed __init__ pointer to tensorstats * refactored alpha and exp-synapses, tests passed; minor edit to __init__ for synapses * refactored short-term syn, tests passed - including stp-dense-syn and minor cleanup/edit to synapse __init__ * refactored bcm-syn and test passed * refactored exp-stdp-syn and passed tests for exp-stdp-syn and trace-stdp-syn * refactored event-stdp-syn and test passed * refactored mstdpet-syn and test passed * refactored stdp-conv-syn/conv-syn and test passed * refactored and passed test for deconv/stdp-deconv-syn and other minor cleanup for conv/deconv support * Refactoring neuronal and synaptic components (#123) - merge from fork to v3 * refactoring graded cells * update refactored models * update sLIF cell --------- Co-authored-by: Alex Ororbia * commented out deprecator in hebb-syn and exp-kernel * update hebbian synapse * update hebbian synapse * working reinforce synapse * minor edits to exp-kernel/wtas-cell * update requirements * refactored conv/deconv-hebb-syn and tests passed * update hebbian synapse reset bug * update reset methods * update patched synapse reset * add `not self.inputs.targeted and ` to required components. Fixing general `__repr__` bug in `jaxcomponent` * minor edit to lif/modulated-syn init file * fixed some minor bugs in rate-coded cells/hebb-syn * update code * minor patches to components, including hebb-syn/conv/deconv and reward-cell * minor patches to components, including hebb-syn/conv/deconv and reward-cell * update testing for graded neurons and input encoders * update phasor cell * update test bernoulli cell and poisson cell * update components and their related test cases * fixed monitor bugs from v2, tweaked unit-tests for input-encoders/latency-cell * update test case for test_sLIFCell.py * some cleanup * made revisions to components/clean-up; added back in deprecators * removed lava sub-module, and removed monitor/base-monitor legacy components * minor cleanup of inits * refactored regression module to be compliant with v3 * adjusted sphinx-docs w.r.t. new v3 refactoring * minor revision to double-exp syn pointing, mods to modeling docs * updated adex tutorial doc to v3 * revised adex and error-cell neurocog tutorials * fixed minor issues in input-encoders, further revisions to docs for v3 * revised dyn/chem-syn neurocog doc, cleaned up dynamic syn * revised fn and hh-cell neurocog docs, added some refs to distribution generator * revised integration and izh-cell neurocog docs * revised izh-cell, cleaned-up fn-cell, and revised lif neurocog docs * revised metrics/plotting neurocog docs * revised mod/reward-stdp neurocog doc * revised stp-syn neurocog doc and updated stp-syn to use proper initializer * revised elements of utils to comply with docs * revised stdp neurocog doc to v3 * revised traces neurocog tutorial to v3 * cleaned up utils.optim and wrote compliant NAG optim * cleaned up utils.optim and wrote compliant NAG optim * cleanup of components, added leaky-noise-cell, minor edits * revised leaky-noise-cell, wrote its unit test, test-passed * some revisions/updates to toc/pointer/general tutorial docs * minor revisions to pyproject/req files * update reinforce synapse * update test cases * implemented in-house gmm, in-built to ngclearn; tested on gaussian mode data * wrote gmm density estimator tutorial * patched some tests/syn/neuron components, added sketch of bmm density * fixed test_laplacianErrorCell and laplace-cell bug * fixed test_laplacianErrorCell and laplace-cell bug * made patches to bmm * updated density tutorial/neurocog doc * minor edit to gmm/bmm docs * minor edit to gmm/bmm docs * cleaned up density structure, use parent mixture class to organize model variations * cleaned up density structure, use parent mixture class to organize model variations * added basic exp-mixture to utils.density * minor edits to emm * cleaned up mixtures and finished debugging EMM/works on example * removed old weight_distribution.py, other cleanup/revisions throughout * minor edit to data-loader * revised tests to no longer use weight_distribution/revisions throughout * minor edit to emm doc * added bic calculation to metric_utils * fix ratecell ug of passing unrelated kwargs to parent class * added calc_update() co-routine to hebbian-syn component * fix weight init * integrated rbm/harmonium model-exhibit * Update __init__.py Added the config/logging back to the init * placed pointer to rao-ballard1999 exhibit; updates to docs * updates to docs/revisions * removed flag from bernoulli/latency-cells for now; minor edit to doc * updates to theory doc * updated history log * minor clean-up of ngclearn.utils.viz.dim_reduce * Update jaxComponent.py Added support for turning off autosave * update hebbian synapse saving * update saving and loading utils, making hebbian synapse use these utils for custom optimizer params saving and loading * minor revisions/polish * modded docs to include v3 foundations * updates to init for logging * Updates to lessons * final cleanup/polish/update to docs for v3 nudge * updates to museum doc for v3 * nudged citation file * minor nudge to docs/files to point to v3 --------- Co-authored-by: Will Gebhardt Co-authored-by: Alexander Ororbia Co-authored-by: Viet Dung Nguyen <60036798+rxng8@users.noreply.github.com> Co-authored-by: Viet Nguyen Co-authored-by: Viet Dung Nguyen * update to rbm/harmonium doc * updated leaky-noise-cell to maintain temporal derivative of state * minor revisons/updates to hebb/dense syn, metric utils * cleaned-up/revised leaky-noise-cell * cleaned-up/revised leaky-noise-cell --------- Co-authored-by: Alexander Ororbia Co-authored-by: Viet Dung Nguyen <60036798+rxng8@users.noreply.github.com> Co-authored-by: Will Gebhardt Co-authored-by: Viet Nguyen Co-authored-by: Viet Dung Nguyen * nudge release to v3.0.1 * minor revision of leaky-noise-cell --------- Co-authored-by: Alexander Ororbia Co-authored-by: Viet Dung Nguyen <60036798+rxng8@users.noreply.github.com> Co-authored-by: Will Gebhardt Co-authored-by: Viet Nguyen Co-authored-by: Viet Dung Nguyen * added pointer/stub for ei-rnn song-et-al in museum doc * update to ei-rnn doc * update to ei-rnn arch fig * added log-gaussian initializer to distribution_generator * bug-fix to log-gaussian func * Refactor patch utility functions and add doc strings (#136) * Rao1999 hpc (#135) * Enhance documentation for predictive coding model Expanded the documentation for the predictive coding model, detailing the construction of neural and synaptic components, process dynamics, and training procedures. * Add files via upload * Update image path for GEC in documentation * Revise PC model documentation formatting Updated headings and formatting for clarity in PC model documentation. * Change header levels for PC model training sections * Add files via upload * Update PC model training section with input image details Added explanation about the input image for the PC model training. * Update pc_rao_ballard1999.md * Delete docs/images/museum/hgpc/Patch_input.png * Add files via upload * Fix image source and enhance PC model description Updated image source and adjusted description for clarity. * Refactor PC model training sections in documentation Removed the section for training the PC model on the full image and added a reference to it in the patched image section. * fixed minor errors in pc-rao doc * made revisions to pc-rao doc * mod to pc-rao doc * update to docs * minor revision to h-h doc-string * added lkwta utility * Add retinal ganglion cell input encoder (#137) * Add RetinalGanglionCell component with filtering methods Implement RetinalGanglionCell with Gaussian filtering and patch extraction. * Add RetinalGanglionCell import to input_encoders * Add RetinalGanglionCell to input encoders * Enhance filter functions in ganglionCell.py Refactor Gaussian filter creation and add Difference of Gaussian filter functionality. * Refactor patch synapse (#138) * Refactor multi-patch synapse creation and initialization Refactor _create_multi_patch_synapses function to use n_modules instead of n_sub_models and update weight initialization. Introduce weight masks for synaptic weights. * Refactor HebbianPatchedSynapse and add attributes Refactor HebbianPatchedSynapse initialization and add new attributes for post-in and pre-out. * feat: Integrate MPSSynapse Component (#140) * feat: integrate MPSSynapse component for compressed synaptic transforms * style: conform to Google docstrings, move utils, and add unit tests * feat: implement native learning via evolve method and unit tests * Fixed MPS Matrix Properties: I fixed the .T transpose bug you interrupted earlier—because self.W10.weights inside an MPSSynapse generates the tensor via an einsum, returning an Array, get() throws an error. * Fix MPS synapse memory leak by implementing project_backward * Delete uv.lock * docs: add academic references and detailed docstrings to MPSSynapse * sorry, here you go, I loosened the test tolerances to 1e-2 as suggested --------- Co-authored-by: Alex Ororbia * integrated working som-synapse into competitive sub-package for synapses * cleaned up som-syn * update test code for hebbian patch synapse * fix SOM Synapse bug * Flexible batch size (#142) * Modify reset method to accept batch_size parameter for flexible test set size * Modify reset method to accept batch_size parameter * Refactor RateCell class reset function for flexible batch size * Refactor GaussianErrorCell class functions for flexible batch size * flexible batch_size * cleaned up graded/patched comps with inner batched_reset formulation * minor clean-up of som-syn * claned up ganglion-cell, added batched_reset * minor cleanup * added working hopfield-syn/modern-hopfield-syn * update SOM synapse to batchified version * integrated prototype for vector-quantize memory model/synapse * wrote/integrated an ART2A synapse model, batch-generalized * updates to art2a, cleanup of probes * updates to art2a, cleanup of probes * added in knn-probe for utils.analysis * cleaned up vq-synapse * cleaned up vq-synapse * tweaked/cleaned-up gaussian-error-cell * Update JaxProcessesMixin.py Added automatic jit wrapping which is on by default, add "use_jit=False" to a process to disable * minor patch fixes, including making .mask a compartment in key syn * patch to bernoulli/latency and wtas cells * update reset function of the ganglion cell Co-authored-by: Copilot * minor mod to model_utils * docs now with a few more mods * Nudge to release of v3.1.0 (#146) * create release branch * Dev (#62) * implemented raw classical instantaneous stdp * mod to classical stdp * mod to classical stdp syn * mod to stdp syn * mod to stdp syn * mod to stdp syn * mod to stdp syn * mod to stdp syn * minor mod of syn * cleaned up stdp syn * cleaned up stdp syn --------- Co-authored-by: ago109 * added block diag init to weight dist * added block diag init to weight dist * added block diag init to weight dist; with will optimization * slight extension to rate-cell for tensor-shaping * slight extension to rate-cell for tensor-shaping * slight extension to rate-cell for tensor-shaping * slightly modded bernoulli-cell help to reflect correct compartment names * nudge to readme for minor version shift to beta2 * nudge to readme for minor version shift to beta2 * mod to docs to prep for nudge to beta2 * nudge correctly to pip version beta3 * generalized rate-cell a bit * touched up rate-cell further * minor mod to lif * updated lif-cell to use units/tags and minor cleanup and edits * Monitor plot (#66) * Update base_monitor.py * added plotting viewed compartments * added meta-data to rate-cell, input encoders, adex * fixed minor saving/loading in rate-cell w/ vectorized compartments * Added auto resolving for monitors (#67) * fixed surr arg in lif-cell * modded bernoulli-cell to include max-frequency constraint * added warning check to bernoulli, some cleanup * integrated if-cell, cleaned up lif and inits * mod to latency-cell * updated the poissonCell to be a true poisson * fixed minor bug in deprecation for poiss/bern * fixed minor bug in deprecation for poiss/bern * fixed validation fun in bern/poiss * moved back and cleaned up bernoulli and poisson cells * added threshold-clipping to latency cell * updates to if/lif * added batch-size arg to slif * fixed minor load bug in lif-cell * fixed a blocking jit-partial call in lif update_theta method; when loading * minor edit to dim-reduce * Patched synapses added (#68) * Patched synapses added * Update __init__.py * Update patch_utils.py patch_with_stride & patch_with_overlap functions + Create_Patches class added * Update patchedSynapse.py * Update hebbianPatchedSynapse.py * Update synapse_plot.py order added * updated monitor plot code * update to dim-reduce * integrated phasor-cell, minor cleanup of latency * tweak to adex thr arg * tweak to adex thr arg * integrated resonate-and-fire neuronal cell * mod to raf-cell * cleaned up raf * cleaned up raf * cleaned up raf-cell * cleaned up raf-cell * cleaned up raf-cell * minor tweak to dim-reduce in utils * Fix typo in pcn_discrim.md (#69) * model_utils and rate cell (#70) * Patched synapses added * Update __init__.py * Update patch_utils.py patch_with_stride & patch_with_overlap functions + Create_Patches class added * Update patchedSynapse.py * Update hebbianPatchedSynapse.py * Update synapse_plot.py order added * Create hierarchical_sc.md 1 * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update sparse_coding.md * Update sparse_coding.md * Update sparse_coding.md * Update sparse_coding.md * Update hierarchical_sc.md * Update sparse_coding.md * Update sparse_coding.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Add files via upload * Delete docs/images/hgpc_network.pdf * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Create hgpc * Delete docs/images/museum/hgpc * Create d * Add files via upload * Delete docs/images/hgpc_model.png * Delete docs/images/museum/hgpc/d * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Delete docs/images/museum/hgpc/Input_layer.png * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Create Generative_PC.md * Update and rename Generative_PC.md to generative_pc.md * Update generative_pc.md * Update generative_pc.md * Update model_utils.py * Update model_utils.py * Update model_utils.py * Update model_utils.py * Update rateCell.py * Update generative_pc.md * Create pc-sindy.md * Update pc-sindy.md * Update model_utils.py sine activation function added * Update model_utils.py * Update ode_utils.py jitified * Delete docs/museum/hierarchical_sc.md * Delete docs/museum/generative_pc.md * Delete ngclearn/components/synapses/patched directory * Update __init__.py * Add files via upload ode with scanner added * Update ode_solver.py _ removed * Fix/reorganize feature library (#74) * Update ode_utils.py * Update ode_solver.py rk4 revised and __main__ added * Delete ngclearn/utils/diffeq/ode_functions.py * Create odes.py odes name and structure changed * Update __init__.py * Create feature_library.py * Create __init__.py * Create base.py * Delete docs/museum/pc-sindy.md * Create m.md * Add files via upload * Delete docs/images/museum/sindy/m.md * Add files via upload * Create sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * fix: correct feature library path and directory name * Delete ngclearn/utils/dymbolic_dictionary directory * Update model_utils.py (#78) * Additions for inhibition stuff * add sindy documentation for exhibits (#81) * Add files via upload * Add files via upload * Update ode_utils.py (#79) refactor: delete @partial(jit, static_argnums=(2, )) lines Co-authored-by: Will Gebhardt * Add patched synapse (#80) * Update __init__.py Add point to patched components * Add patched in __init__.py Add patched synapses importing * Add patched synaptic components * Delete ngclearn/components/synapses/patched/__pycache__ directory * Update __init__.py new line characters added * Update hebbianPatchedSynapse.py * Update patchedSynapse.py new line characters added * Update staticPatchedSynapse.py new line characters added * Update staticPatchedSynapse.py New line characters + comments for describing each input vars * Update patchedSynapse.py Removed a comment line * Update hebbianPatchedSynapse.py remove unused arguments * Update hebbianPatchedSynapse.py * Update hebbianPatchedSynapse.py add description for w_mask * Update hebbianPatchedSynapse.py * Update hebbianPatchedSynapse.py * Update patchedSynapse.py * Update patchedSynapse.py * Update hebbianPatchedSynapse.py * Update __init__.py (#83) * Update __init__.py typo fixed * Update staticPatchedSynapse.py a typo fixed * Update hebbianPatchedSynapse.py typo foxed * Add l1 decay term to update calculation (#84) * Update hebbianSynapse.py * update main update main at the end * Update hebbianSynapse.py add regularization argument and w_decay is deprecated. * Update hebbianSynapse.py add elastic_net * Update hebbianSynapse.py * Update hebbianSynapse.py * feat NGC module regression (#86) * feat npc module regression * Update __init__.py * Update __init__.py * Update elastic_net.py * Update lasso.py * Update ridge.py * Update elastic_net.py * Update ridge.py * Update lasso.py * Update odes.py removed @partial(jit, static_argnums=(0,)) * Update odes.py (#87) removed @partial(jit, static_argnums=(0,)) * Update odes.py typo fixed in __main__ * Update __init__.py add dot * Update __init__.py add dot * Add attribute 'lr' (#90) * Update elastic_net.py * add lr as attribute to lasso.py * add lr as attribute to ridge.py * refactor w_bound=0. for weights elastic_net.py deactivated w_bound for weights elastic_net.py * Update lasso.py * deactivated w_bound for weights ridge.py * commit probes/mods to utils to analysis_tools branch * commit probes/mods to utils to analysis_tools branch * update documentation * cleaned up probes/docs for probes * change heads_dim to attn_dim, and modify the mlp to be as similar as possible to the attentive probing pattern * in layer normalization or any other Gaussian, standardeviation can never be zero. Additionally, if the subtraction inside the square root goes to zero, the gradient will become NaN. Therefore, adding a clipping is necessary. * update attentive probe code * minor tweak to attentive prob code comments * cleaned up probe parent fit routine * cleaned up probe parent fit routine * cleaned up probe parent fit routine * cleaned up probe parent fit routine * minor edits to attn probe * update attentive probe with input layer norm * update input layer normalization * update code to fix nan bug * minor tweak to attn probe * cleaned up probes * cleaned up probes * cleaned up probes * cleaned up probes * generalized dropout in terms of shape * tweak to atten probe * tweak to atten probe * added silu/swish/elu to model_utils * cleaned up model_utils * fix bug in attention probe dropout, fix bug in None noise_key passed in the probing jit function, add the spliting of noise_keys to two dropout in two cross attention * hyperparameter tunning arguments added * Merging over Dynamics feature branch to main (#92) * modded bernoulli-cell to include max-frequency constraint * added warning check to bernoulli, some cleanup * integrated if-cell, cleaned up lif and inits * mod to latency-cell * updated the poissonCell to be a true poisson * fixed minor bug in deprecation for poiss/bern * fixed minor bug in deprecation for poiss/bern * fixed validation fun in bern/poiss * moved back and cleaned up bernoulli and poisson cells * added threshold-clipping to latency cell * updates to if/lif * added batch-size arg to slif * fixed minor load bug in lif-cell * fixed a blocking jit-partial call in lif update_theta method; when loading * minor edit to dim-reduce * updated monitor plot code * update to dim-reduce * integrated phasor-cell, minor cleanup of latency * tweak to adex thr arg * tweak to adex thr arg * integrated resonate-and-fire neuronal cell * mod to raf-cell * cleaned up raf * cleaned up raf * cleaned up raf-cell * cleaned up raf-cell * cleaned up raf-cell * minor tweak to dim-reduce in utils * Additions for inhibition stuff * update to API modeling docs to reflect RAF neuronal cell --------- Co-authored-by: Alexander Ororbia Co-authored-by: Will Gebhardt * remove unused local variables * update note * update model utils * remove notes * Update ode utils (#94) * Update ode_utils.py merge ode_solver into ide_utils * Delete ngclearn/utils/diffeq/ode_solver.py * Update ode_utils.py refactor doc-string * minor fix to header in diffeq * Update files with ode_solver (#95) * Update ode_utils.py merge ode_solver into ide_utils * Delete ngclearn/utils/diffeq/ode_solver.py * Update ode_utils.py refactor doc-string * Update odes.py * Update sindy.md ode_solver to ode_utils * revised/cleaned up sindy tutorial doc/imgs * add prior for hebbian patched synapse (#96) * prior replaced w_decay hebbianPatchedSynapse.py remove w_decay add prior_type and prior_lmbda * revised typo hebbianSynapse.py dWweight was typo * cleaned up doc-strings in odes.py to comply w/ ngc-learn format * minor tweak to sig-figs printing in probe utils * add-sigma-to-gaussianErrorCell (#97) * add-sigma-to-gaussianErrorCell add not updating scalar variance for gaussian errors * Update gaussianErrorCell.py * cleaned up ode_utils, cleaned up gaussian/laplacian cell * Update gaussianErrorCell.py (#98) added `and not isinstance(sigma, int)` * cleaned up gauss/laplace error cells * integrated bernoulli err-cell * Major release update merge to main (in prep for 2.0.0 release on release branch/pip) (#99) * add initial patch mask features * minor edit to bern-cell * fixed bernoulli error cell * example rate cell test * made some corrections to bern err-cell and heb syn * made some corrections to bern err-cell and heb syn * cleaned up bern-cell, hebb-syn * minor mod to model-utils * attempted rewrite of bernoulli-cell * got bernoulli-cell rewritten and unit-tested * edit to bern-cell * bernoulli and poisson cells revised, unit-tested * latency-cell refactored and unit-tested * refactored Rate Cell * minor revisions to input-encoders, revised phasor-cell w/ unit-test * revised and add unit-test for varTrace * revised and added unit-test for exp-kernel * revised and added unit-test for exp-kernel * revised slif cell w/ unit-test; needed mod to diffeq * revised slif-cell w/ unit-test; cleaned up ode_utils to play nicer w/ new sim-lib * revised lif-cell w/ unit-test * revised unit-tests to pass globally; some minor patches to phasor-cell and lif * minor cleanup of unit-test for phasor * revised if-cell w/ unit-test * revised if-cell w/ unit-test * revised quad-lif w/ unit-test * revised adex-cell w/ unit test, minor cleanup of quad-lif * minor edit to adex unit-test * refactor bernoulli, laplacian, and rewarderror cells * revised raf-cell w/ unit test; fixed typos/mistakes in all spiking cells * revised wtas-cell w/ unit test * revised fh-cell w/ unit test * revised izh-cell w/ unit test * patched ode_utils backend wrt jax, cleaned up unit-tests, added disable flag for phasor-cell * update rate cell * fix test rate cell * update test for bernoulli cell * update refactoring for gaussian error cell * update unit testing for all graded neurons * wrote+unit-test of hodgkin-huxley spike cell, minor tweaks/clean-up elsewhere * added rk2 support for H-H cell * update rate cell and fix bug of passing a tuple of (jax Array -- not hashable) to jax jit functions. Basically, simplify the codebase by using a hashmap of functions * update test rate cell * refactored dense and trace-stdp syn w/ unit-test * refactored exp-stdp syn w/ unit-test * refactored event-stdp w/ unit-test * cleanup of stdp-syn * refactored bcm syn w/ unit-test * refactored stp-syn with unit-test * cleaned up modulated * refactored mstdp-et syn w/ unit-test * refactored lava components to new sim-lib * refactored conv/hebb-conv syn w/ unit-test * refactored/revised hebb-deconv syn w/ unit-test * revised/refactored hebb/stdp conv/deconv syn w/ unit-tests * updated modeling doc to point to hodgkin-huxley cell * updated modeling docs * fixed typo in adex-cell tutorial doc * revised tutorials to reflect new sim-lib config/syntax * revised tutorials to reflect new sim-lib config/syntax * patched docs to reflect revisions/refactor * tweaked requirements in prep for major release * cleaned up a few unit tests to use deterministic syn init vals * mod to requirements * nudge toml to upcoming 2.0.0 * update to support docs in prep for 2.0.0 * update patched synapses and their test cases * cleaned up syn modeling doc * push hebbian synapse * push reinforce synapse * push np seed * patched minor prior None arg issue in hebb-syn * moved reinforce-syn to right spot * update reinforce synapse and testing * tweaked trace-stdp and mstdpet * patched mstdpet unit-test * update reinforce synapse and test cases * add reinforce synapse fix * minor mod to mstdpet * update test code for more than 1 steps * Updated monitors * patched tests to use process naming * Added wrapper for reset and advance_state * Added a JaxProcess Added Jax Process to allow for scanning over the process. * update the old rate cell * update old hebbian synapse * minor edit to if-cell * ported over adex tutorial to new ngclearn format * hh-cell supports rk4 integration * clean up and integrated hodgkin-huxley mini lesson in neurocog tutorials * Update jaxProcess.py Updated the jax process to allow for more configurations of inputs. * update working reinforce synapse * update correct reinforce and testing * update documentation * update features, documentation, and testing * update testing for REINFORCE cell * update code and test * update code * add clipping gradient to model utils * update reinforce cell to the new model utils clip * update test cases --------- Co-authored-by: Viet Dung Nguyen Co-authored-by: Alexander Ororbia Co-authored-by: Will Gebhardt * Major release update (to 2.0.0) (#100) * add initial patch mask features * minor edit to bern-cell * fixed bernoulli error cell * example rate cell test * made some corrections to bern err-cell and heb syn * made some corrections to bern err-cell and heb syn * cleaned up bern-cell, hebb-syn * minor mod to model-utils * attempted rewrite of bernoulli-cell * got bernoulli-cell rewritten and unit-tested * edit to bern-cell * bernoulli and poisson cells revised, unit-tested * latency-cell refactored and unit-tested * refactored Rate Cell * minor revisions to input-encoders, revised phasor-cell w/ unit-test * revised and add unit-test for varTrace * revised and added unit-test for exp-kernel * revised and added unit-test for exp-kernel * revised slif cell w/ unit-test; needed mod to diffeq * revised slif-cell w/ unit-test; cleaned up ode_utils to play nicer w/ new sim-lib * revised lif-cell w/ unit-test * revised unit-tests to pass globally; some minor patches to phasor-cell and lif * minor cleanup of unit-test for phasor * revised if-cell w/ unit-test * revised if-cell w/ unit-test * revised quad-lif w/ unit-test * revised adex-cell w/ unit test, minor cleanup of quad-lif * minor edit to adex unit-test * refactor bernoulli, laplacian, and rewarderror cells * revised raf-cell w/ unit test; fixed typos/mistakes in all spiking cells * revised wtas-cell w/ unit test * revised fh-cell w/ unit test * revised izh-cell w/ unit test * patched ode_utils backend wrt jax, cleaned up unit-tests, added disable flag for phasor-cell * update rate cell * fix test rate cell * update test for bernoulli cell * update refactoring for gaussian error cell * update unit testing for all graded neurons * wrote+unit-test of hodgkin-huxley spike cell, minor tweaks/clean-up elsewhere * added rk2 support for H-H cell * update rate cell and fix bug of passing a tuple of (jax Array -- not hashable) to jax jit functions. Basically, simplify the codebase by using a hashmap of functions * update test rate cell * refactored dense and trace-stdp syn w/ unit-test * refactored exp-stdp syn w/ unit-test * refactored event-stdp w/ unit-test * cleanup of stdp-syn * refactored bcm syn w/ unit-test * refactored stp-syn with unit-test * cleaned up modulated * refactored mstdp-et syn w/ unit-test * refactored lava components to new sim-lib * refactored conv/hebb-conv syn w/ unit-test * refactored/revised hebb-deconv syn w/ unit-test * revised/refactored hebb/stdp conv/deconv syn w/ unit-tests * updated modeling doc to point to hodgkin-huxley cell * updated modeling docs * fixed typo in adex-cell tutorial doc * revised tutorials to reflect new sim-lib config/syntax * revised tutorials to reflect new sim-lib config/syntax * patched docs to reflect revisions/refactor * tweaked requirements in prep for major release * cleaned up a few unit tests to use deterministic syn init vals * mod to requirements * nudge toml to upcoming 2.0.0 * update to support docs in prep for 2.0.0 * update patched synapses and their test cases * cleaned up syn modeling doc * push hebbian synapse * push reinforce synapse * push np seed * patched minor prior None arg issue in hebb-syn * moved reinforce-syn to right spot * update reinforce synapse and testing * tweaked trace-stdp and mstdpet * patched mstdpet unit-test * update reinforce synapse and test cases * add reinforce synapse fix * minor mod to mstdpet * update test code for more than 1 steps * Updated monitors * patched tests to use process naming * Added wrapper for reset and advance_state * Added a JaxProcess Added Jax Process to allow for scanning over the process. * update the old rate cell * update old hebbian synapse * minor edit to if-cell * ported over adex tutorial to new ngclearn format * hh-cell supports rk4 integration * clean up and integrated hodgkin-huxley mini lesson in neurocog tutorials * Update jaxProcess.py Updated the jax process to allow for more configurations of inputs. * update working reinforce synapse * update correct reinforce and testing * update documentation * update features, documentation, and testing * update testing for REINFORCE cell * update code and test * update code * add clipping gradient to model utils * update reinforce cell to the new model utils clip * major cleanup in prep for merge over to main/prep for major release * update test cases * update to require file in docs --------- Co-authored-by: Viet Dung Nguyen Co-authored-by: Alexander Ororbia Co-authored-by: Will Gebhardt * Major release update merge to main (sync up) (#101) * add initial patch mask features * minor edit to bern-cell * fixed bernoulli error cell * example rate cell test * made some corrections to bern err-cell and heb syn * made some corrections to bern err-cell and heb syn * cleaned up bern-cell, hebb-syn * minor mod to model-utils * attempted rewrite of bernoulli-cell * got bernoulli-cell rewritten and unit-tested * edit to bern-cell * bernoulli and poisson cells revised, unit-tested * latency-cell refactored and unit-tested * refactored Rate Cell * minor revisions to input-encoders, revised phasor-cell w/ unit-test * revised and add unit-test for varTrace * revised and added unit-test for exp-kernel * revised and added unit-test for exp-kernel * revised slif cell w/ unit-test; needed mod to diffeq * revised slif-cell w/ unit-test; cleaned up ode_utils to play nicer w/ new sim-lib * revised lif-cell w/ unit-test * revised unit-tests to pass globally; some minor patches to phasor-cell and lif * minor cleanup of unit-test for phasor * revised if-cell w/ unit-test * revised if-cell w/ unit-test * revised quad-lif w/ unit-test * revised adex-cell w/ unit test, minor cleanup of quad-lif * minor edit to adex unit-test * refactor bernoulli, laplacian, and rewarderror cells * revised raf-cell w/ unit test; fixed typos/mistakes in all spiking cells * revised wtas-cell w/ unit test * revised fh-cell w/ unit test * revised izh-cell w/ unit test * patched ode_utils backend wrt jax, cleaned up unit-tests, added disable flag for phasor-cell * update rate cell * fix test rate cell * update test for bernoulli cell * update refactoring for gaussian error cell * update unit testing for all graded neurons * wrote+unit-test of hodgkin-huxley spike cell, minor tweaks/clean-up elsewhere * added rk2 support for H-H cell * update rate cell and fix bug of passing a tuple of (jax Array -- not hashable) to jax jit functions. Basically, simplify the codebase by using a hashmap of functions * update test rate cell * refactored dense and trace-stdp syn w/ unit-test * refactored exp-stdp syn w/ unit-test * refactored event-stdp w/ unit-test * cleanup of stdp-syn * refactored bcm syn w/ unit-test * refactored stp-syn with unit-test * cleaned up modulated * refactored mstdp-et syn w/ unit-test * refactored lava components to new sim-lib * refactored conv/hebb-conv syn w/ unit-test * refactored/revised hebb-deconv syn w/ unit-test * revised/refactored hebb/stdp conv/deconv syn w/ unit-tests * updated modeling doc to point to hodgkin-huxley cell * updated modeling docs * fixed typo in adex-cell tutorial doc * revised tutorials to reflect new sim-lib config/syntax * revised tutorials to reflect new sim-lib config/syntax * patched docs to reflect revisions/refactor * tweaked requirements in prep for major release * cleaned up a few unit tests to use deterministic syn init vals * mod to requirements * nudge toml to upcoming 2.0.0 * update to support docs in prep for 2.0.0 * update patched synapses and their test cases * cleaned up syn modeling doc * push hebbian synapse * push reinforce synapse * push np seed * patched minor prior None arg issue in hebb-syn * moved reinforce-syn to right spot * update reinforce synapse and testing * tweaked trace-stdp and mstdpet * patched mstdpet unit-test * update reinforce synapse and test cases * add reinforce synapse fix * minor mod to mstdpet * update test code for more than 1 steps * Updated monitors * patched tests to use process naming * Added wrapper for reset and advance_state * Added a JaxProcess Added Jax Process to allow for scanning over the process. * update the old rate cell * update old hebbian synapse * minor edit to if-cell * ported over adex tutorial to new ngclearn format * hh-cell supports rk4 integration * clean up and integrated hodgkin-huxley mini lesson in neurocog tutorials * Update jaxProcess.py Updated the jax process to allow for more configurations of inputs. * update working reinforce synapse * update correct reinforce and testing * update documentation * update features, documentation, and testing * update testing for REINFORCE cell * update code and test * update code * add clipping gradient to model utils * update reinforce cell to the new model utils clip * major cleanup in prep for merge over to main/prep for major release * update test cases * update to require file in docs --------- Co-authored-by: Viet Dung Nguyen Co-authored-by: Alexander Ororbia Co-authored-by: Will Gebhardt * update test cases * Nudging main v2.0.0 to release stage (formal release) (#102) * generalized rate-cell a bit * touched up rate-cell further * minor mod to lif * updated lif-cell to use units/tags and minor cleanup and edits * Monitor plot (#66) * Update base_monitor.py * added plotting viewed compartments * added meta-data to rate-cell, input encoders, adex * fixed minor saving/loading in rate-cell w/ vectorized compartments * Added auto resolving for monitors (#67) * fixed surr arg in lif-cell * modded bernoulli-cell to include max-frequency constraint * added warning check to bernoulli, some cleanup * integrated if-cell, cleaned up lif and inits * mod to latency-cell * updated the poissonCell to be a true poisson * fixed minor bug in deprecation for poiss/bern * fixed minor bug in deprecation for poiss/bern * fixed validation fun in bern/poiss * moved back and cleaned up bernoulli and poisson cells * added threshold-clipping to latency cell * updates to if/lif * added batch-size arg to slif * fixed minor load bug in lif-cell * fixed a blocking jit-partial call in lif update_theta method; when loading * minor edit to dim-reduce * Patched synapses added (#68) * Patched synapses added * Update __init__.py * Update patch_utils.py patch_with_stride & patch_with_overlap functions + Create_Patches class added * Update patchedSynapse.py * Update hebbianPatchedSynapse.py * Update synapse_plot.py order added * updated monitor plot code * update to dim-reduce * integrated phasor-cell, minor cleanup of latency * tweak to adex thr arg * tweak to adex thr arg * integrated resonate-and-fire neuronal cell * mod to raf-cell * cleaned up raf * cleaned up raf * cleaned up raf-cell * cleaned up raf-cell * cleaned up raf-cell * minor tweak to dim-reduce in utils * Fix typo in pcn_discrim.md (#69) * model_utils and rate cell (#70) * Patched synapses added * Update __init__.py * Update patch_utils.py patch_with_stride & patch_with_overlap functions + Create_Patches class added * Update patchedSynapse.py * Update hebbianPatchedSynapse.py * Update synapse_plot.py order added * Create hierarchical_sc.md 1 * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update sparse_coding.md * Update sparse_coding.md * Update sparse_coding.md * Update sparse_coding.md * Update hierarchical_sc.md * Update sparse_coding.md * Update sparse_coding.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Add files via upload * Delete docs/images/hgpc_network.pdf * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Create hgpc * Delete docs/images/museum/hgpc * Create d * Add files via upload * Delete docs/images/hgpc_model.png * Delete docs/images/museum/hgpc/d * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Delete docs/images/museum/hgpc/Input_layer.png * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Create Generative_PC.md * Update and rename Generative_PC.md to generative_pc.md * Update generative_pc.md * Update generative_pc.md * Update model_utils.py * Update model_utils.py * Update model_utils.py * Update model_utils.py * Update rateCell.py * Update generative_pc.md * Create pc-sindy.md * Update pc-sindy.md * Update model_utils.py sine activation function added * Update model_utils.py * Update ode_utils.py jitified * Delete docs/museum/hierarchical_sc.md * Delete docs/museum/generative_pc.md * Delete ngclearn/components/synapses/patched directory * Update __init__.py * Add files via upload ode with scanner added * Update ode_solver.py _ removed * Fix/reorganize feature library (#74) * Update ode_utils.py * Update ode_solver.py rk4 revised and __main__ added * Delete ngclearn/utils/diffeq/ode_functions.py * Create odes.py odes name and structure changed * Update __init__.py * Create feature_library.py * Create __init__.py * Create base.py * Delete docs/museum/pc-sindy.md * Create m.md * Add files via upload * Delete docs/images/museum/sindy/m.md * Add files via upload * Create sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * Update sindy.md * fix: correct feature library path and directory name * Delete ngclearn/utils/dymbolic_dictionary directory * Update model_utils.py (#78) * Additions for inhibition stuff * add sindy documentation for exhibits (#81) * Add files via upload * Add files via upload * Update ode_utils.py (#79) refactor: delete @partial(jit, static_argnums=(2, )) lines Co-authored-by: Will Gebhardt * Add patched synapse (#80) * Update __init__.py Add point to patched components * Add patched in __init__.py Add patched synapses importing * Add patched synaptic components * Delete ngclearn/components/synapses/patched/__pycache__ directory * Update __init__.py new line characters added * Update hebbianPatchedSynapse.py * Update patchedSynapse.py new line characters added * Update staticPatchedSynapse.py new line characters added * Update staticPatchedSynapse.py New line characters + comments for describing each input vars * Update patchedSynapse.py Removed a comment line * Update hebbianPatchedSynapse.py remove unused arguments * Update hebbianPatchedSynapse.py * Update hebbianPatchedSynapse.py add description for w_mask * Update hebbianPatchedSynapse.py * Update hebbianPatchedSynapse.py * Update patchedSynapse.py * Update patchedSynapse.py * Update hebbianPatchedSynapse.py * Update __init__.py (#83) * Update __init__.py typo fixed * Update staticPatchedSynapse.py a typo fixed * Update hebbianPatchedSynapse.py typo foxed * Add l1 decay term to update calculation (#84) * Update hebbianSynapse.py * update main update main at the end * Update hebbianSynapse.py add regularization argument and w_decay is deprecated. * Update hebbianSynapse.py add elastic_net * Update hebbianSynapse.py * Update hebbianSynapse.py * feat NGC module regression (#86) * feat npc module regression * Update __init__.py * Update __init__.py * Update elastic_net.py * Update lasso.py * Update ridge.py * Update elastic_net.py * Update ridge.py * Update lasso.py * Update odes.py removed @partial(jit, static_argnums=(0,)) * Update odes.py (#87) removed @partial(jit, static_argnums=(0,)) * Update odes.py typo fixed in __main__ * Update __init__.py add dot * Update __init__.py add dot * Add attribute 'lr' (#90) * Update elastic_net.py * add lr as attribute to lasso.py * add lr as attribute to ridge.py * refactor w_bound=0. for weights elastic_net.py deactivated w_bound for weights elastic_net.py * Update lasso.py * deactivated w_bound for weights ridge.py * commit probes/mods to utils to analysis_tools branch * commit probes/mods to utils to analysis_tools branch * update documentation * cleaned up probes/docs for probes * change heads_dim to attn_dim, and modify the mlp to be as similar as possible to the attentive probing pattern * in layer normalization or any other Gaussian, standardeviation can never be zero. Additionally, if the subtraction inside the square root goes to zero, the gradient will become NaN. Therefore, adding a clipping is necessary. * update attentive probe code * minor tweak to attentive prob code comments * cleaned up probe parent fit routine * cleaned up probe parent fit routine * cleaned up probe parent fit routine * cleaned up probe parent fit routine * minor edits to attn probe * update attentive probe with input layer norm * update input layer normalization * update code to fix nan bug * minor tweak to attn probe * cleaned up probes * cleaned up probes * cleaned up probes * cleaned up probes * generalized dropout in terms of shape * tweak to atten probe * tweak to atten probe * added silu/swish/elu to model_utils * cleaned up model_utils * fix bug in attention probe dropout, fix bug in None noise_key passed in the probing jit function, add the spliting of noise_keys to two dropout in two cross attention * hyperparameter tunning arguments added * Merging over Dynamics feature branch to main (#92) * modded bernoulli-cell to include max-frequency constraint * added warning check to bernoulli, some cleanup * integrated if-cell, cleaned up lif and inits * mod to latency-cell * updated the poissonCell to be a true poisson * fixed minor bug in deprecation for poiss/bern * fixed minor bug in deprecation for poiss/bern * fixed validation fun in bern/poiss * moved back and cleaned up bernoulli and poisson cells * added threshold-clipping to latency cell * updates to if/lif * added batch-size arg to slif * fixed minor load bug in lif-cell * fixed a blocking jit-partial call in lif update_theta method; when loading * minor edit to dim-reduce * updated monitor plot code * update to dim-reduce * integrated phasor-cell, minor cleanup of latency * tweak to adex thr arg * tweak to adex thr arg * integrated resonate-and-fire neuronal cell * mod to raf-cell * cleaned up raf * cleaned up raf * cleaned up raf-cell * cleaned up raf-cell * cleaned up raf-cell * minor tweak to dim-reduce in utils * Additions for inhibition stuff * update to API modeling docs to reflect RAF neuronal cell --------- Co-authored-by: Alexander Ororbia Co-authored-by: Will Gebhardt * remove unused local variables * update note * update model utils * remove notes * Update ode utils (#94) * Update ode_utils.py merge ode_solver into ide_utils * Delete ngclearn/utils/diffeq/ode_solver.py * Update ode_utils.py refactor doc-string * minor fix to header in diffeq * Update files with ode_solver (#95) * Update ode_utils.py merge ode_solver into ide_utils * Delete ngclearn/utils/diffeq/ode_solver.py * Update ode_utils.py refactor doc-string * Update odes.py * Update sindy.md ode_solver to ode_utils * revised/cleaned up sindy tutorial doc/imgs * add prior for hebbian patched synapse (#96) * prior replaced w_decay hebbianPatchedSynapse.py remove w_decay add prior_type and prior_lmbda * revised typo hebbianSynapse.py dWweight was typo * cleaned up doc-strings in odes.py to comply w/ ngc-learn format * minor tweak to sig-figs printing in probe utils * add-sigma-to-gaussianErrorCell (#97) * add-sigma-to-gaussianErrorCell add not updating scalar variance for gaussian errors * Update gaussianErrorCell.py * cleaned up ode_utils, cleaned up gaussian/laplacian cell * Update gaussianErrorCell.py (#98) added `and not isinstance(sigma, int)` * cleaned up gauss/laplace error cells * integrated bernoulli err-cell * Major release update merge to main (in prep for 2.0.0 release on release branch/pip) (#99) * add initial patch mask features * minor edit to bern-cell * fixed bernoulli error cell * example rate cell test * made some corrections to bern err-cell and heb syn * made some corrections to bern err-cell and heb syn * cleaned up bern-cell, hebb-syn * minor mod to model-utils * attempted rewrite of bernoulli-cell * got bernoulli-cell rewritten and unit-tested * edit to bern-cell * bernoulli and poisson cells revised, unit-tested * latency-cell refactored and unit-tested * refactored Rate Cell * minor revisions to input-encoders, revised phasor-cell w/ unit-test * revised and add unit-test for varTrace * revised and added unit-test for exp-kernel * revised and added unit-test for exp-kernel * revised slif cell w/ unit-test; needed mod to diffeq * revised slif-cell w/ unit-test; cleaned up ode_utils to play nicer w/ new sim-lib * revised lif-cell w/ unit-test * revised unit-tests to pass globally; some minor patches to phasor-cell and lif * minor cleanup of unit-test for phasor * revised if-cell w/ unit-test * revised if-cell w/ unit-test * revised quad-lif w/ unit-test * revised adex-cell w/ unit test, minor cleanup of quad-lif * minor edit to adex unit-test * refactor bernoulli, laplacian, and rewarderror cells * revised raf-cell w/ unit test; fixed typos/mistakes in all spiking cells * revised wtas-cell w/ unit test * revised fh-cell w/ unit test * revised izh-cell w/ unit test * patched ode_utils backend wrt jax, cleaned up unit-tests, added disable flag for phasor-cell * update rate cell * fix test rate cell * update test for bernoulli cell * update refactoring for gaussian error cell * update unit testing for all graded neurons * wrote+unit-test of hodgkin-huxley spike cell, minor tweaks/clean-up elsewhere * added rk2 support for H-H cell * update rate cell and fix bug of passing a tuple of (jax Array -- not hashable) to jax jit functions. Basically, simplify the codebase by using a hashmap of functions * update test rate cell * refactored dense and trace-stdp syn w/ unit-test * refactored exp-stdp syn w/ unit-test * refactored event-stdp w/ unit-test * cleanup of stdp-syn * refactored bcm syn w/ unit-test * refactored stp-syn with unit-test * cleaned up modulated * refactored mstdp-et syn w/ unit-test * refactored lava components to new sim-lib * refactored conv/hebb-conv syn w/ unit-test * refactored/revised hebb-deconv syn w/ unit-test * revised/refactored hebb/stdp conv/deconv syn w/ unit-tests * updated modeling doc to point to hodgkin-huxley cell * updated modeling docs * fixed typo in adex-cell tutorial doc * revised tutorials to reflect new sim-lib config/syntax * revised tutorials to reflect new sim-lib config/syntax * patched docs to reflect revisions/refactor * tweaked requirements in prep for major release * cleaned up a few unit tests to use deterministic syn init vals * mod to requirements * nudge toml to upcoming 2.0.0 * update to support docs in prep for 2.0.0 * update patched synapses and their test cases * cleaned up syn modeling doc * push hebbian synapse * push reinforce synapse * push np seed * patched minor prior None arg issue in hebb-syn * moved reinforce-syn to right spot * update reinforce synapse and testing * tweaked trace-stdp and mstdpet * patched mstdpet unit-test * update reinforce synapse and test cases * add reinforce synapse fix * minor mod to mstdpet * update test code for more than 1 steps * Updated monitors * patched tests to use process naming * Added wrapper for reset and advance_state * Added a JaxProcess Added Jax Process to allow for scanning over the process. * update the old rate cell * update old hebbian synapse * minor edit to if-cell * ported over adex tutorial to new ngclearn format * hh-cell supports rk4 integration * clean up and integrated hodgkin-huxley mini lesson in neurocog tutorials * Update jaxProcess.py Updated the jax process to allow for more configurations of inputs. * update working reinforce synapse * update correct reinforce and testing * update documentation * update features, documentation, and testing * update testing for REINFORCE cell * update code and test * update code * add clipping gradient to model utils * update reinforce cell to the new model utils clip * update test cases --------- Co-authored-by: Viet Dung Nguyen Co-authored-by: Alexander Ororbia Co-authored-by: Will Gebhardt * Major release update (to 2.0.0) (#100) * add initial patch mask features * minor edit to bern-cell * fixed bernoulli error cell * example rate cell test * made some corrections to bern err-cell and heb syn * made some corrections to bern err-cell and heb syn * cleaned up bern-cell, hebb-syn * minor mod to model-utils * attempted rewrite of bernoulli-cell * got bernoulli-cell rewritten and unit-tested * edit to bern-cell * bernoulli and poisson cells revised, unit-tested * latency-cell refactored and unit-tested * refactored Rate Cell * minor revisions to input-encoders, revised phasor-cell w/ unit-test * revised and add unit-test for varTrace * revised and added unit-test for exp-kernel * revised and added unit-test for exp-kernel * revised slif cell w/ unit-test; needed mod to diffeq * revised slif-cell w/ unit-test; cleaned up ode_utils to play nicer w/ new sim-lib * revised lif-cell w/ unit-test * revised unit-tests to pass globally; some minor patches to phasor-cell and lif * minor cleanup of unit-test for phasor * revised if-cell w/ unit-test * revised if-cell w/ unit-test * revised quad-lif w/ unit-test * revised adex-cell w/ unit test, minor cleanup of quad-lif * minor edit to adex unit-test * refactor bernoulli, laplacian, and rewarderror cells * revised raf-cell w/ unit test; fixed typos/mistakes in all spiking cells * revised wtas-cell w/ unit test * revised fh-cell w/ unit test * revised izh-cell w/ unit test * patched ode_utils backend wrt jax, cleaned up unit-tests, added disable flag for phasor-cell * update rate cell * fix test rate cell * update test for bernoulli cell * update refactoring for gaussian error cell * update unit testing for all graded neurons * wrote+unit-test of hodgkin-huxley spike cell, minor tweaks/clean-up elsewhere * added rk2 support for H-H cell * update rate cell and fix bug of passing a tuple of (jax Array -- not hashable) to jax jit functions. Basically, simplify the codebase by using a hashmap of functions * update test rate cell * refactored dense and trace-stdp syn w/ unit-test * refactored exp-stdp syn w/ unit-test * refactored event-stdp w/ unit-test * cleanup of stdp-syn * refactored bcm syn w/ unit-test * refactored stp-syn with unit-test * cleaned up modulated * refactored mstdp-et syn w/ unit-test * refactored lava components to new sim-lib * refactored conv/hebb-conv syn w/ unit-test * refactored/revised hebb-deconv syn w/ unit-test * revised/refactored hebb/stdp conv/deconv syn w/ unit-tests * updated modeling doc to point to hodgkin-huxley cell * updated modeling docs * fixed typo in adex-cell tutorial doc * revised tutorials to reflect new sim-lib config/syntax * revised tutorials to reflect new sim-lib config/syntax * patched docs to reflect revisions/refactor * tweaked requirements in prep for major release * cleaned up a few unit tests to use deterministic syn init vals * mod to requirements * nudge toml to upcoming 2.0.0 * update to support docs in prep for 2.0.0 * update patched synapses and their test cases * cleaned up syn modeling doc * push hebbian synapse * push reinforce synapse * push np seed * patched minor prior None arg issue in hebb-syn * moved reinforce-syn to right spot * update reinforce synapse and testing * tweaked trace-stdp and mstdpet * patched mstdpet unit-test * update reinforce synapse and test cases * add reinforce synapse fix * minor mod to mstdpet * update test code for more than 1 steps * Updated monitors * patched tests to use process naming * Added wrapper for reset and advance_state * Added a JaxProcess Added Jax Process to allow for scanning over the process. * update the old rate cell * update old hebbian synapse * minor edit to if-cell * ported over adex tutorial to new ngclearn format * hh-cell supports rk4 integration * clean up and integrated hodgkin-huxley mini lesson in neurocog tutorials * Update jaxProcess.py Updated the jax process to allow for more configurations of inputs. * update working reinforce synapse * update correct reinforce and testing * update documentation * update features, documentation, and testing * update testing for REINFORCE cell * update code and test * update code * add clipping gradient to model utils * update reinforce cell to the new model utils clip * major cleanup in prep for merge over to main/prep for major release * update test cases * update to require file in docs --------- Co-authored-by: Viet Dung Nguyen Co-authored-by: Alexander Ororbia Co-authored-by: Will Gebhardt * Major release update merge to main (sync up) (#101) * add initial patch mask features * minor edit to bern-cell * fixed bernoulli error cell * example rate cell test * made some corrections to bern err-cell and heb syn * made some corrections to bern err-cell and heb syn * cleaned up bern-cell, hebb-syn * minor mod to model-utils * attempted rewrite of bernoulli-cell * got bernoulli-cell rewritten and unit-tested * edit to bern-cell * bernoulli and poisson cells revised, unit-tested * latency-cell refactored and unit-tested * refactored Rate Cell * minor revisions to input-encoders, revised phasor-cell w/ unit-test * revised and add unit-test for varTrace * revised and added unit-test for exp-kernel * revised and added unit-test for exp-kernel * revised slif cell w/ unit-test; needed mod to diffeq * revised slif-cell w/ unit-test; cleaned up ode_utils to play nicer w/ new sim-lib * revised lif-cell w/ unit-test * revised unit-tests to pass globally; some minor patches to phasor-cell and lif * minor cleanup of unit-test for phasor * revised if-cell w/ unit-test * revised if-cell w/ unit-test * revised quad-lif w/ unit-test * revised adex-cell w/ unit test, minor cleanup of quad-lif * minor edit to adex unit-test * refactor bernoulli, laplacian, and rewarderror cells * revised raf-cell w/ unit test; fixed typos/mistakes in all spiking cells * revised wtas-cell w/ unit test * revised fh-cell w/ unit test * revised izh-cell w/ unit test * patched ode_utils backend wrt jax, cleaned up unit-tests, added disable flag for phasor-cell * update rate cell * fix test rate cell * update test for bernoulli cell * update refactoring for gaussian error cell * update unit testing for all graded neurons * wrote+unit-test of hodgkin-huxley spike cell, minor tweaks/clean-up elsewhere * added rk2 support for H-H cell * update rate cell and fix bug of passing a tuple of (jax Array -- not hashable) to jax jit functions. Basically, simplify the codebase by using a hashmap of functions * update test rate cell * refactored dense and trace-stdp syn w/ unit-test * refactored exp-stdp syn w/ unit-test * refactored event-stdp w/ unit-test * cleanup of stdp-syn * refactored bcm syn w/ unit-test * refactored stp-syn with unit-test * cleaned up modulated * refactored mstdp-et syn w/ unit-test * refactored lava components to new sim-lib * refactored conv/hebb-conv syn w/ unit-test * refactored/revised hebb-deconv syn w/ unit-test * revised/refactored hebb/stdp conv/deconv syn w/ unit-tests * updated modeling doc to point to hodgkin-huxley cell * updated modeling docs * fixed typo in adex-cell tutorial doc * revised tutorials to reflect new sim-lib config/syntax * revised tutorials to reflect new sim-lib config/syntax * patched docs to reflect revisions/refactor * tweaked requirements in prep for major release * cleaned up a few unit tests to use deterministic syn init vals * mod to requirements * nudge toml to upcoming 2.0.0 * update to support docs in prep for 2.0.0 * update patched synapses and their test cases * cleaned up syn modeling doc * push hebbian synapse * push reinforce synapse * push np seed * patched minor prior None arg issue in hebb-syn * moved reinforce-syn to right spot * update reinforce synapse and testing * tweaked trace-stdp and mstdpet * patched mstdpet unit-test * update reinforce synapse and test cases * add reinforce synapse fix * minor mod to mstdpet * update test code for more than 1 steps * Updated monitors * patched tests to use process naming * Added wrapper for reset and advance_state * Added a JaxProcess Added Jax Process to allow for scanning over the process. * update the old rate cell * update old hebbian synapse * minor edit to if-cell * ported over adex tutorial to new ngclearn format * hh-cell supports rk4 integration * clean up and integrated hodgkin-huxley mini lesson in neurocog tutorials * Update jaxProcess.py Updated the jax process to allow for more configurations of inputs. * update working reinforce synapse * update correct reinforce and testing * update documentation * update features, documentation, and testing * update testing for REINFORCE cell * update code and test * update code * add clipping gradient to model utils * update reinforce cell to the new model utils clip * major cleanup in prep for merge over to main/prep for major release * update test cases * update to require file in docs --------- Co-authored-by: Viet Dung Nguyen Co-authored-by: Alexander Ororbia Co-authored-by: Will Gebhardt * update test cases --------- Co-authored-by: Will Gebhardt Co-authored-by: Alexander Ororbia Co-authored-by: Faezeh Habibi <155960330+Faezehabibi@users.noreply.github.com> Co-authored-by: Sonny George <56851635+sonnygeorge@users.noreply.github.com> Co-authored-by: Viet Dung Nguyen <60036798+rxng8@users.noreply.github.com> Co-authored-by: Alexander Ororbia Co-authored-by: Viet Dung Nguyen Co-authored-by: Viet Nguyen Co-authored-by: Alexander Ororbia * added hh-plot for hh tutorial * Further nudge from main to release (#103) * generalized rate-cell a bit * touched up rate-cell further * minor mod to lif * updated lif-cell to use units/tags and minor cleanup and edits * Monitor plot (#66) * Update base_monitor.py * added plotting viewed compartments * added meta-data to rate-cell, input encoders, adex * fixed minor saving/loading in rate-cell w/ vectorized compartments * Added auto resolving for monitors (#67) * fixed surr arg in lif-cell * modded bernoulli-cell to include max-frequency constraint * added warning check to bernoulli, some cleanup * integrated if-cell, cleaned up lif and inits * mod to latency-cell * updated the poissonCell to be a true poisson * fixed minor bug in deprecation for poiss/bern * fixed minor bug in deprecation for poiss/bern * fixed validation fun in bern/poiss * moved back and cleaned up bernoulli and poisson cells * added threshold-clipping to latency cell * updates to if/lif * added batch-size arg to slif * fixed minor load bug in lif-cell * fixed a blocking jit-partial call in lif update_theta method; when loading * minor edit to dim-reduce * Patched synapses added (#68) * Patched synapses added * Update __init__.py * Update patch_utils.py patch_with_stride & patch_with_overlap functions + Create_Patches class added * Update patchedSynapse.py * Update hebbianPatchedSynapse.py * Update synapse_plot.py order added * updated monitor plot code * update to dim-reduce * integrated phasor-cell, minor cleanup of latency * tweak to adex thr arg * tweak to adex thr arg * integrated resonate-and-fire neuronal cell * mod to raf-cell * cleaned up raf * cleaned up raf * cleaned up raf-cell * cleaned up raf-cell * cleaned up raf-cell * minor tweak to dim-reduce in utils * Fix typo in pcn_discrim.md (#69) * model_utils and rate cell (#70) * Patched synapses added * Update __init__.py * Update patch_utils.py patch_with_stride & patch_with_overlap functions + Create_Patches class added * Update patchedSynapse.py * Update hebbianPatchedSynapse.py * Update synapse_plot.py order added * Create hierarchical_sc.md 1 * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update sparse_coding.md * Update sparse_coding.md * Update sparse_coding.md * Update sparse_coding.md * Update hierarchical_sc.md * Update sparse_coding.md * Update sparse_coding.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Add files via upload * Delete docs/images/hgpc_network.pdf * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Create hgpc * Delete docs/images/museum/hgpc * Create d * Add files via upload * Delete docs/images/hgpc_model.png * Delete docs/images/museum/hgpc/d * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Delete docs/images/museum/hgpc/Input_layer.png * Add files via upload * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Update hierarchical_sc.md * Create Generative_PC.md * Update and rename Generative_PC.md to generative_pc.md * Update generative_pc.md * Update generative_pc.md * Update model_utils.py * Update model_utils.py * Update model_utils.py * Update model_utils.py * Update rateCell.py * Update generative_pc.md * Create pc-sindy.md * Update pc-sindy.md * Update model_utils.py sine activation function added * Update model_utils.py * Update ode_utils.py jitified * Delete docs/museum/hierarchical_sc.md * Delete docs/museum/generative_pc.md * Delete ngclearn/components/synapses/patched directory * Update __init__.py * Add files via upload ode with scanner added * Update ode_solver.py _ removed * Fix/reorganize feature library (#74) * Update ode_utils.py * Update ode_solver.py rk4 revised and __main__ added * Delete ngclearn/utils/diffeq/ode_functions.py * Create odes.py odes name and structure changed * Update __init__.py * Create feature_library.py * Create __init__.py * Create base.py * Delete docs/muse… * patched pkg_resources and versioning items to prep for v3.1.0 * cleaned up stdp-syn error in nudge --------- Co-authored-by: Alexander Ororbia Co-authored-by: Alexander Ororbia Co-authored-by: Viet Dung Nguyen <60036798+rxng8@users.noreply.github.com> Co-authored-by: Will Gebhardt Co-authored-by: Viet Nguyen Co-authored-by: Viet Dung Nguyen Co-authored-by: Faezeh Habibi <155960330+Faezehabibi@users.noreply.github.com> Co-authored-by: Anton Vice <118047001+antonvice@users.noreply.github.com> Co-authored-by: Copilot Co-authored-by: Sonny George <56851635+sonnygeorge@users.noreply.github.com> Co-authored-by: Alexander Ororbia Co-authored-by: Ankur Mali --- AUTHORS | 1 + README.md | 11 +- docs/images/museum/hgpc/GEC.png | Bin 0 -> 348398 bytes docs/images/museum/hgpc/patch_input.png | Bin 0 -> 103373 bytes docs/museum/harmonium.md | 5 +- docs/museum/pc_rao_ballard1999.md | 325 ++++++++++++++- .../ngclearn.components.input_encoders.rst | 8 + ...clearn.components.synapses.competitive.rst | 53 +++ .../ngclearn.components.synapses.hebbian.rst | 8 + docs/source/ngclearn.components.synapses.rst | 9 + docs/source/ngclearn.utils.analysis.rst | 8 + docs/source/ngclearn.utils.rst | 8 + docs/tutorials/neurocog/index.rst | 20 +- history.txt | 8 + ngclearn/__init__.py | 24 +- ngclearn/components/__init__.py | 3 + .../components/input_encoders/__init__.py | 2 + .../input_encoders/bernoulliCell.py | 10 +- .../components/input_encoders/ganglionCell.py | 226 +++++++++++ .../components/input_encoders/latencyCell.py | 24 +- .../neurons/graded/bernoulliErrorCell.py | 11 +- .../neurons/graded/gaussianErrorCell.py | 53 +-- .../neurons/graded/laplacianErrorCell.py | 10 +- .../neurons/graded/leakyNoiseCell.py | 20 +- .../components/neurons/graded/rateCell.py | 10 +- .../components/neurons/spiking/WTASCell.py | 22 +- .../neurons/spiking/hodgkinHuxleyCell.py | 8 +- ngclearn/components/synapses/__init__.py | 6 +- .../synapses/competitive/ART2ASynapse.py | 246 ++++++++++++ .../synapses/competitive/SOMSynapse.py | 377 ++++++++++++++++++ .../synapses/competitive/__init__.py | 6 + .../synapses/competitive/hopfieldSynapse.py | 230 +++++++++++ .../competitive/vectorQuantizeSynapse.py | 287 +++++++++++++ ngclearn/components/synapses/denseSynapse.py | 22 +- .../components/synapses/hebbian/BCMSynapse.py | 2 +- .../synapses/hebbian/STDPSynapse.py | 224 +++++++++++ .../components/synapses/hebbian/__init__.py | 1 + .../synapses/hebbian/hebbianSynapse.py | 18 +- ngclearn/components/synapses/mpsSynapse.py | 225 +++++++++++ .../synapses/patched/hebbianPatchedSynapse.py | 41 +- .../synapses/patched/patchedSynapse.py | 145 ++++--- ngclearn/utils/JaxProcessesMixin.py | 34 +- ngclearn/utils/__init__.py | 1 + ngclearn/utils/analysis/__init__.py | 2 + ngclearn/utils/analysis/attentive_probe.py | 23 +- ngclearn/utils/analysis/knn_probe.py | 163 ++++++++ ngclearn/utils/analysis/linear_probe.py | 10 +- ngclearn/utils/diffeq/ode_utils.py | 2 +- ngclearn/utils/matrix_utils.py | 26 ++ ngclearn/utils/metric_utils.py | 33 +- ngclearn/utils/model_utils.py | 270 +++++++++++-- ngclearn/utils/patch_utils.py | 6 +- pyproject.toml | 2 +- requirements.txt | 4 +- .../neurons/graded/test_leakyNoiseCell.py | 9 +- .../synapses/competitve/test_SOMSynapse.py | 112 ++++++ .../synapses/hebbian/test_BCMSynapse.py | 4 +- .../patched/test_hebbianPatchedSynapse.py | 4 +- .../synapses/patched/test_patchedSynapse.py | 2 + tests/components/synapses/test_mpsSynapse.py | 97 +++++ 60 files changed, 3255 insertions(+), 266 deletions(-) create mode 100644 docs/images/museum/hgpc/GEC.png create mode 100644 docs/images/museum/hgpc/patch_input.png create mode 100644 docs/source/ngclearn.components.synapses.competitive.rst create mode 100644 ngclearn/components/input_encoders/ganglionCell.py create mode 100644 ngclearn/components/synapses/competitive/ART2ASynapse.py create mode 100644 ngclearn/components/synapses/competitive/SOMSynapse.py create mode 100644 ngclearn/components/synapses/competitive/__init__.py create mode 100644 ngclearn/components/synapses/competitive/hopfieldSynapse.py create mode 100644 ngclearn/components/synapses/competitive/vectorQuantizeSynapse.py create mode 100755 ngclearn/components/synapses/hebbian/STDPSynapse.py create mode 100644 ngclearn/components/synapses/mpsSynapse.py create mode 100644 ngclearn/utils/analysis/knn_probe.py create mode 100644 ngclearn/utils/matrix_utils.py create mode 100644 tests/components/synapses/competitve/test_SOMSynapse.py create mode 100644 tests/components/synapses/test_mpsSynapse.py diff --git a/AUTHORS b/AUTHORS index efa2d9f7..8523ca5e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,3 +15,4 @@ Contributors Maxbeth2 (Ohas) pagrawal-psu pulinagrawal +antonvice diff --git a/README.md b/README.md index a164fff3..757b9862 100644 --- a/README.md +++ b/README.md @@ -15,15 +15,12 @@ which implements several historical models, can be found here. The official blog-post related to the source paper behind this software library -can be found +can be found here.
You can find the related paper right here, which was selected to appear in the Nature Neuromorphic Hardware and Computing Collection in 2023 and was chosen as one of the Editors' Highlights for Applied Physics and Mathematics in 2022. - - ## Installation ### Dependencies @@ -42,7 +39,7 @@ ngc-learn requires: --> --- -ngc-learn 3.0.0 and later require Python 3.10 or newer as well as ngcsimlib >=3.0.0. +ngc-learn 3.1.0 and later require Python 3.10 or newer as well as ngcsimlib >=3.0.0. ngc-learn's plotting capabilities (routines within `ngclearn.utils.viz`) require Matplotlib (>=3.8.0) and imageio (>=2.31.5) and both plotting and density estimation tools (routines within ``ngclearn.utils.density``) will require Scikit-learn (>=0.24.2). @@ -75,7 +72,7 @@ Python 3.11.4 (main, MONTH DAY YEAR, TIME) [GCC XX.X.X] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import ngclearn >>> ngclearn.__version__ -'3.0.0' +'3.1.0' ``` Note: For access to the previous Tensorflow-2 version of ngc-learn (of @@ -122,7 +119,7 @@ $ python install -e . **Version:**
-3.0.1 +3.1.0 Author: Alexander G. Ororbia II
diff --git a/docs/images/museum/hgpc/GEC.png b/docs/images/museum/hgpc/GEC.png new file mode 100644 index 0000000000000000000000000000000000000000..47ec531fb21fec9c946845bb4a2c524c5712064f GIT binary patch literal 348398 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

    ~qP`(S1P?c5P)b2HZc}U&;ySpwJCaTv^c8B{hC7 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 VQr14J84B_zE2$(=BW4`<{{hZp?U?`o literal 0 HcmV?d00001 diff --git a/docs/museum/harmonium.md b/docs/museum/harmonium.md index c43e6fd5..e14d0c7b 100644 --- a/docs/museum/harmonium.md +++ b/docs/museum/harmonium.md @@ -8,9 +8,8 @@ In this walkthrough, we will design a simple Harmonium, also known as the restri specifically focus on learning its synaptic connections with an algorithmic recipe known as contrastive divergence (CD), which can be considered to be a stochastic form of CHL. After going through this exhibit, you will: -1. Learn how to construct an `NGCGraph` that emulates the structure of an RBM and adapt the NGC settling process to - calculate approximate synaptic weight gradients in accordance to contrastive divergence. -2. Simulate fantasized image samples using the block Gibbs sampler implicitly defined by the negative phase graph. +1. Learn how to construct a model context that emulates the structure of an RBM and simulate its inference/reconstruction process to calculate approximate synaptic weight gradients in accordance to contrastive divergence (including an extension of it called persistent contrastive divergence). +2. Simulate fantasized image samples using a block Gibbs sampler that is defined by (re-)using a portion of the model's message-passing structure. Note that the folders of interest to this walkthrough are: + `ngc-museum/exhibits/harmonium/`: this contains the necessary simulation scripts (which can be found diff --git a/docs/museum/pc_rao_ballard1999.md b/docs/museum/pc_rao_ballard1999.md index cfa6b921..7bdc9952 100644 --- a/docs/museum/pc_rao_ballard1999.md +++ b/docs/museum/pc_rao_ballard1999.md @@ -1,4 +1,4 @@ -# Hierarchical Predictive Coding (Rao & Ballard; 1999) +# Hierarchical Predictive Coding for Reconstruction (Rao & Ballard; 1999) In this exhibit, we create, simulate, and visualize the internally acquired receptive fields of the predictive coding model originally proposed in (Rao & Ballard, 1999) [1]. @@ -6,7 +6,328 @@ model originally proposed in (Rao & Ballard, 1999) [1]. The model code for this exhibit can be found [here](https://github.com/NACLab/ngc-museum/tree/main/exhibits/pc_recon). +## Setting Up Hierarchical Predictive Coding (HPC) with NGC-Learn + +### The HPC Model for Reconstruction Tasks + +To build an HPC model, you will first need to define all of the components inside of the model. +After doing this, you will next wire those components together under a specific configuration, depending +on the task. +This setup process involves doing the following: +1. **Create neural component**: instantiating neuronal unit (with dynamics) components. +2. **Create synaptic component**: instantiating synaptic connection components. +3. **Wire components**: defining how the components connect and interact with each other. + + + +### 1: Create the Neural Component(s): + + + + +**Representation (Response) Neuronal Layers** +
    + +If we want to build an HPC model, which is a hierarchical neural network, we will need to set up a few neural layers. For predictive coding with real-valued (graded) dynamics, we will want to use the library's in-built `RateCell` components ([RateCell tutorial](https://ngc-learn.readthedocs.io/en/latest/tutorials/neurocog/rate_cell.html)). +Since we want a 3-layer network (i.e., an HPC model with three hidden, or "representation", layers), we need to define three components, each with an `n_units` size for their respective hidden representations. This is done as follows: + +```python +with Context("Circuit") as circuit: ## set up a (simulation) context for HPC model w/ 3 hidden layers + z3 = RateCell("z3", n_units=h3_dim, tau_m=tau_m, act_fx=act_fx, prior=(prior_type, lmbda)) + z2 = RateCell("z2", n_units=h2_dim, tau_m=tau_m, act_fx=act_fx, prior=(prior_type, lmbda)) + z1 = RateCell("z1", n_units=h1_dim, tau_m=tau_m, act_fx=act_fx, prior=(prior_type, lmbda)) +``` + + + +
    +
    + + + +**Error Neuronal Layers** +
    + + +For each (`RateCell`) layer's activation, we will also want to setup an additional set of neuronal +layers -- with the same size as the representation layers -- to measure the prediction error(s) +for the sets of individual `RateCell` components. The error values that this layers will emit will +be later used to calculate the (free) **energy** for each layer as well as the whole model. This is +specified like so: + +```python + e2 = GaussianErrorCell("e2", n_units=h2_dim) ## e2_size == z2_size + e1 = GaussianErrorCell("e1", n_units=h1_dim) ## e1_size == z1_size + e0 = GaussianErrorCell("e0", n_units=in_dim) ## e0_size == z0_size (x size) (stimulus layer) +``` + +
    +
    + + + +### 2: Create the Synaptic Component(s): + + + +
    +
    + + + +**Forward Synaptic Connections** +
    + +To connect the layers of our model to each other, we will need to create synaptic components +(which will project/propagate information across the layers); ultimately, this means we need +to construct the message-passing scheme of our HPC model. In order to send information in a +"forward pass" (from the stimulus/input layer into deeper hidden layers, in a bottom-up stream), +we make use of `ForwardSynapse` components. Please check out +[Brain's Information Flow](https://github.com/Faezehabibi/pc_tutorial/blob/main/information_flow.md#---information-flow-in-the-brain--) for a more detailed explanation of the flow of information that we use in the context +of brain modeling. +Setting up the forward projections/pathway is done like so: + +```python + E3 = ForwardSynapse("E3", shape=(h2_dim, h3_dim)) ## pre-layer size (h2) => (h3) post-layer size + E2 = ForwardSynapse("E2", shape=(h1_dim, h2_dim)) ## pre-layer size (h1) => (h2) post-layer size + E1 = ForwardSynapse("E1", shape=(in_dim, h1_dim)) ## pre-layer size (x) => (h1) post-layer size +``` + + + +
    +
    + + + +**Backward(s) Synaptic Connections** +
    + +For each `ForwardSynapse` component that sends information upward (i.e., the "bottom-up" stream), +there exists a `BackwardSynapse` component that reverses the flow of information flow by sending +signals back downwards (i.e., the "top-down" stream -- from the top layer to the bottom/input ones). +Again, we refer you to this resource [Information Flow](https://github.com/Faezehabibi/pc_tutorial/blob/19b0692fa307f2b06676ca93b9b93ba3ba854766/information_flow.md) for more information. +To set up the backwards/message-passing connections, you will write to the following: + +```python + W3 = BackwardSynapse("W3", + shape=(h3_dim, h2_dim), ## pre-layer size (h3) => (h2) post-layer size + optim_type=opt_type, ## optimization method (sgd, adam, ...) + weight_init=w3_init, ## W3[t0]: initial values before training at time[t0] + w_bound=w_bound, ## -1 for deactivating the bouding synaptic value + sign_value=-1., ## -1 means M-step solve minimization problem + eta=eta, ## learning-rate (lr) + ) + W2 = BackwardSynapse("W2", + shape=(h2_dim, h1_dim), ## pre-layer size (h2) => (h1) post-layer size + optim_type=opt_type, ## Optimizer + weight_init=w2_init, ## W2[t0] + w_bound=w_bound, ## -1: deactivate the bouding + sign_value=-1., ## Minimization + eta=eta, ## lr + ) + W1 = BackwardSynapse("W1", + shape=(h1_dim, in_dim), ## pre-layer size (h1) => (x) post-layer size + optim_type=opt_type, ## Optimizer + weight_init=w1_init, ## W1[t0] + w_bound=w_bound, ## -1: deactivate the bouding + sign_value=-1., ## Minimization + eta=eta, ## lr + ) +``` + +
    +
    + + +### Wiring the Component(s) Together: + + +The signaling pathway that we will create is in accordance with [1] (Rao and Ballard's classical model). +Error (mismatch signals) is information that goes from the bottom (layer) of the model to its top (layer) in +the forward pass(es). +Corrected prediction information will come back from the top (layer) to the bottom (layer) in the backward +pass(es). + +The following code block will set up the top-down projection message-passing pathway: + +```python + ######### Feedback pathways (Top-down) ######### + ### Actual neural activations + z2.z >> e2.target ## Layer 2's target is z2's rate-value `z` + z1.z >> e1.target ## Layer 1's target is z1's rate-value `z` + ## Note: e0.target will be clamped to input data `x` + + ### Top-down predictions + z3.zF >> W3.inputs ## pass phi(z3) down W3 + W3.outputs >> e2.mu ## prediction `mu` for (layer 2) z2's `z` + z2.zF >> W2.inputs ## pass phi(z2) down W2 + W2.outputs >> e1.mu ## prediction `mu` for (layer 1) z1's `z` + z1.zF >> W1.inputs ## pass phi(z1) down W1 + W1.outputs >> e0.mu ## prediction `mu` for (input layer) z0=x + + ### Top-down prediction errors + e1.dtarget >> z1.j_td + e2.dtarget >> z2.j_td +``` + +The following code-block will set up the error-feedback, bottom-up message-passing pathway: + +```python + ######### Forward propagation (Bottom-up) ######### + ## feedforward the errors via synapses + e2.dmu >> E3.inputs + e1.dmu >> E2.inputs + e0.dmu >> E1.inputs + + ## Bottom-up modulated errors + E3.outputs >> z3.j + E2.outputs >> z2.j + E1.outputs >> z1.j +``` + +Finally, to enable learning, we will need to set up simple 2-term/factor Hebbian rules like so: + +```python + ########### Hebbian learning ############ + ### Set up terms for 2-term Hebbian rules + ## Pre-synaptic activation (terms) + z3.zF >> W3.pre + z2.zF >> W2.pre + z1.zf >> W1.pre + + ## Post-synaptic residual error (terms) + e2.dmu >> W3.post + e1.dmu >> W2.post + e0.dmu >> W1.post +``` + +
    +
    + + +#### Specifying the HPC Model's Process Dynamics: + +The only remaining thing to do for the above model is to specify its core simulation functions +(known in NGC-Learn as `MethodProcess` mechanisms). For an HPC model, we want to make sure +we define how it's full message-passing is carried out as well as how learning (synaptic plasticity) +occurs. Ultimately, this will follow the (dynamic) expectation-maximization (E-M) scheme we have +discussed in other model exhibits, e.g., the [sparse coding and dictionary learning exhibit](sparse_coding.md). + +The method-processes for inference (expectation) and adaptation (maximization) can be written out under +your model context as follows: + +```python + reset_process = (MethodProcess(name="reset_process") ## reset-to-baseline + >> z3.reset + >> z2.reset + >> z1.reset + >> e2.reset + >> e1.reset + >> e0.reset + >> W3.reset + >> W2.reset + >> W1.reset + >> E3.reset + >> E2.reset + >> E1.reset) + advance_process = (MethodProcess(name="advance_process") ## E-step + >> E1.advance_state + >> E2.advance_state + >> E3.advance_state + >> z3.advance_state + >> z2.advance_state + >> z1.advance_state + >> W3.advance_state + >> W2.advance_state + >> W1.advance_state + >> e2.advance_state + >> e1.advance_state + >> e0.advance_state) + evolve_process = (MethodProcess(name="evolve_process") ## M-step + >> W1.evolve + >> W2.evolve + >> W3.evolve) +``` + +Below we show a code-snippet depicting how the HPC model's ability to process a stimulus input +(or batch of inputs) `obs` -- or observation -- is carried out in practice: + +```python +######### Process ######### + +#### reset/set all neuronal components to their resting values / initial conditions +circuit.reset.run() + +#### clamp the observation/signal obs to the lowest layer activation +e0.target.set(obs) ## e0 contains the place where our stimulus target goes + +#### pin/tie feedback synapses to transpose of forward ones +E1.weights.set(jnp.transpose(W1.weights.value)) +E2.weights.set(jnp.transpose(W2.weights.value)) +E3.weights.set(jnp.transpose(W3.weights.value)) + +#### apply the dynamic E-M algorithm on the HPC model given obs +inputs = jnp.array(self.advance_proc.pack_rows(T, t=lambda x: x, dt=dt)) +stateManager.state, outputs = self.process.scan(inputs) ## Perform several (T) E-steps +circuit.evolve.run(t=T, dt=1.) ## Perform M-step (scheduled synaptic updates) + +#### extract some statistics for downstream analysis +obs_mu = e0.mu.value ## get reconstructed signal +L0 = e0.L.value ## calculate reconstruction loss +free_energy = e0.L.value + e1.L.value + e2.L.value ## F = Sum_l Sum_j [e^l_j]^2 +``` + +Note that we make use of NGC-Learn's backend state-manager (`ngcsimlib.global_state.StateManager`) to +roll-out the `T` E-steps carried out above efficiently (and effectively using JAX's scan utilities; +see the NGC-Learn configuration documents, such as the one related to the +[global state](../tutorials/configuration/global_state.md) for more information). + +
    +
    +
    +
    + + + + +### Train the PC model for Reconstructing Image Patches + + + +
    + +In this scenario, the input image is not the full scene (or complete set of pixels that fully describe an image); +instead, the input is locally "patched", which means that is has been broken down into smaller $K \times K$ +blocks/grids. This input patch exctraction scheme changes the information processing of the neuronal +units within the network, i.e., local features are now important. The original model(s) of Rao and Ballard's +1999 work [1] are also in a patched format, modeling how retinal processing units are localized in nature. +Setting up the input stimulus in this manner also results in models that acquire filters (or receptive fields) +similar to those acquired in convolutional neural networks (CNNs). + +
    + +```python + for nb in range(n_batches): + Xb = X[nb * images_per_batch: (nb + 1) * images_per_batch, :] ## shape: (mb_size, 784) + Xb = generate_patch_set(Xb, patch_shape, center=True) + + Xmu, Lb = model.process(Xb) +``` + + + + + ## References [1] Rao, Rajesh PN, and Dana H. Ballard. "Predictive coding in the visual cortex: a functional interpretation of -some extra-classical receptive-field effects." Nature neuroscience 2.1 (1999): 79-87. \ No newline at end of file +some extra-classical receptive-field effects." Nature neuroscience 2.1 (1999): 79-87. diff --git a/docs/source/ngclearn.components.input_encoders.rst b/docs/source/ngclearn.components.input_encoders.rst index 7b9fbc33..677f271f 100644 --- a/docs/source/ngclearn.components.input_encoders.rst +++ b/docs/source/ngclearn.components.input_encoders.rst @@ -12,6 +12,14 @@ ngclearn.components.input\_encoders.bernoulliCell module :undoc-members: :show-inheritance: +ngclearn.components.input\_encoders.ganglionCell module +------------------------------------------------------- + +.. automodule:: ngclearn.components.input_encoders.ganglionCell + :members: + :undoc-members: + :show-inheritance: + ngclearn.components.input\_encoders.latencyCell module ------------------------------------------------------ diff --git a/docs/source/ngclearn.components.synapses.competitive.rst b/docs/source/ngclearn.components.synapses.competitive.rst new file mode 100644 index 00000000..a766e3c8 --- /dev/null +++ b/docs/source/ngclearn.components.synapses.competitive.rst @@ -0,0 +1,53 @@ +ngclearn.components.synapses.competitive package +================================================ + +Submodules +---------- + +ngclearn.components.synapses.competitive.ART2ASynapse module +------------------------------------------------------------ + +.. automodule:: ngclearn.components.synapses.competitive.ART2ASynapse + :members: + :undoc-members: + :show-inheritance: + +ngclearn.components.synapses.competitive.SOMSynapse module +---------------------------------------------------------- + +.. automodule:: ngclearn.components.synapses.competitive.SOMSynapse + :members: + :undoc-members: + :show-inheritance: + +ngclearn.components.synapses.competitive.hopfieldSynapse module +--------------------------------------------------------------- + +.. automodule:: ngclearn.components.synapses.competitive.hopfieldSynapse + :members: + :undoc-members: + :show-inheritance: + +ngclearn.components.synapses.competitive.simple\_ART2ASynapse module +-------------------------------------------------------------------- + +.. automodule:: ngclearn.components.synapses.competitive.simple_ART2ASynapse + :members: + :undoc-members: + :show-inheritance: + +ngclearn.components.synapses.competitive.vectorQuantizeSynapse module +--------------------------------------------------------------------- + +.. automodule:: ngclearn.components.synapses.competitive.vectorQuantizeSynapse + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: ngclearn.components.synapses.competitive + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/ngclearn.components.synapses.hebbian.rst b/docs/source/ngclearn.components.synapses.hebbian.rst index 778e59ec..ef76ced8 100644 --- a/docs/source/ngclearn.components.synapses.hebbian.rst +++ b/docs/source/ngclearn.components.synapses.hebbian.rst @@ -12,6 +12,14 @@ ngclearn.components.synapses.hebbian.BCMSynapse module :undoc-members: :show-inheritance: +ngclearn.components.synapses.hebbian.STDPSynapse module +------------------------------------------------------- + +.. automodule:: ngclearn.components.synapses.hebbian.STDPSynapse + :members: + :undoc-members: + :show-inheritance: + ngclearn.components.synapses.hebbian.eventSTDPSynapse module ------------------------------------------------------------ diff --git a/docs/source/ngclearn.components.synapses.rst b/docs/source/ngclearn.components.synapses.rst index 43791098..087bf917 100644 --- a/docs/source/ngclearn.components.synapses.rst +++ b/docs/source/ngclearn.components.synapses.rst @@ -7,6 +7,7 @@ Subpackages .. toctree:: :maxdepth: 4 + ngclearn.components.synapses.competitive ngclearn.components.synapses.convolution ngclearn.components.synapses.hebbian ngclearn.components.synapses.modulated @@ -55,6 +56,14 @@ ngclearn.components.synapses.exponentialSynapse module :undoc-members: :show-inheritance: +ngclearn.components.synapses.mpsSynapse module +---------------------------------------------- + +.. automodule:: ngclearn.components.synapses.mpsSynapse + :members: + :undoc-members: + :show-inheritance: + ngclearn.components.synapses.staticSynapse module ------------------------------------------------- diff --git a/docs/source/ngclearn.utils.analysis.rst b/docs/source/ngclearn.utils.analysis.rst index 98e44181..b6c12f1e 100644 --- a/docs/source/ngclearn.utils.analysis.rst +++ b/docs/source/ngclearn.utils.analysis.rst @@ -12,6 +12,14 @@ ngclearn.utils.analysis.attentive\_probe module :undoc-members: :show-inheritance: +ngclearn.utils.analysis.knn\_probe module +----------------------------------------- + +.. automodule:: ngclearn.utils.analysis.knn_probe + :members: + :undoc-members: + :show-inheritance: + ngclearn.utils.analysis.linear\_probe module -------------------------------------------- diff --git a/docs/source/ngclearn.utils.rst b/docs/source/ngclearn.utils.rst index 9f4e4809..c674b875 100644 --- a/docs/source/ngclearn.utils.rst +++ b/docs/source/ngclearn.utils.rst @@ -50,6 +50,14 @@ ngclearn.utils.io\_utils module :undoc-members: :show-inheritance: +ngclearn.utils.matrix\_utils module +----------------------------------- + +.. automodule:: ngclearn.utils.matrix_utils + :members: + :undoc-members: + :show-inheritance: + ngclearn.utils.metric\_utils module ----------------------------------- diff --git a/docs/tutorials/neurocog/index.rst b/docs/tutorials/neurocog/index.rst index b702a535..faecb52a 100644 --- a/docs/tutorials/neurocog/index.rst +++ b/docs/tutorials/neurocog/index.rst @@ -22,7 +22,16 @@ available for external download in the `Model Museum = (3, 8): ## for new versions of python/ngc-learn + from importlib.metadata import version, distributions, PackageNotFoundError +else: ## for older versions of python before 3.8 + from importlib_metadata import version, distributions, PackageNotFoundError +#import pkg_resources +#from pkg_resources import get_distribution +#__version__ = get_distribution('ngclearn').version + +## Following obtains ngc-learn's version +from importlib.metadata import version +__version__ = version("ngclearn") if sys.version_info.minor < 10: import warnings @@ -10,9 +17,12 @@ "Running ngclearn and jax in a python version prior to 3.10 may have unintended consequences. Compatibility " "with python 3.8 is maintained to allow for lava-nc components and should only be used with those") +## Following obtains installed package names (as normalized keys) for ngc-learn #required = {'ngcsimlib', 'jax', 'jaxlib'} ## list of core ngclearn dependencies required = {'ngcsimlib'} #, 'jax', 'jaxlib'} -installed = {pkg.key for pkg in pkg_resources.working_set} +#installed = {pkg.key for pkg in pkg_resources.working_set} +#missing = required - installed +installed = {dist.metadata['Name'].lower().replace('-', '_') for dist in distributions()} missing = required - installed for key in required: @@ -20,7 +30,7 @@ raise ImportError(str(key) + ", a core dependency of ngclearn, is not " \ "currently installed!") - +################################################################################## ## Needed to preload is called before anything in ngclearn from pathlib import Path from sys import argv @@ -36,7 +46,7 @@ from ngcsimlib.parser import compilable from ngcsimlib.operations import Summation, Product - +## this prevents ngc-learn from messing with sphinx/building if not Path(argv[0]).name == "sphinx-build" or Path(argv[0]).name == "build.py": if "readthedocs" not in argv[0]: ## prevent readthedocs execution of preload from ngcsimlib import configure diff --git a/ngclearn/components/__init__.py b/ngclearn/components/__init__.py index d8c4dc67..0b81afdc 100644 --- a/ngclearn/components/__init__.py +++ b/ngclearn/components/__init__.py @@ -27,6 +27,7 @@ ## point to input encoder component types from .input_encoders.bernoulliCell import BernoulliCell from .input_encoders.poissonCell import PoissonCell +from .input_encoders.ganglionCell import RetinalGanglionCell from .input_encoders.latencyCell import LatencyCell from .input_encoders.phasorCell import PhasorCell @@ -34,10 +35,12 @@ from .synapses.denseSynapse import DenseSynapse from .synapses.staticSynapse import StaticSynapse from .synapses.hebbian.hebbianSynapse import HebbianSynapse +from .synapses.hebbian.STDPSynapse import STDPSynapse from .synapses.hebbian.traceSTDPSynapse import TraceSTDPSynapse from .synapses.hebbian.expSTDPSynapse import ExpSTDPSynapse from .synapses.hebbian.eventSTDPSynapse import EventSTDPSynapse from .synapses.hebbian.BCMSynapse import BCMSynapse +from .synapses.competitive.SOMSynapse import SOMSynapse from .synapses.STPDenseSynapse import STPDenseSynapse from .synapses.exponentialSynapse import ExponentialSynapse from .synapses.doubleExpSynapse import DoubleExpSynapse diff --git a/ngclearn/components/input_encoders/__init__.py b/ngclearn/components/input_encoders/__init__.py index 5d14d2ec..9af3241b 100644 --- a/ngclearn/components/input_encoders/__init__.py +++ b/ngclearn/components/input_encoders/__init__.py @@ -1,5 +1,7 @@ from .bernoulliCell import BernoulliCell from .poissonCell import PoissonCell from .latencyCell import LatencyCell +from .ganglionCell import RetinalGanglionCell from .phasorCell import PhasorCell + diff --git a/ngclearn/components/input_encoders/bernoulliCell.py b/ngclearn/components/input_encoders/bernoulliCell.py index 87b965fc..132f7d92 100755 --- a/ngclearn/components/input_encoders/bernoulliCell.py +++ b/ngclearn/components/input_encoders/bernoulliCell.py @@ -26,12 +26,14 @@ class BernoulliCell(JaxComponent): batch_size: batch size dimension of this cell (Default: 1) """ - def __init__(self, name: str, n_units: int, batch_size: int = 1, key: Union[jax.Array, None] = None, **kwargs): + def __init__( + self, name: str, n_units: int, batch_size: int = 1, key: Union[jax.Array, None] = None, **kwargs + ): super().__init__(name=name, key=key) ## Layer Size Setup - self.batch_size = Compartment(batch_size) - self.n_units = Compartment(n_units) + self.batch_size = batch_size + self.n_units = n_units restVals = jnp.zeros((batch_size, n_units)) self.inputs = Compartment(restVals, display_name="Input Stimulus") # input compartment @@ -47,7 +49,7 @@ def advance_state(self, t): @compilable def reset(self): - restVals = jnp.zeros((self.batch_size.get(), self.n_units.get())) + restVals = jnp.zeros((self.batch_size, self.n_units)) # BUG: the self.inputs here does not have the targeted field # NOTE: Quick workaround is to check if targeted is in the input or not hasattr(self.inputs, "targeted") and not self.inputs.targeted and self.inputs.set(restVals) diff --git a/ngclearn/components/input_encoders/ganglionCell.py b/ngclearn/components/input_encoders/ganglionCell.py new file mode 100644 index 00000000..a35c7b0a --- /dev/null +++ b/ngclearn/components/input_encoders/ganglionCell.py @@ -0,0 +1,226 @@ +from ngclearn.components.jaxComponent import JaxComponent +from jax import numpy as jnp, random +from ngclearn import compilable +from ngclearn import Compartment +import jax +from typing import Union, Tuple + +def _create_gaussian_filter(patch_shape, sigma): + ## Create a 2D Gaussian kernel centered on patch_shape with given sigma. + px, py = patch_shape + + x_ = jnp.linspace(0, px - 1, px) + y_ = jnp.linspace(0, py - 1, py) + + x, y = jnp.meshgrid(x_, y_) + + xc = px // 2 + yc = py // 2 + + filter = jnp.exp(-((x - xc) ** 2 + (y - yc) ** 2) / (2 * (sigma ** 2))) + return filter / jnp.sum(filter) + +def _create_dog_filter(patch_shape, sigma, k=1.6, lmbda=1): + g1 = _create_gaussian_filter(patch_shape, sigma=sigma) + g2 = _create_gaussian_filter(patch_shape, sigma=sigma * k) + + dog = g1 - lmbda * g2 + + return dog #- jnp.mean(dog) + +def _create_patches(obs, patch_shape, step_shape): + """ + Extract 2D patches from a batch of images using a sliding window. + + Args: + obs: Input array (B, ix, iy) + + patch_shape: Patch size (px, py) + + step_shape: Stride (sx, sy) -- use 0 for full-overlap + + Returns: + Patches array (B, n_cells, px, py) + + """ + + B, ix, iy = obs.shape + px, py = patch_shape + sx, sy = step_shape + + if sx == 0: + n_x = ix // px + else: + n_x = (ix - px) // sx + 1 + + if sy == 0: + n_y = iy // py + else: + n_y = (iy - py) // sy + 1 + + patches = jnp.stack([ + obs[:, + i * sx:i * sx + px, j * sy:j * sy + py + ] for i in range(n_x) + for j in range(n_y) + ], axis=1) + + return patches + + +class RetinalGanglionCell(JaxComponent): + """ + A group of retinal ganglion cell that senses the input stimuli and sends out the filtered signal to the brain. + + | --- Cell Input Compartments: --- + | inputs - input (takes in external signals) + | --- Cell State Compartments: --- + | filter - filter (function applied to input) + | --- Cell Output Compartments: --- + | outputs - output + + Args: + name: the string name of this cell + + filter_type: string name of filter function (Default: identity) + :Note: supported filters include "gaussian", "difference_of_gaussian" + + sigma: standard deviation of gaussian kernel + + area_shape: receptive field area of ganglion cells in this module all together + + n_cells: number of ganglion cells in this module + + patch_shape: each ganglion cell receptive field area + + step_shape: the non-overlapping area between each two ganglion cells + + batch_size: batch size dimension of this cell (Default: 1) + """ + + def __init__(self, name: str, + filter_type: str, + area_shape: Tuple[int, int], + n_cells: int, + patch_shape: Tuple[int, int], + step_shape: Tuple[int, int], + batch_size: int = 1, + sigma: float = 1.0, + key: Union[jax.Array, None] = None, + **kwargs): + super().__init__(name=name, key=key) + + + ## Layer Size Setup + self.filter_type = filter_type + self.n_cells = n_cells + self.sigma = sigma + + self.batch_size = batch_size + self.area_shape = area_shape + self.patch_shape = patch_shape + self.step_shape = step_shape + + filter = jnp.ones(self.patch_shape) + + if filter_type == 'gaussian': + filter = _create_gaussian_filter(patch_shape=self.patch_shape, sigma=self.sigma) + elif filter_type == 'difference_of_gaussian': + filter = _create_dog_filter(patch_shape=self.patch_shape, sigma=sigma) + + # ═════════════════ compartments initial values ════════════════════ + in_restVals = jnp.zeros((batch_size, + *self.area_shape)) ## input: (B | ix | iy) + + out_restVals = jnp.zeros((batch_size, ## output.shape: (B | n_cells * px * py) + self.n_cells * self.patch_shape[0] * self.patch_shape[1])) + + # ═══════════════════ set compartments ══════════════════════ + self.inputs = Compartment(in_restVals, display_name="Input Stimulus") # input compartment + self.filter = Compartment(filter, display_name="Filter") # Filter compartment + self.outputs = Compartment(out_restVals, display_name="Output Signal") # output compartment + + @compilable + def advance_state(self, t): + inputs = self.inputs.get() + filter = self.filter.get() + px, py = self.patch_shape + + # ═══════════════════ extract pathches for filters ══════════════════ + input_patches = _create_patches(inputs, patch_shape=self.patch_shape, step_shape=self.step_shape) + + # ═══════════════════ apply filter to all pathches ══════════════════ + filtered_input = input_patches * filter ## shape: (B | n_cells | px | py) + + # ════════════ reshape all cells responses to a single input to brain ════════════ + filtered_input = filtered_input.reshape(-1, self.n_cells * (px * py)) ## shape: (B | n_cells * px * py) + + # ═══════════════════ normalize filtered signals ══════════════════ + outputs = filtered_input - jnp.mean(filtered_input, axis=1, keepdims=True) ## shape: (B | n_cells * px * py) + + self.outputs.set(outputs) + + @compilable + def reset(self): ## reset core components/statistics + # self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member + in_restVals = jnp.zeros((self.batch_size, *self.area_shape)) ## input: (B | ix | iy) + out_restVals = jnp.zeros((self.batch_size, ## output.shape: (B | n_cells * px * py) + self.n_cells * self.patch_shape[0] * self.patch_shape[1])) + self.inputs.set(in_restVals) + self.outputs.set(out_restVals) + + # Viet: NOTE: we should not need this function since the reset function + # one could set the batch size then do reset + # @compilable + # def batched_reset(self, batch_size): + # in_restVals = jnp.zeros((batch_size, *self.area_shape)) ## input: (B | ix | iy) + + # out_restVals = jnp.zeros((batch_size, ## output.shape: (B | n_cells * px * py) + # self.n_cells * self.patch_shape[0] * self.patch_shape[1])) + + # self.inputs.set(in_restVals) + # self.outputs.set(out_restVals) + + @classmethod + def help(cls): ## component help function + properties = { + "cell_type": "RetinalGanglionCell - filters the input stimuli, " + } + compartment_props = { + "inputs": + {"inputs": "Takes in external input signal values"}, + "states": + {"filter": "Preprocessing function applies to input)"}, + "outputs": + {"outputs": "Preprocessed signal values emitted at time t"}, + } + hyperparams = { + "filter_type": "Type of the filter for preprocessing the input", + "sigma": "Standard deviation of gaussian kernel", + "area_shape": "Effective receptive field area shape of ganglion cells in this module", + "n_cells": "Number of Retinal Ganglion (center-surround) cells to model in this layer", + "patch_shape": "Classical Receptive field area shape of individual ganglion cells in this module", + "step_shape": "Extra-Classical Receptive field area shape each ganglion cell in this module", + "batch_size": "Batch size dimension of this component" + } + info = {cls.__name__: properties, + "compartments": compartment_props, + "dynamics": "~ Gaussian(x)", + "hyperparameters": hyperparams} + return info + +if __name__ == '__main__': + from ngcsimlib.context import Context + with Context("Bar") as bar: + X = RetinalGanglionCell("RGC", filter_type="gaussian", + sigma=2.3, + area_shape=(16, 26), + n_cells = 3, + patch_shape=(16, 16), + step_shape=(0, 5) + ) + print(X) + + + + diff --git a/ngclearn/components/input_encoders/latencyCell.py b/ngclearn/components/input_encoders/latencyCell.py index c0708e3d..6d2ada37 100755 --- a/ngclearn/components/input_encoders/latencyCell.py +++ b/ngclearn/components/input_encoders/latencyCell.py @@ -151,18 +151,18 @@ def __init__( super().__init__(name=name, key=key) ## latency meta-parameters - self.first_spike_time = Compartment(first_spike_time) - self.tau = Compartment(tau) - self.threshold = Compartment(threshold) - self.linearize = Compartment(linearize) - self.clip_spikes = Compartment(clip_spikes) + self.first_spike_time = first_spike_time + self.tau = tau + self.threshold = threshold + self.linearize = linearize + self.clip_spikes = clip_spikes ## normalize latency code s.t. final spike(s) occur w/in num_steps - self.normalize = Compartment(normalize) - self.num_steps = Compartment(num_steps) + self.normalize = normalize + self.num_steps = num_steps ## Layer Size Setup - self.batch_size = Compartment(batch_size) - self.n_units = Compartment(n_units) + self.batch_size = batch_size + self.n_units = n_units ## Compartment setup restVals = jnp.zeros((batch_size, n_units)) @@ -175,12 +175,12 @@ def __init__( @compilable def calc_spike_times(self): - if self.clip_spikes.get(): + if self.clip_spikes: self.clip_mask.set((self.inputs.get() < self.threshold) * 1.) else: self.clip_mask.set(self.inputs.get() * 0.) - if self.linearize.get(): + if self.linearize: self.targ_sp_times.set( _calc_spike_times_linear(self.inputs.get(), self.tau.get(), @@ -207,7 +207,7 @@ def advance_state(self, t): @compilable def reset(self): - restVals = jnp.zeros((self.batch_size.get(), self.n_units.get())) + restVals = jnp.zeros((self.batch_size, self.n_units)) # BUG: the self.inputs here does not have the targeted field # NOTE: Quick workaround is to check if targeted is in the input or not hasattr(self.inputs, "targeted") and not self.inputs.targeted and self.inputs.set(restVals) diff --git a/ngclearn/components/neurons/graded/bernoulliErrorCell.py b/ngclearn/components/neurons/graded/bernoulliErrorCell.py index 978aa1ce..7aacbccc 100755 --- a/ngclearn/components/neurons/graded/bernoulliErrorCell.py +++ b/ngclearn/components/neurons/graded/bernoulliErrorCell.py @@ -105,13 +105,15 @@ def advance_state(self, dt): ## compute Bernoulli error cell output self.L.set(jnp.squeeze(L)) self.mask.set(mask) + @compilable + def reset(self): ## reset core components/statistics + self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member - # @transition(output_compartments=["dp", "dtarget", "target", "p", "modulator", "L", "mask"]) @compilable - def reset(self): ## reset core components/statistics - _shape = (self.batch_size, self.shape[0]) + def batched_reset(self, batch_size): + _shape = (batch_size, self.shape[0]) if len(self.shape) > 1: - _shape = (self.batch_size, self.shape[0], self.shape[1], self.shape[2]) + _shape = (batch_size, self.shape[0], self.shape[1], self.shape[2]) restVals = jnp.zeros(_shape) ## "rest"/reset values dp = restVals dtarget = restVals @@ -130,7 +132,6 @@ def reset(self): ## reset core components/statistics self.L.set(L) self.mask.set(mask) - @classmethod def help(cls): ## component help function properties = { diff --git a/ngclearn/components/neurons/graded/gaussianErrorCell.py b/ngclearn/components/neurons/graded/gaussianErrorCell.py index 776dad46..d12bd33f 100755 --- a/ngclearn/components/neurons/graded/gaussianErrorCell.py +++ b/ngclearn/components/neurons/graded/gaussianErrorCell.py @@ -7,12 +7,12 @@ class GaussianErrorCell(JaxComponent): ## Rate-coded/real-valued error unit/cell """ - A simple (non-spiking) Gaussian error cell - this is a fixed-point solution - of a mismatch signal. + A simple (non-spiking) Gaussian error cell - this is a fixed-point calculation of a mismatch signal. Specifically, + this error cell offers a configurable variance and calculates its local free energy (Gaussian log likelihood). | --- Cell Input Compartments: --- | mu - predicted value (takes in external signals) - | Sigma - predicted covariance (takes in external signals) + | Sigma - predicted covariance (takes in external signals), or, if just a scalar, then it's sigma^2 | target - desired/goal value (takes in external signals) | modulator - modulation signal (takes in optional external signals) | mask - binary/gating mask to apply to error neuron calculations @@ -31,7 +31,8 @@ class GaussianErrorCell(JaxComponent): ## Rate-coded/real-valued error unit/cell sigma: initial/fixed value for prediction covariance matrix (𝚺) in multivariate gaussian distribution; Note that if the compartment `Sigma` is never used, then this cell assumes that the covariance collapses - to a constant/fixed `sigma` + to a constant/fixed `sigma^2`, i.e., Sigma = sigma^2, where `sigma` is a scalar standard deviation argument + (Default: 1) """ def __init__(self, name, n_units, batch_size=1, sigma=1., shape=None, **kwargs): super().__init__(name, **kwargs) @@ -47,8 +48,8 @@ def __init__(self, name, n_units, batch_size=1, sigma=1., shape=None, **kwargs): sigma_shape = jnp.array(sigma).shape self.sigma_shape = sigma_shape self.shape = shape - self.n_units = n_units self.batch_size = batch_size + self.n_units = n_units ## Convolution shape setup self.width = self.height = n_units @@ -67,13 +68,15 @@ def __init__(self, name, n_units, batch_size=1, sigma=1., shape=None, **kwargs): self.mask = Compartment(restVals + 1.0) @staticmethod - def eval_log_density(target, mu, Sigma): + def _eval_log_density(target, mu, Sigma): ## Gaussian log likelihood + ## NOTE: ln(p) = -(x - mu)^2 * 1/(2 Sigma), where Sigma might be sigma^2 or covariance matrix _dmu = (target - mu) - log_density = -jnp.sum(jnp.square(_dmu)) * (0.5 / Sigma) - return log_density + #_numerator = 1. # 0.5 + log_density = -jnp.sum(jnp.square(_dmu)) * (1./((Sigma ** 2) * 2)) #* (_numerator / Sigma) + return log_density, _dmu ## return density and raw delta @compilable - def advance_state(self, dt): ## compute Gaussian error cell output + def advance_state(self, dt): ## compute Gaussian error cell output (fixed-point) # Get the variables mu = self.mu.get() target = self.target.get() @@ -87,12 +90,12 @@ def advance_state(self, dt): ## compute Gaussian error cell output # but should support full log likelihood of the multivariate Gaussian with covariance of different types # TODO: could introduce a variant of GaussianErrorCell that moves according to an ODE # (using integration time constant dt) - _dmu = (target - mu) # e (error unit) - dmu = _dmu / Sigma - dtarget = -dmu # reverse of e - dSigma = Sigma * 0 + 1. # no derivative is calculated at this time for sigma - L = -jnp.sum(jnp.square(_dmu)) * (0.5 / Sigma) - #L = GaussianErrorCell.eval_log_density(target, mu, Sigma) + + L, _dmu = GaussianErrorCell._eval_log_density(target, mu, Sigma) # L = -jnp.sum(jnp.square(_dmu)) * (0.5 / Sigma) + ## _dmu => "raw" e (error unit/mis-match) # _dmu = (target - mu) + dmu = _dmu * (1./ Sigma) ## obtain precision-scaled e: (target - mu)/Sigma + dtarget = -dmu # reverse of e ## -(target - mu)/Sigma + dSigma = Sigma * 0 + 1. # no derivative is calculated at this time for Sigma dmu = dmu * modulator * mask ## not sure how mask will apply to a full covariance... dtarget = dtarget * modulator * mask @@ -105,13 +108,15 @@ def advance_state(self, dt): ## compute Gaussian error cell output self.L.set(jnp.squeeze(L)) self.mask.set(mask) - # @transition(output_compartments=["dmu", "dtarget", "dSigma", "target", "mu", "modulator", "L", "mask"]) - # @staticmethod @compilable def reset(self): ## reset core components/statistics - _shape = (self.batch_size, self.shape[0]) + self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member + + @compilable + def batched_reset(self, batch_size): + _shape = (batch_size, self.shape[0]) if len(self.shape) > 1: - _shape = (self.batch_size, self.shape[0], self.shape[1], self.shape[2]) + _shape = (batch_size, self.shape[0], self.shape[1], self.shape[2]) restVals = jnp.zeros(_shape) dmu = restVals dtarget = restVals @@ -125,8 +130,10 @@ def reset(self): ## reset core components/statistics self.dmu.set(dmu) self.dtarget.set(dtarget) self.dSigma.set(dSigma) - self.target.set(target) - self.mu.set(mu) + if not self.target.targeted: + self.target.set(target) + if not self.mu.targeted: + self.mu.set(mu) self.modulator.set(modulator) self.L.set(L) self.mask.set(mask) @@ -134,7 +141,7 @@ def reset(self): ## reset core components/statistics @classmethod def help(cls): ## component help function properties = { - "cell_type": "GaussianErrorcell - computes mismatch/error signals at " + "cell_type": "GaussianErrorCell - computes mismatch/error signals at " "each time step t (between a `target` and a prediction `mu`)" } compartment_props = { @@ -145,7 +152,7 @@ def help(cls): ## component help function "modulator": "External input modulatory/scaling signal(s)", "mask": "External binary/gating mask to apply to signals"}, "outputs": - {"L": "Local loss value computed/embodied by this error-cell", + {"L": "Local loss / free-energy value embodied by this error-cell", "dmu": "first derivative of loss w.r.t. prediction value(s)", "dSigma": "first derivative of loss w.r.t. variance/covariance value(s)", "dtarget": "first derivative of loss w.r.t. target value(s)"}, diff --git a/ngclearn/components/neurons/graded/laplacianErrorCell.py b/ngclearn/components/neurons/graded/laplacianErrorCell.py index c881372b..542c21a2 100755 --- a/ngclearn/components/neurons/graded/laplacianErrorCell.py +++ b/ngclearn/components/neurons/graded/laplacianErrorCell.py @@ -100,8 +100,12 @@ def advance_state(self, dt): ## compute Laplacian error cell output self.mask.set(mask) @compilable - def reset(self): ## reset core components/statistics - restVals = jnp.zeros((self.batch_size, self.n_units)) + def reset(self): ## reset core components/statistics + self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member + + @compilable + def batched_reset(self, batch_size): + restVals = jnp.zeros((batch_size, self.n_units)) dshift = restVals dtarget = restVals dScale = jnp.zeros(self.scale_shape) @@ -109,7 +113,7 @@ def reset(self): ## reset core components/statistics shift = restVals modulator = shift + 1. L = 0. - mask = jnp.ones((self.batch_size, self.n_units)) + mask = jnp.ones((batch_size, self.n_units)) self.dshift.set(dshift) self.dtarget.set(dtarget) diff --git a/ngclearn/components/neurons/graded/leakyNoiseCell.py b/ngclearn/components/neurons/graded/leakyNoiseCell.py index ab6245ed..40192d1c 100755 --- a/ngclearn/components/neurons/graded/leakyNoiseCell.py +++ b/ngclearn/components/neurons/graded/leakyNoiseCell.py @@ -1,5 +1,6 @@ from jax import numpy as jnp, random, jit -from ngcsimlib.logger import info +#from ngcsimlib.logger import info +from ngcsimlib import deprecate_args from ngclearn import compilable #from ngcsimlib.parser import compilable from ngclearn import Compartment #from ngcsimlib.compartment import Compartment from ngclearn.components.jaxComponent import JaxComponent @@ -65,6 +66,7 @@ class LeakyNoiseCell(JaxComponent): ## Real-valued, leaky noise cell leak_scale: degree to which membrane leak should be scaled (Default: 1) """ + @deprecate_args(sigma_rec="sigma_pre") def __init__( self, name, n_units, tau_x, act_fx="relu", integration_type="euler", batch_size=1, sigma_pre=0.1, sigma_post=0.1, leak_scale=1., shape=None, **kwargs @@ -127,13 +129,19 @@ def advance_state(self, t, dt): self.r_prime.set(r_prime) @compilable - def reset(self): - _shape = (self.batch_size, self.shape[0]) + def reset(self): ## reset core components/statistics + self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member + + @compilable + def batched_reset(self, batch_size): + _shape = (batch_size, self.shape[0]) if len(self.shape) > 1: - _shape = (self.batch_size, self.shape[0], self.shape[1], self.shape[2]) + _shape = (batch_size, self.shape[0], self.shape[1], self.shape[2]) restVals = jnp.zeros(_shape) - self.j_input.set(restVals) - self.j_recurrent.set(restVals) + if not self.j_input.targeted: + self.j_input.set(restVals) + if not self.j_recurrent.targeted: + self.j_recurrent.set(restVals) self.x.set(restVals) self.r.set(restVals) self.r_prime.set(restVals) diff --git a/ngclearn/components/neurons/graded/rateCell.py b/ngclearn/components/neurons/graded/rateCell.py index 3cf50a22..98f60325 100755 --- a/ngclearn/components/neurons/graded/rateCell.py +++ b/ngclearn/components/neurons/graded/rateCell.py @@ -252,10 +252,14 @@ def advance_state(self, dt): self.zF.set(zF) @compilable - def reset(self): #, batch_size, shape): #n_units - _shape = (self.batch_size, self.shape[0]) + def reset(self): ## reset core components/statistics + self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member + + @compilable + def batched_reset(self, batch_size): + _shape = (batch_size, self.shape[0]) if len(self.shape) > 1: - _shape = (self.batch_size, self.shape[0], self.shape[1], self.shape[2]) + _shape = (batch_size, self.shape[0], self.shape[1], self.shape[2]) restVals = jnp.zeros(_shape) self.j.set(restVals) self.j_td.set(restVals) diff --git a/ngclearn/components/neurons/spiking/WTASCell.py b/ngclearn/components/neurons/spiking/WTASCell.py index b4602c74..71721ba4 100755 --- a/ngclearn/components/neurons/spiking/WTASCell.py +++ b/ngclearn/components/neurons/spiking/WTASCell.py @@ -50,7 +50,16 @@ class WTASCell(JaxComponent): ## winner-take-all spiking cell @deprecate_args(thrBase="thr_base") def __init__( - self, name, n_units, tau_m, resist_m=1., thr_base=0.4, thr_gain=0.002, refract_time=0., thr_jitter=0.05, + self, + name, + n_units, + tau_m, + resist_m=1., + thr_base=0.4, + thr_gain=0.002, + refract_time=0., + thr_jitter=0.05, + batch_size=1, **kwargs ): super().__init__(name, **kwargs) @@ -63,7 +72,7 @@ def __init__( self.refract_T = refract_time ## Layer Size Setup - self.batch_size = 1 + self.batch_size = batch_size self.n_units = n_units ## base threshold setup @@ -113,15 +122,6 @@ def reset(self): self.rfr.set(restVals + self.refract_T) self.tols.set(restVals) - # def save(self, directory, **kwargs): - # file_name = directory + "/" + self.name + ".npz" - # jnp.savez(file_name, threshold=self.thr.get()) - # - # def load(self, directory, seeded=False, **kwargs): - # file_name = directory + "/" + self.name + ".npz" - # data = jnp.load(file_name) - # self.thr.set( data['threshold'] ) - @classmethod def help(cls): ## component help function properties = { diff --git a/ngclearn/components/neurons/spiking/hodgkinHuxleyCell.py b/ngclearn/components/neurons/spiking/hodgkinHuxleyCell.py index 87ec823b..f71d8c29 100644 --- a/ngclearn/components/neurons/spiking/hodgkinHuxleyCell.py +++ b/ngclearn/components/neurons/spiking/hodgkinHuxleyCell.py @@ -38,7 +38,7 @@ def dx_dt(t, x, params): class HodgkinHuxleyCell(JaxComponent): ## Hodgkin-Huxley spiking cell """ - A spiking cell based the Hodgkin-Huxley (H-H) 1952 set of dynamics for describing the ionic mechanisms that underwrite + A spiking cell based on the Hodgkin-Huxley (H-H) 1952 set of dynamics for describing the ionic mechanisms that underwrite the initiation and propagation of action potentials within a (giant) squid axon. The four differential equations for adjusting this specific cell @@ -64,11 +64,9 @@ class HodgkinHuxleyCell(JaxComponent): ## Hodgkin-Huxley spiking cell | tols - time-of-last-spike | References: - | Hodgkin, Alan L., and Andrew F. Huxley. "A quantitative description of membrane current and its application to - | conduction and excitation in nerve." The Journal of physiology 117.4 (1952): 500. + | Hodgkin, Alan L., and Andrew F. Huxley. "A quantitative description of membrane current and its application to conduction and excitation in nerve." The Journal of physiology 117.4 (1952): 500. | - | Kistler, Werner M., Wulfram Gerstner, and J. Leo van Hemmen. "Reduction of the Hodgkin-Huxley equations to a - | single-variable threshold model." Neural computation 9.5 (1997): 1015-1045. + | Kistler, Werner M., Wulfram Gerstner, and J. Leo van Hemmen. "Reduction of the Hodgkin-Huxley equations to a single-variable threshold model." Neural computation 9.5 (1997): 1015-1045. Args: name: the string name of this cell diff --git a/ngclearn/components/synapses/__init__.py b/ngclearn/components/synapses/__init__.py index 95bf3f70..28bd001b 100644 --- a/ngclearn/components/synapses/__init__.py +++ b/ngclearn/components/synapses/__init__.py @@ -8,11 +8,15 @@ from .alphaSynapse import AlphaSynapse ## dense synaptic components -# from .hebbian.hebbianSynapse import HebbianSynapse +from .hebbian.hebbianSynapse import HebbianSynapse +from .hebbian.STDPSynapse import STDPSynapse from .hebbian.traceSTDPSynapse import TraceSTDPSynapse from .hebbian.expSTDPSynapse import ExpSTDPSynapse from .hebbian.eventSTDPSynapse import EventSTDPSynapse from .hebbian.BCMSynapse import BCMSynapse +from .mpsSynapse import MPSSynapse +### dense competitive synaptic components/elements +from .competitive.SOMSynapse import SOMSynapse ## conv/deconv synaptic components from .convolution.convSynapse import ConvSynapse diff --git a/ngclearn/components/synapses/competitive/ART2ASynapse.py b/ngclearn/components/synapses/competitive/ART2ASynapse.py new file mode 100644 index 00000000..de0a9f4c --- /dev/null +++ b/ngclearn/components/synapses/competitive/ART2ASynapse.py @@ -0,0 +1,246 @@ +from jax import random, numpy as jnp, jit, nn +from functools import partial +from ngclearn import compilable +from ngclearn import Compartment +from ngclearn.utils.model_utils import softmax, bkwta + +from ngclearn.components.synapses.denseSynapse import DenseSynapse + +@partial(jit, static_argnums=[1]) +def _normalize(x_in, norm_fx=0): + if norm_fx == 1: + xmin = jnp.min(x, axis=1, keepdims=True) + xmax = jnp.max(x, axis=1, keepdims=True) + x = (x_in - xmin)/(xmax - xmin) + else: + x = x_in / jnp.linalg.norm(x_in, ord=2, axis=1, keepdims=True) + return x + +class ART2ASynapse(DenseSynapse): # Adaptive resonance theory (ART) 2A synaptic cable + """ + A synaptic cable that emulates a simplified form of adaptive resonance theory (ART) + adapted for continuous input signals (specifically, the ART2A-C model that handles + real-valued input values). + + | --- Synapse Compartments: --- + | inputs - input (takes in external signals) + | outputs - output signals (transformation induced by synapses) + | weights - current value matrix of synaptic efficacies + | i_tick - current internal tick / marker (gets incremented by 1 for each call to `evolve`) + | eta - current learning rate value + | key - JAX PRNG key + | --- Synaptic Plasticity Compartments: --- + | inputs - pre-synaptic signal/value to drive 1st term of ART2A update (x) + | outputs - post-synaptic signal/value to drive 2nd term of ART2A update (y) + | dWeights - current delta matrix containing changes to be applied to synapses + + | References: + | Carpenter, Gail A., and Stephen Grossberg. "ART 2: Self-organization of stable category + | recognition codes for analog input patterns." Applied optics 26.23 (1987): 4919-4930. + | + | Ororbia, Alexander G. "Continual competitive memory: A neural system for online task-free + | lifelong learning." arXiv preprint arXiv:2106.13300 (2021). + + Args: + name: the string name of this cell + + shape: tuple specifying shape of this synaptic cable (usually a 2-tuple with number of + inputs by number of outputs) + + eta: (initial) learning rate / step-size for this ART2A model (initial condition value for `eta`) + + eta_decrement: constant value to decrease `eta` by each call to this synapse's `evolve()`, i.e., + this triggers a linear schedule for decreasing `eta` by (Default: 0) + + vigilance: vigilance parameter to decide if a memory vector is updated (rho) + + weight_init: a kernel to drive initialization of this synaptic cable's values; + typically a tuple with 1st element as a string calling the name of + initialization to use + + resist_scale: a fixed scaling factor to apply to synaptic transform (Default: 1.) + + p_conn: probability of a connection existing (default: 1.); setting + this to < 1. will result in a sparser synaptic structure + """ + + def __init__( + self, + name, + shape, ## determines memory matrix size + eta=0.05, ## learning rate + eta_decrement=0., ## linear scheduled decrement over eta + vigilance=0.3, ## vigilance parameter (rho) + weight_init=None, + resist_scale=1., + p_conn=1., + batch_size=1, + **kwargs + ): + super().__init__( + name, shape, weight_init, None, resist_scale, p_conn, batch_size=batch_size, **kwargs + ) + + ### Synapse and ART-2A hyper-parameters + self.K = 1 ## number of winners for bmu calculation + self.norm_fx = 0 ## 0 -> normalize via norm, 1 -> complement coding (min-max rescale) + + self.shape = shape ## shape of synaptic efficacy matrix + self.initial_eta = eta + self.eta_decr = eta_decrement ## linear decrease to iteratively update eta by (each "tick") + self.vigilance = vigilance ## (rho) + + ## ART-2A Compartment setup + self.xprobe = Compartment(jnp.zeros((batch_size, shape[0]))) + self.eta = Compartment(jnp.zeros((1, 1)) + self.initial_eta, display_name="Dynamic step size") + self.i_tick = Compartment(jnp.zeros((1, 1))) + #self.bmu = Compartment(jnp.zeros((1, 1)), display_name="Best matching unit mask") + self.dWeights = Compartment(self.weights.get() * 0) + self.misses = Compartment(jnp.zeros((batch_size, 1))) ## marker for non-resonant patterns in a batch + + self.weights.set(self.weights.get() * 0) + self.used = Compartment(jnp.zeros((1, shape[1]))) ## marks if memory slot used + + def insert(self, x, idx): ## manual memory insertion co-routine + W = self.weights.get() + z_m = jnp.expand_dims(nn.one_hot(idx, W.shape[1]), axis=0) + dW = (W * 0 + x.T) * z_m + W = W + dW + self.weights.set(W) + self.used.set(((self.used.get() + z_m) > 0.) * 1.) + + def grow(self, n_memories): ## grow out memory matrix by fixed amount + W = self.weights.get() + used = self.used.get() + ## expand memory matrix by a fixed set of empty memory slots + W = jnp.concat([W, jnp.zeros((W.shape[0], n_memories))], axis=1) + n_unused = jnp.zeros((1, n_memories)) + used = jnp.concat([used, n_unused], axis=1) + #print("used: ", used.shape) + self.used.set(used) + self.weights.set(W) + self.dWeights.set(W * 0) + self.shape = self.weights.get().shape + + @compilable + def consolidate(self): ## memory consolition co-routine (for non-resonant signals) + n_used = int(jnp.sum(self.used.get())) ## number unused slots left + x = self.xprobe.get() + W = self.weights.get() + nonresonants = self.misses.get() + ## we project non-resonant memories to empty slots in memory W + S = jnp.eye(x.shape[0], self.shape[1], k=n_used) + dWstore = jnp.matmul((x * nonresonants).T, S) + W = W + dWstore ## Hebbian update to memory + ## re-compute number of used slots post-consolidation + nW = jnp.linalg.norm(W, ord=2, axis=0, keepdims=True) + used = (nW > 0.) * 1 + + self.weights.set(W) + self.used.set(used) + ## else, currently discard un-absorbed/non-resonant patterns + ## can add a function that "grows" out block matrix by a chunk (to control growth) + ## TODO: add pruning mechanism for low-usage slots + + @compilable + def advance_state(self): ## forward-inference step of ART2A + x_in = self.inputs.get() + W = self.weights.get() ## get (transposed) memory matrix + used = self.used.get() + + x = _normalize(x_in, norm_fx=self.norm_fx) + self.xprobe.set(x) + sims = jnp.matmul(x, W) ## compute similarities (parallel dot products) + ## we correct activities by masking out unused slots + sims_min = jnp.amin(sims, axis=1, keepdims=True) + sims = sims * used + (1. - used) * (sims_min - 1.) + z_winners = sims * bkwta(sims, nWTA=self.K) ## get winner mask (hidden layer) + self.outputs.set(z_winners) + + @compilable + def evolve(self, t, dt): ## competitive Hebbian update step of ART2A + W = self.weights.get() ## D x Z + x = self.xprobe.get() ## B x D + z_winners = self.outputs.get() ## B x Z + eta = self.eta.get() + ## Note: we refactor ART update into a leaky integrator equation: + ## W = W * (1 - b) + dW * b = W + b * (-W + dW); b = eta + + ## for resonant patterns, we perform a Hebbian storage update + hits = (z_winners >= self.vigilance) * 1. ## B x Z + m = (jnp.sum(hits, axis=1, keepdims=True) > 0.) * 1. ## B x 1 + wnew = (-jnp.matmul(z_winners, W.T) + x) * m ## B x D + dW = jnp.matmul(wnew.T, hits) ## D x Z ## adjustment matrix + W = W + dW * eta ## D x Z ## do a step of Hebbian ascent + nonresonants = 1. - m ## mark non-resonant patterns in batch + + ## NOTE: is this post-weight-update normalization needed? + #nW = jnp.linalg.norm(W, ord=2, axis=0, keepdims=True) + #used = (nW > 0.) * 1 + #mz = (jnp.sum(hits, axis=0, keepdims=True) > 0.) * 1. + #W = W / (nW * mz + (1. - mz)) + + self.weights.set(W) + self.misses.set(nonresonants) ## store unused/non-resonant pattern mas + + #tmp_key, *subkeys = random.split(self.key.get(), 3) + #self.key.set(tmp_key) + ## synaptic update noise + #eps = random.normal(subkeys[0], W.shape) ## TODO: is this same size as tensor? or scalar? + + ## update learning rate eta + eta_tp1 = jnp.maximum(1e-5, eta - self.eta_decr) + self.eta.set(eta_tp1) + + self.i_tick.set(self.i_tick.get() + 1) + + @compilable + def reset(self): + preVals = jnp.zeros((self.batch_size.get(), self.shape.get()[0])) + postVals = jnp.zeros((self.batch_size.get(), self.shape.get()[1])) + + if not self.inputs.targeted: + self.inputs.set(preVals) + self.outputs.set(postVals) + self.xprobe.set(preVals) + #self.misses.set(jnp.zeros((self.batch_size.get(), 1))) + self.misses.set(self.misses.get() * 0) + self.dWeights.set(jnp.zeros(self.shape.get())) + + @classmethod + def help(cls): ## component help function + properties = { + "synapse_type": "ART2ASynapse - performs an adaptable synaptic transformation of inputs to produce output " + "signals; synapses are adjusted via competitive Hebbian learning in accordance with " + "adaptive resonance theory (2A)" + } + compartment_props = { + "input_compartments": + {"inputs": "Takes in external input signal values", + "key": "JAX PRNG key"}, + "parameter_compartments": + {"weights": "Synapse efficacy/strength parameter values"}, + "output_compartments": + {"outputs": "Output of synaptic transformation"}, + } + hyperparams = { + "shape": "Shape of synaptic weight value matrix; number inputs x number outputs", + "batch_size": "Batch size dimension of this component", + "weight_init": "Initialization conditions for synaptic weight (W) values", + "resist_scale": "Resistance level scaling factor (applied to output of transformation)", + "p_conn": "Probability of a connection existing (otherwise, it is masked to zero)", + "eta": "Global learning rate", + "eta_decrement": "Constant amount to decrease global learning by each call to `evolve`" + } + info = {cls.__name__: properties, + "compartments": compartment_props, + "dynamics": "outputs = [bmu_mask] ;" + "dW = ART2A competitive Hebbian update", + "hyperparameters": hyperparams} + return info + +# if __name__ == '__main__': +# from ngcsimlib.context import Context +# with Context("Bar") as bar: +# Wab = ART2ASynapse("Wab", (2, 3), 4, 4, 1.) +# print(Wab) diff --git a/ngclearn/components/synapses/competitive/SOMSynapse.py b/ngclearn/components/synapses/competitive/SOMSynapse.py new file mode 100644 index 00000000..c95a48d4 --- /dev/null +++ b/ngclearn/components/synapses/competitive/SOMSynapse.py @@ -0,0 +1,377 @@ +import jax +from jax import random, numpy as jnp, jit +from ngclearn import compilable #from ngcsimlib.parser import compilable +from ngclearn import Compartment #from ngcsimlib.compartment import Compartment +from ngclearn.utils.model_utils import softmax + +from ngclearn.components.synapses.denseSynapse import DenseSynapse + +def _gaussian_kernel(dist, sigma): ## Gaussian neighborhood function + density = jnp.exp(-jnp.power(dist, 2) / (2 * (sigma ** 2))) # n_units x 1 + return density + +def _ricker_marr_kernel(dist, sigma): ## mexican hat neighborhood function + ## can reform Ricker-Marr in terms of a function of a Gaussian density + gauss_density = _gaussian_kernel(dist, sigma) + density = gauss_density * (1. - (jnp.power(dist, 2) / (sigma ** 2))) + # NOTE: Since the mexican hat density can produce negative values, + # we clip to 0 to avoid this as negative density messes up SOM learning + return jnp.maximum(density, 0.) + +def _euclidean_dist(a: jax.Array, b: jax.Array): + """ Compute batch-wise Euclidean (L2) distance between two sets of vectors a and b + + Args: + a (jax.Array): (batch_size, n_inputs) + b (jax.Array): (n_inputs, n_units_xy) n_units here is height * width of SOM topology + + Returns: + d (jax.Array): (batch_size, n_units_xy) distance of each input pattern to each SOM unit + delta (jax.Array): (batch_size, n_inputs, n_units_xy) raw differences between each input pattern and each SOM unit + """ + # (B, I, 1) - (1, I, U) -> (B, I, U) + delta = jnp.expand_dims(a, axis=-1) - jnp.expand_dims(b, axis=0) + # (B, U) # norm across n_inputs dimension + d = jnp.linalg.norm(delta, axis=1) + return d, delta + +def _manhattan_dist(a: jax.Array, b:jax.Array): + """Manhattan (L1) distance + + Args: + a (jax.Array): (batch_size, n_inputs) + b (jax.Array): (n_inputs, n_units_xy) n_units here is height * width of SOM topology + + Returns: + d (jax.Array): (batch_size, n_units_xy) distance of each input pattern to each SOM unit + delta (jax.Array): (batch_size, n_inputs, n_units_xy) raw differences between each input pattern and each SOM unit + """ + # (B, I, 1) - (1, I, U) -> (B, I, U) + delta = jnp.expand_dims(a, axis=-1) - jnp.expand_dims(b, axis=0) + # (B, U) # norm across n_inputs dimension + d = jnp.linalg.norm(delta, ord=1, axis=1) + return d, delta + +def _cosine_dist(a: jax.Array, b: jax.Array): + """Cosine-similarity distance + + Args: + a (jax.Array): (batch_size, n_inputs) + b (jax.Array): (n_inputs, n_units_xy) n_units here is height * width of SOM topology + + Returns: + d (jax.Array): (batch_size, n_units_xy) distance of each input pattern to each SOM unit + delta (jax.Array): (batch_size, n_inputs, n_units_xy) raw differences between each input pattern and each SOM unit + """ + # (B, I, 1) - (1, I, U) -> (B, I, U) + delta = jnp.expand_dims(a, axis=-1) - jnp.expand_dims(b, axis=0) + + # Viet: Original code + # d = 1. - (jnp.matmul(a.T, b) / (jnp.linalg.norm(a, axis=0) * jnp.linalg.norm(b, axis=0))) + + # Viet: new code for cosine similarity distance (similar code but more readable) + a_norm = jnp.linalg.norm(a, axis=1, keepdims=True) # (B, 1) + b_norm = jnp.linalg.norm(b, axis=0, keepdims=True) # (1, U) + # (I, U) / (B, 1) * (1, U) = (B, U) = (B, I) + cosine_similarity = a @ b / (a_norm * b_norm) # (B, U) + d = 1. - cosine_similarity # convert similarity to distance + return d, delta + + +class SOMSynapse(DenseSynapse): # Self-organizing map (SOM) synaptic cable + """ + A synaptic cable that emulates a self-organizing map (or Kohonen map) that is adapted via + competitive Hebbian learning. Many of this synapses internal compartments house dynamically-updated + values for learning elements such as the SOM's neighborhood radius and learning rate. + + Mathematically, a synaptic update performed according to SOM theory is: + | Delta W_{ij} = (x.T - W) * n(BMU) * eta + | where n(BMU) is a neighborhood weighting function centered around (topological) coordinates of BMU + | where x is vector of pre-synaptic inputs, W is SOM's synaptic matrix, and BMU is best-matching unit for x + + | --- Synapse Compartments: --- + | inputs - input (takes in external signals) + | outputs - output signals (transformation induced by synapses) + | weights - current value matrix of synaptic efficacies + | bmu - current best-matching unit (BMU), based on current inputs + | delta - current differences between inputs and each weight vector of this SOM's synaptic matrix + | i_tick - current internal tick / marker (gets incremented by 1 for each call to `evolve`) + | eta - current learning rate value + | radius - current radius value to control neighborhood function + | key - JAX PRNG key + | --- Synaptic Plasticity Compartments: --- + | inputs - pre-synaptic signal/value to drive 1st term of SOM update (x) + | outputs - post-synaptic signal/value to drive 2nd term of SOM update (y) + | neighbor_weights - topology weighting applied to synaptic adjustments + | dWeights - current delta matrix containing changes to be applied to synapses + + | References: + | Kohonen, Teuvo. "The self-organizing map." Proceedings of the IEEE 78.9 (2002): 1464-1480. + + Args: + name: the string name of this cell + + n_inputs: number of input units to this SOM + + n_units_x: number of output units along length of rectangular topology of this SOM + + n_units_y: number of output units along width of rectangular topology of this SOM + + eta: (initial) learning rate / step-size for this SOM (initial condition value for `eta`) + + distance_function: string specifying distance function to use for finding best-matching units (BMUs) + (Default: "euclidean"). + usage guide: + "euclidean" = use L2 / Euclidean distance + "manhattan" = use L1 / Manhattan / taxi-cab distance + "cosine" = use cosine-similarity distance + + neighbor_function: string specifying neighborhood function to compute approximate topology weighting across + units in topology (based on BMU) (Default: "gaussian"). + usage guide: + "gaussian" = use Gaussian kernel + "ricker" = use Mexican-hat / Ricker-Marr kernel + + weight_init: a kernel to drive initialization of this synaptic cable's values; + typically a tuple with 1st element as a string calling the name of + initialization to use + + resist_scale: a fixed scaling factor to apply to synaptic transform + (Default: 1.), i.e., yields: out = ((W * Rscale) * in) + + p_conn: probability of a connection existing (default: 1.); setting + this to < 1. will result in a sparser synaptic structure + """ + + def __init__( + self, + name, + n_inputs, + n_units_x, ## num units along width of SOM rectangular topology + n_units_y, ## num units along length of SOM rectangular topology + eta=0.5, ## learning rate + distance_function="euclidean", + neighbor_function="gaussian", + weight_init=None, + resist_scale=1., + p_conn=1., + batch_size=1, + **kwargs + ): + shape = (n_inputs, n_units_x * n_units_y) + super().__init__( + name, shape, weight_init, None, resist_scale, p_conn, batch_size=batch_size, **kwargs + ) + + ### build (rectangular) topology coordinates + # NOTE: Viet: We might want to use np.meshgrid here instead of the for-loop approach to build coordinates + # for performance reasons. But for now, we can keep it as is for readability and clarity. + # We can optimize later if needed. + # Shape: (n_units_x * n_units_y, 2) + coords = [] + for i in range(n_units_x): + x = jnp.ones((n_units_x, 1)) * i + y = jnp.expand_dims(jnp.arange(start=0, stop=n_units_y), axis=1) + xy = jnp.concat((x, y), axis=1) + coords.append(xy) + self.coords = jnp.concat(coords, axis=0) + + ### Synapse and SOM hyper-parameters + #self.radius = radius + self.distance_function = distance_function + self.dist_fx = 0 ## default := 0 (euclidean) + if "manhattan" in distance_function: + self.dist_fx = 1 + elif "cosine" in distance_function: + self.dist_fx = 2 + self.neighbor_function = neighbor_function + self.neighbor_fx = 0 ## default := 0 (Gaussian) + if "ricker" in neighbor_function: + self.neighbor_fx = 1 ## Mexican-hat function + self.shape = shape ## shape of synaptic efficacy matrix + + ## exponential decay -> dz/dt = -kz has sol'n: z0 exp(-k t) + # self.iterations = 50000 + # self.initial_eta = eta ## alpha (in SOM-lingo) #0.5 + # self.initial_radius = jnp.maximum(n_units_x, n_units_y) / 2 #n_units_x / 2 + # self.C = self.iterations / jnp.log(self.initial_radius) + + ## exponential decay -> dz/dt = -kz has sol'n: z0 exp(-k t) + self.initial_eta = eta ## alpha (in SOM-lingo) #0.5 + self.initial_radius = jnp.maximum(n_units_x, n_units_y) / 2 + self.tau_eta = 50000 + self.tau_radius = self.tau_eta / jnp.log(self.initial_radius) ## C + + ## SOM Compartment setup + self.radius = Compartment(jnp.zeros((1, 1)) + self.initial_radius) + self.eta = Compartment(jnp.zeros((1, 1)) + self.initial_eta) + self.i_tick = Compartment(jnp.zeros((1, 1))) + # Viet: batch-aware setup + self.bmu = Compartment(jnp.zeros((self.batch_size, 1), dtype=jnp.int32)) + self.delta = Compartment(jnp.zeros((self.batch_size, shape[0], shape[1]))) + self.neighbor_weights = Compartment(jnp.zeros((self.batch_size, shape[1]))) + self.dWeights = Compartment(self.weights.get() * 0) + + def _calc_bmu(self): + """obtain index of best-matching unit (BMU) + This will compute the distance between x (batch_size, n_inputs) + and W (n_inputs, n_units_xy) + + Returns: + jax.Array: bmu and delta + """ + x = self.inputs.get() + W = self.weights.get() + if self.dist_fx == 1: ## L1 distance + d, delta = _manhattan_dist(x, W) + elif self.dist_fx == 2: ## cosine distance + d, delta = _cosine_dist(x, W) + else: ## L2 distance + d, delta = _euclidean_dist(x, W) + # Viet: BMU has to have shape (batch_size, 1) + return jnp.argmin(d, axis=1, keepdims=True), delta + + def _calc_neighborhood_weights(self): ## neighborhood function + # bmu is not a vector of indices, each one is best-matching unit for each sample in batch + bmu = self.bmu.get().reshape(-1) ## get best-matching unit per sample, flatten to (batch_size,) + coords = self.coords ## constant coordinate array + radius = self.radius.get() ## get current neighborhood radius value + coord_bmu = coords[bmu, :] # (B, 2) get coordinates of BMU for each sample in batch + # (1, n_units_xy, 2) - (B, 1, 2) -> (B, n_units_xy, 2) # get delta between coordinates of each SOM unit and BMU + delta = jnp.expand_dims(coords, axis=0) - jnp.expand_dims(coord_bmu, axis=1) + + ### neighborhood-weighting computation note: + ### internally, calculation of neighborhood weighting depends on 1st calculating + ### L2 distance in Cartesian coordinate-space, then applying the neighborhood + ### over these coordinate distance values + # (B, n_units_xy) + bmu_dist = jnp.linalg.norm(delta, axis=2) + if self.neighbor_fx == 1: ## apply Mexican-hat kernel + neighbor_weights = _ricker_marr_kernel(bmu_dist, sigma=radius) + else: ## apply Gaussian kernel + neighbor_weights = _gaussian_kernel(bmu_dist, sigma=radius) + ## TODO: add in triangular, bubble, & laplacian kernels + + # (B, n_units_xy) + return neighbor_weights + + + @compilable + def advance_state(self): ## forward-inference step of SOM + bmu_idx, delta = self._calc_bmu() + self.bmu.set(bmu_idx) ## store BMU + self.delta.set(delta) ## store delta/differences + neighbor_weights = self._calc_neighborhood_weights() + self.neighbor_weights.set(neighbor_weights) ## store neighborhood weightings + + ## compute an approximate weighted activity output for input pattern + #activity = jnp.sum(self.weights * self.resist_scale * neighbor_weights, axis=1, keepdims=True) + ### obtain weighted competitive activations (via softmax probs) + activity = softmax(neighbor_weights * self.resist_scale) + self.outputs.set(activity) + + @compilable + def evolve(self, t, dt): ## competitive Hebbian update step of SOM + # #bmu = self.bmu.get() ## best-matching unit + # delta = self.delta.get() ## deltas/differences between input & all SOM templates + # neighbor_weights = self.neighbor_weights.get() ## get neighborhood weight values + + # ## exponential decay -> dz/dt = -kz has sol'n: z0 exp(-k t) + # #t = self.i_tick.get() + # ## update radius + # r = self.radius.get() + # r = r + (-r) * (1./self.tau_radius) + # self.radius.set(r) + # ## update learning rate alpha + # a = self.eta.get() + # a = a + (-a) * (1./self.tau_eta) + # self.eta.set(a) + # # self.radius.set(self.initial_radius * jnp.exp(-self.i_tick.get() / self.C)) ## update radius + # # self.eta.set(self.initial_eta * jnp.exp(-self.i_tick.get() / self.iterations)) ## update learning rate alpha + + # dWeights = delta * neighbor_weights * self.eta.get() ## calculate change-in-synapses + # self.dWeights.set(dWeights) + # _W = self.weights.get() + dWeights ## update via competitive Hebbian rule + # self.weights.set(_W) + + # self.i_tick.set(self.i_tick.get() + 1) + + ### Viet: My batchified code + # (B, n_inputs, n_units_xy) + delta = self.delta.get() ## deltas/differences between input & all SOM templates + # (B, n_units_xy) + neighbor_weights = self.neighbor_weights.get() ## get neighborhood weight values + # NOTE: Viet: since we are doing batch mode, do we need to scale the updates by the batch size? + # update neighborhood radius + r = self.radius.get() + r = r + (-r) * (1. / self.tau_radius) + self.radius.set(r) + ## update learning rate alpha + a = self.eta.get() + a = a + (-a) * (1. / self.tau_eta) + self.eta.set(a) + # Update weights + # (B, n_inputs, n_units_xy) * (B, 1, n_units_xy) -> (B, n_inputs, n_units_xy) + dWeights = delta * jnp.expand_dims(neighbor_weights, axis=1) * self.eta.get() + # NOTE: Viet: since we are doing batch mode, we need to average the updates across the + # batch dimension + dWeights = dWeights.mean(axis=0) ## (n_inputs, n_units_xy) + self.dWeights.set(dWeights) + _W = self.weights.get() + dWeights ## update via competitive Hebbian rule + self.weights.set(_W) + # update tick. NOTE: are we ticking by batch size or 1? + self.i_tick.set(self.i_tick.get() + 1) + + + @compilable + def reset(self): + preVals = jnp.zeros((self.batch_size, self.shape[0])) + postVals = jnp.zeros((self.batch_size, self.shape[1])) + + if not self.inputs.targeted: + self.inputs.set(preVals) + self.outputs.set(postVals) + self.dWeights.set(jnp.zeros(self.shape)) + self.delta.set(jnp.zeros((self.batch_size, self.shape[0], self.shape[1]))) + self.bmu.set(jnp.zeros((self.batch_size, 1), dtype=jnp.int32)) + self.neighbor_weights.set(jnp.zeros((self.batch_size, self.shape[1]))) + + @classmethod + def help(cls): ## component help function + properties = { + "synapse_type": "SOMSynapse - performs an adaptable synaptic transformation of inputs to produce output " + "signals; synapses are adjusted via competitive Hebbian learning in accordance with a " + "Kohonen map" + } + compartment_props = { + "input_compartments": + {"inputs": "Takes in external input signal values", + "key": "JAX PRNG key"}, + "parameter_compartments": + {"weights": "Synapse efficacy/strength parameter values"}, + "output_compartments": + {"outputs": "Output of synaptic transformation", + "bmu": "Best-matching unit (BMU)"}, + } + hyperparams = { + "shape": "Shape of synaptic weight value matrix; number inputs x number outputs", + "batch_size": "Batch size dimension of this component", + "weight_init": "Initialization conditions for synaptic weight (W) values", + "resist_scale": "Resistance level scaling factor (applied to output of transformation)", + "p_conn": "Probability of a connection existing (otherwise, it is masked to zero)", + "eta": "Global learning rate", + "radius": "Radius parameter to control influence of neighborhood function", + "distance_function": "Distance function used to compute BMU" + } + info = {cls.__name__: properties, + "compartments": compartment_props, + "dynamics": "outputs = [W * alpha(bmu)] ;" + "dW = SOM competitive Hebbian update", + "hyperparameters": hyperparams} + return info + +# if __name__ == '__main__': +# from ngcsimlib.context import Context +# with Context("Bar") as bar: +# Wab = SOMSynapse("Wab", (2, 3), 4, 4, 1.) +# print(Wab) diff --git a/ngclearn/components/synapses/competitive/__init__.py b/ngclearn/components/synapses/competitive/__init__.py new file mode 100644 index 00000000..a7240441 --- /dev/null +++ b/ngclearn/components/synapses/competitive/__init__.py @@ -0,0 +1,6 @@ +from .SOMSynapse import SOMSynapse +from .hopfieldSynapse import HopfieldSynapse +from .vectorQuantizeSynapse import VectorQuantizeSynapse ## LVQ +from .ART2ASynapse import ART2ASynapse ## ART for contus inputs +## NOTE: add in ART1Synapse for processing binary/pulse values + diff --git a/ngclearn/components/synapses/competitive/hopfieldSynapse.py b/ngclearn/components/synapses/competitive/hopfieldSynapse.py new file mode 100644 index 00000000..cf22a8f9 --- /dev/null +++ b/ngclearn/components/synapses/competitive/hopfieldSynapse.py @@ -0,0 +1,230 @@ +from jax import random, numpy as jnp, jit, vmap +from ngclearn import compilable #from ngcsimlib.parser import compilable +from ngclearn import Compartment #from ngcsimlib.compartment import Compartment +from ngclearn.utils.model_utils import softmax, bkwta + +from ngclearn.components.synapses.denseSynapse import DenseSynapse + +class HopfieldSynapse(DenseSynapse): # (Modern) Hopfield synaptic cable + """ + A synaptic cable that emulates a modern Hopfield network (MHN). Note that this model has been generalized a bit, + a.l.a. NAC-Lab style, and comes equipped with two non-standard local plasticity update rules to alter the + underlying memory matrix W from scratch (or to fine-tune an existing preloaded one); note that a mixed + MHN can be created (one where initial patterns are stored but portions / elements of the + memory matrix are further adapted in accordance to a local adjustment rule). This model currently only implements + the exponential coupling/energy function. + + | --- Synapse Compartments: --- + | inputs - input probe (takes in external signals) + | outputs - output signals (retrieved memory / updated probe) + | weights - current value matrix of synaptic efficacies + | similarities - current raw similarity scores computed (pre-softmax) + | memory_weights - current similarity scores computed (post-softmax) + | i_tick - current internal tick / marker (gets incremented by 1 for each call to `evolve`) + | energy - current energy functional reading (given current clamped input probe) + | key - JAX PRNG key + | --- Synaptic Plasticity Compartments: --- + | dWeights - current delta matrix containing changes to be applied to synapses + + | References: + | Movellan, Javier R. "Contrastive Hebbian learning in the continuous Hopfield model." Connectionist models. + | Morgan Kaufmann, 1991. 10-17. + | + | Krotov, Dmitry, and John Hopfield. "Large associative memory problem in neurobiology and machine learning." + | arXiv preprint arXiv:2008.06996 (2020). + | + | Hintzman, Douglas L. "MINERVA 2: A simulation model of human memory." Behavior Research Methods, Instruments, + | & Computers 16.2 (1984): 96-101. + + Args: + name: the string name of this cell + + shape: tuple specifying shape of this synaptic cable (usually a 2-tuple + with number of inputs by number of outputs) + + eta: (initial) learning rate / step-size for this SOM (initial condition value for `eta`) + + reg_lambda: weight decay coefficient applied to Hebbian update + + beta: (inverse) temperature to control sharpness of memory similarity calculation + + initial_patterns: seed patterns to store within memory matrix (Default: None) + + update_rule: local plasticity rule to use to adjust/update memory matrix (Default: "delta"; + Currently, two rules are encoded that work - a custom delta rule (prescribed error rule) and + a custom contrastive Hebbian rule (Movellan/NAC-Lab-style) + + weight_init: a kernel to drive initialization of this synaptic cable's values; + typically a tuple with 1st element as a string calling the name of + initialization to use + + resist_scale: a fixed scaling factor to apply to synaptic transform + (Default: 1.), i.e., yields: out = ((W * Rscale) * in) + + p_conn: probability of a connection existing (default: 1.); setting + this to < 1. will result in a sparser synaptic structure + """ + + def __init__( + self, + name, + shape, + eta, + reg_lambda=0., + beta=8., + initial_patterns=None, + update_rule = "delta", ## memory plasticity rule + weight_init=None, + resist_scale=1., + p_conn=1., + batch_size=1, + **kwargs + ): + super().__init__( + name, shape, weight_init, None, resist_scale, p_conn, batch_size=batch_size, **kwargs + ) + + ### Synapse and Hopfield hyper-parameters + self.eta = eta + self.reg_lambda = reg_lambda #0.0001 ## regularization co-efficient + self.l1_lambda = 0. #0.0001 ## coefficient for L1 decay + self.beta = beta + if initial_patterns is not None: ## preload memory synaptic matrix + W = self.weights.get() + D, H = W.shape + tmp_key, *subkeys = random.split(self.key.get(), 3) + if initial_patterns.shape[1] < H: ## randomly portions of memory with stored patterns/templates + ptrs = random.permutation(subkeys[0], H) + W = jnp.concat([initial_patterns, W[:, 0:(H - initial_patterns.shape[1])]], axis=1) + W = W[:, ptrs] ## shuffle memories + self.weights.set(W) + else: ## memory is exactly the set of stored patterns/templates + self.weights.set(initial_patterns) + self.rule_fx = 2 ## Default: delta-rule + if update_rule == "contrastive": + self.rule_fx = 1 + + ## Hopfield Compartment setup + inputVals = jnp.zeros((self.batch_size, shape[0])) + simVals = jnp.zeros((self.batch_size, shape[0])) + self.inputs = Compartment(inputVals) ## input shape = output shape + self.outputs = Compartment(inputVals) ## output shape = input shape + self.similarities = Compartment(simVals) ## "hidden layer" + self.memory_weights = Compartment(simVals) + + self.energy = Compartment(jnp.zeros((1, 1)), display_name="Energy") + self.i_tick = Compartment(jnp.zeros((1, 1))) + self.dWeights = Compartment(self.weights.get() * 0) + + @compilable + def advance_state(self): ## forward-inference step of SOM + WX = self.weights.get() + probe_t = self.inputs.get() + + ## TODO: what about power/quadratic functions instead? (integrate Minerva power coupling) + sims = jnp.matmul(probe_t, WX) ## similarities (w/ xn as probe) + sims_max = jnp.max(sims, axis=1, keepdims=True) + sims = sims - sims_max + self.similarities.set(sims) ## similarities = "hidden layer" + memory_weights = softmax(sims * self.beta) + self.memory_weights.set(memory_weights) + z = memory_weights + probe_tp1 = jnp.matmul(z, WX.T) ## calc probe update + self.outputs.set(probe_tp1) + + ## Calculate (modern) Hopfield energy functional + N = WX.shape[1] ## how many neural memories are there + max_sim_value = jnp.max(self.beta * sims, axis=1, keepdims=True) + lse = max_sim_value + jnp.log(jnp.sum(jnp.exp(self.beta * sims - max_sim_value), axis=1, keepdims=True)) + term1 = -(1. / self.beta) * lse + term2 = 0.5 * jnp.expand_dims(jnp.diag(jnp.matmul(probe_t, probe_tp1.T)),axis=1) + term3 = (1. / self.beta) * jnp.log(N) + 0.5 * jnp.max(jnp.linalg.norm(WX, ord=2, axis=1) ** 2) ## C + Ex = jnp.mean(term1 + term2 + term3, axis=0, keepdims=True) #* (1. / probe_t.shape[0]) ## calc batch avg energy + self.energy.set(Ex) + + self.i_tick.set(self.i_tick.get() + 1.) ## march internal tick forward + + @compilable + def evolve(self, t, dt): ## plasticity rule for changing this Hopfield network's memory matrix + x = self.inputs.get() + x_hat = self.outputs.get() + s = self.memory_weights.get() + W = self.weights.get() + beta = self.beta + + ## TODO: make updates noisy? (perturbative) + ## TODO: also, make a perturbation-based update synapse? + if self.rule_fx == 1: ## contrastive (Movellan) Hebbian style plasticity + ## TODO: add a loop to iterative over negative term several times + ## we propagate the updated probe (negative) through memory to get a negative weighted state + sims_hat = jnp.matmul(x_hat, W) + s_hat = softmax(sims_hat - jnp.max(sims_hat, axis=1, keepdims=True) * beta) #s_hat = bkwta(s_hat, nWTA=1) + ## positive Hebbian prod of probe+pos-state against negative Hebbian prod of updated-probe+neg-state + term1 = (x.T @ s) + term2 = -(x_hat.T @ s_hat) + dW = term1 + term2 + #elif self.rule_fx == XX: ## deriv of energy w.r.t. memory W rule + # dW = x.T @ -s + else: ## delta-rule (prescribed error rule) is the default + dW = (x - x_hat).T @ s ## (deriv of MSE w.r.t. x_hat/updated probe) + Ns = x.shape[0] ## get batch size + dW = dW * (1./ Ns) ## we average batch updates + + ## TODO: add a term that checks if we need to append to memory W + W = W + dW * self.eta - W * self.reg_lambda - jnp.sign(W) * self.l1_lambda ## actually adjust synaptic efficacies + + self.dWeights.set(dW) + self.weights.set(W) + + @compilable + def reset(self): + inputVals = jnp.zeros((self.batch_size.get(), self.shape.get()[0])) + outputVals = jnp.zeros((self.batch_size.get(), self.shape.get()[1])) + + if not self.inputs.targeted: + self.inputs.set(inputVals) + self.outputs.set(inputVals) + self.similarities.set(outputVals) + self.memory_weights.set(outputVals) + self.energy.set(self.energy.get() * 0) + self.dWeights.set(jnp.zeros(self.shape.get())) + + @classmethod + def help(cls): ## component help function + properties = { + "synapse_type": "HopfieldSynapse - performs an adaptable synaptic transformation of inputs to produce output " + "signals; synapses are adjusted via Hebbian learning in accordance with a Hopfield network" + } + compartment_props = { + "input_compartments": + {"inputs": "Takes in external input signal values", + "key": "JAX PRNG key"}, + "parameter_compartments": + {"weights": "Synapse efficacy/strength parameter values"}, + "output_compartments": + {"outputs": "Output of synaptic transformation"} + } + hyperparams = { + "shape": "Shape of synaptic weight value matrix; number inputs x number outputs", + "batch_size": "Batch size dimension of this component", + "weight_init": "Initialization conditions for synaptic weight (W) values", + "resist_scale": "Resistance level scaling factor (applied to output of transformation)", + "p_conn": "Probability of a connection existing (otherwise, it is masked to zero)", + "eta": "Global learning rate (to control update to memory matrix)", + "beta": "Inverse temperature (controls softmax sharpness", + "reg_lambda": "Weight decay coefficient to apply to local memory matrix updates", + "update_rule": "What type of rule to use to update memory matrix (locally)", + "initial_patterns": "Matrix containing a series of concatenated vectors to store into memory explicitly", + } + info = {cls.__name__: properties, + "compartments": compartment_props, + "dynamics": "outputs = Hopfield memory retrieval ;" + "dW = Hopfield Hebbian update", + "hyperparameters": hyperparams} + return info + +# if __name__ == '__main__': +# from ngcsimlib.context import Context +# with Context("Bar") as bar: +# Wab = HopfieldSynapse("Wab", (2, 3), 4, 4, 1.) +# print(Wab) diff --git a/ngclearn/components/synapses/competitive/vectorQuantizeSynapse.py b/ngclearn/components/synapses/competitive/vectorQuantizeSynapse.py new file mode 100644 index 00000000..37bea309 --- /dev/null +++ b/ngclearn/components/synapses/competitive/vectorQuantizeSynapse.py @@ -0,0 +1,287 @@ +from jax import random, numpy as jnp, jit +from ngclearn import compilable #from ngcsimlib.parser import compilable +from ngclearn import Compartment #from ngcsimlib.compartment import Compartment +from ngclearn.utils.model_utils import softmax, bkwta #, chebyshev_norm + +from ngclearn.components.synapses.denseSynapse import DenseSynapse + +def _gaussian_kernel(dist, sigma): ## Gaussian weighting function + density = jnp.exp(-jnp.power(dist, 2) / (2 * (sigma ** 2))) # n_units x 1 + return density + +class VectorQuantizeSynapse(DenseSynapse): # Vector quantization (VQ) synaptic cable + """ + A synaptic cable that emulates a vector quantization memory model (the base case of this + model is referred to as "learning vector quantization"; LVQ). + + | --- Synapse Compartments: --- + | inputs - input (takes in external signals) + | labels - label input (optional) + | outputs - output signals (transformation induced by synapses) + | weights - current value matrix of synaptic efficacies + | label_weights - current value of matrix label efficacies (if this VQ is supervised) + | i_tick - current internal tick / marker (gets incremented by 1 for each call to `evolve`) + | eta - current learning rate value + | key - JAX PRNG key + | --- Synaptic Plasticity Compartments: --- + | inputs - pre-synaptic signal/value to drive 1st term of VQ update (x) + | outputs - post-synaptic signal/value to drive 2nd term of VQ update (y) + | labels - (optional) pre-synaptic signal to drive 1st term of VQ update to label matrix + | dWeights - current delta matrix containing changes to be applied to synapses + + | References: + | Somervuo, Panu, and Teuvo Kohonen. "Self-organizing maps and learning vector quantization for + | feature sequences." Neural Processing Letters 10.2 (1999): 151-159. + | + | Kohonen, Teuvo. "The self-organizing map." Proceedings of the IEEE 78.9 (2002): 1464-1480. + | + | Ororbia, Alexander G. "Continual competitive memory: A neural system for online task-free + | lifelong learning." arXiv preprint arXiv:2106.13300 (2021). + + Args: + name: the string name of this cell + + shape: tuple specifying shape of this synaptic cable (usually a 2-tuple with number of + inputs by number of outputs) + + eta: (initial) learning rate / step-size for this VQ model (initial condition value for `eta`) + + eta_decrement: a constant value to linearly decrease `eta` by per synaptic update + (Default: 0, which disables this) + + syn_decay: a synaptic weight (L2) decay to apply to synapses per update + + w_bound: upper soft bound to enforce over synapses post-update (Default: 0, which disables this scaling term) + + distance_function: tuple specifying distance function and its order for computing best-matching units (BMUs) + (Default: ("minkowski", 2)). + usage guide: + ("minkowski", 2) or ("euclidean", ?) => use L2 norm (Euclidean) distance; + ("minkowski", 1) or ("manhattan", ?) => use L1 norm (taxi-cab/city-block) distance; + ("minkowksi", jnp.inf) or ("chebyshev", ?) => use Chebyshev distance; + ("minkowski", p > 2) => use a Minkowski distance of p-th order + + label_dim: dimensionality of label neurons (corresponding to each memory/prototype); note this is + inactive/unused if <= 0 (Default: 0) + + initial_patterns: a tuple containing data vectors (and labels) to initialize code-book by; + note if `label_dim` <= 0, then only first element of tuple will be used (Default: None) + + langevin_noise_scale: scale factor to control degree to which Langevin sampling noise is + applied to a given synaptic weight update (Default: 0, which disables this) + + weight_init: a kernel to drive initialization of this synaptic cable's values; + typically a tuple with 1st element as a string calling the name of + initialization to use + + resist_scale: a fixed scaling factor to apply to synaptic transform + (Default: 1.), i.e., yields: out = ((W * Rscale) * in) + + p_conn: probability of a connection existing (default: 1.); setting + this to < 1. will result in a sparser synaptic structure + """ + + def __init__( + self, + name, + shape, ## determines codebook size + eta=0.3, ## learning rate + eta_decrement=0.00001, ## learning rate linear decrease (per update) + syn_decay=0., ## weight decay term + w_bound=0., + distance_function=("minkowski", 2), + label_dim=0, ## if > 0, then this becomes supervised LVQ(1) + initial_patterns=None, ## possible class-based prototypes to init by + langevin_noise_scale=0., ## scale of Langevin noise to apply to updates + weight_init=None, + resist_scale=1., + p_conn=1., + batch_size=1, + **kwargs + ): + super().__init__( + name, shape, weight_init, None, resist_scale, p_conn, batch_size=batch_size, **kwargs + ) + + ### Synapse / VQ hyper-parameters + self.label_dim = label_dim + self.K = 1 ## number of winners (for a bmu) + dist_fun, dist_order = distance_function ## Default: ("minkowski", 2) -> Euclidean + if "euclidean" in dist_fun.lower(): + dist_order = 2 + elif "manhattan" in dist_fun.lower(): + dist_order = 1 + elif "chebyshev" in dist_fun.lower(): + dist_order = jnp.inf + self.dist_order = dist_order ## set distance order p + + self.shape = shape ## shape of synaptic efficacy matrix + self.initial_eta = eta + self.eta_decr = eta_decrement #0.001 + self.syn_decay = syn_decay + self.w_bound = w_bound ## soft synaptic value bound (on magnitude) + self.zeta = langevin_noise_scale ## Langevin dampening factor + + ## VQ Compartment setup + label_syn_init = labels_init = jnp.zeros((1, 1)) + if self.label_dim > 0: ## do we set up label memory matrix? + label_syn_init = jnp.zeros((label_dim, self.shape[1])) + labels_init = jnp.zeros((self.batch_size, self.label_dim)) + self.labels = Compartment(labels_init, display_name="Label Units") + self.pred_labels = Compartment(labels_init, display_name="Predicted Label Values") + self.label_weights = Compartment(label_syn_init, display_name="Label Synapses / Memory") + self.eta = Compartment(jnp.zeros((1, 1)) + self.initial_eta, display_name="Dynamic step size") + self.i_tick = Compartment(jnp.zeros((1, 1))) + self.dWeights = Compartment(self.weights.get() * 0) + + if initial_patterns is not None: ## preload memory synaptic matrix + initX, initY = initial_patterns + W = self.weights.get() + D, H = W.shape + tmp_key, *subkeys = random.split(self.key.get(), 3) + if initX.shape[1] < H: ## randomly portions of memory with stored patterns/templates + ptrs = random.permutation(subkeys[0], H) + W = jnp.concat([initX, W[:, 0:(H - initX.shape[1])]], axis=1) + W = W[:, ptrs] ## shuffle memories + self.weights.set(W) + if self.label_dim > 0: ## do we preload label matrix? + Wy = self.label_weights.get() + Wy = jnp.concat([initY, Wy[:, 0:(H - initX.shape[1])]], axis=1) + Wy = Wy[:, ptrs] ## shuffle memories + self.label_weights.set(Wy) + else: ## memory is exactly the set of stored patterns/templates + self.weights.set(initX) + if self.label_dim > 0: ## do we preload label matrix? + self.label_weights.set(initY) + @compilable + def advance_state(self): ## forward-inference step of VQ + x_in = self.inputs.get() + x_in = x_in / jnp.linalg.norm(x_in, axis=1, keepdims=True) ## NOTE: we normalize input patterns (?) + self.inputs.set(x_in) + W = self.weights.get().T ## get (transposed) memory matrix + + ### We do some 3D tensor math to handle a batch of predictions that need to be made + ### B = batch-size, D = embedding/input dim, C = number classes, N = number of memories + _W = jnp.expand_dims(W, axis=0) ## 3D tensor format of memory (1 x N x C) + _x_in = jnp.expand_dims(x_in, axis=1) ## 3D projection of input signals (B x 1 x D) + D = _x_in - _W ## compute 3D batched delta tensor (B x N x D) + + ## now apply distance function measuremnt over 3D tensor of deltas + ## get batched (negative) distance measurements + dist = jnp.linalg.norm(D, ord=self.dist_order, axis=2, keepdims=True) ## (B x N x 1) + dist = -jnp.squeeze(dist, axis=2) ## (B x N) (negative distance to find minimal vals) + + ## now get K winners per sample in batch + #values, indices = lax.top_k(dist, K) + bmu_mask = bkwta(dist, nWTA=self.K) + self.outputs.set(bmu_mask) + if self.label_dim > 0: ## store a label prediction (if applicable) + pred_labels = jnp.matmul(bmu_mask, self.label_weights.get().T) + self.pred_labels.set(pred_labels) + + @compilable + def evolve(self, t, dt): ## competitive Hebbian update step of VQ + W = self.weights.get() + x_in = self.inputs.get() + z_out = self.outputs.get() + + ## do the competitive Hebbian update + signed_x_in = x_in + if self.label_dim > 0: ## first, compute the sign of the update if labels are available + ## LVQ(1) => compute sign of dW given label match (-1 if no match, +1 if match) + y_in = self.labels.get() + YW = self.label_weights.get()#.T + y_mem = jnp.matmul(z_out, YW.T) ## decode to get label memories + ## each row of `y_exists`: 1 if lab mem stored, 0 otherwise + y_exists = (jnp.sum(y_mem, axis=1, keepdims=True) > 0.) * 1. + ## TODO: update YW with labels for initial cond? + + y_in_l = jnp.argmax(y_in, axis=1, keepdims=True) ## get lab indices + y_mem_l = jnp.argmax(y_mem, axis=1, keepdims=True) ## get mem lab indices + ## each of `dy`: -1 => incorrect (push away), +1 => correct (push towards) + dy = (y_in_l == y_mem_l) * 2. - 1. + dy = dy * y_exists + (1. - y_exists) ## +1 for each "empty" memory + signed_x_in = x_in * dy ## sign (-1, +1) each update + ## else, sign of all updates is +1 + + ## second, given the above sign, compute the Hebbian adjustment and optional terms + dW = jnp.matmul(signed_x_in.T, z_out) ## calc competitive Hebbian update (N x D) + dW = dW - (W * self.syn_decay) ## inject weight decay + + if self.zeta > 0.: ## synaptic update noise + tmp_key, *subkeys = random.split(self.key.get(), 3) + self.key.set(tmp_key) + eps = random.normal(subkeys[0], W.shape) + dW = dW + jnp.sqrt(2. * self.eta.get()) * eps ## inject Langevin noise + dW = dW + eps * (2. * self.eta.get()) * self.zeta ## noise term (prevents going to zero in theory) + + if self.w_bound > 0.: ## enforce a soft value bound + dW = dW * (self.w_bound - jnp.abs(W)) + # ## else, do not apply soft-bounding + self.dWeights.set(dW) + + ## third, apply the synaptic update to memory matrix W + W = W + dW * self.eta.get() + self.weights.set(W) + + ## update learning rate (eta) + eta_tp1 = jnp.maximum(1e-5, self.eta.get() - self.eta_decr) + self.eta.set(eta_tp1) + + self.i_tick.set(self.i_tick.get() + 1) ## advance internal "tick" + + @compilable + def reset(self): + preVals = jnp.zeros((self.batch_size.get(), self.shape.get()[0])) + postVals = jnp.zeros((self.batch_size.get(), self.shape.get()[1])) + + if not self.inputs.targeted: + self.inputs.set(preVals) + self.outputs.set(postVals) + self.labels.set(self.labels.get() * 0) + self.pred_labels.set(self.pred_labels.get() * 0) + self.dWeights.set(jnp.zeros(self.shape.get())) + #self.bmu.set(self.bmu.get() * 0) + + @classmethod + def help(cls): ## component help function + properties = { + "synapse_type": "VectorQuantizeSynapse - performs an adaptable synaptic transformation of inputs to produce output " + "signals; synapses are adjusted via competitive Hebbian learning in accordance with a " + "vector quantization model" + } + compartment_props = { + "input_compartments": + {"inputs": "Takes in external input signal values", + "labels": "Takes in (optional) label signal values", + "key": "JAX PRNG key"}, + "parameter_compartments": + {"weights": "Synapse efficacy/strength parameter values", + "label_weights": "Label efficacy parameter values (if this VQ is supervised)"}, + "output_compartments": + {"outputs": "Output of synaptic transformation", + "pred_labels": "Predicted labels (if this VQ is supervised)"}, + } + hyperparams = { + "shape": "Shape of synaptic weight value matrix; number inputs x number outputs", + "label_dim": "Dimensionality of labels (if this VQ is supervised)", + "batch_size": "Batch size dimension of this component", + "weight_init": "Initialization conditions for synaptic weight (W) values", + "resist_scale": "Resistance level scaling factor (applied to output of transformation)", + "p_conn": "Probability of a connection existing (otherwise, it is masked to zero)", + "eta": "Global learning rate", + "eta_decrement": "Constant to decrement `eta` by per update/call to `evolve()`", + "distance_function": "Distance function tuple specifying how to compute BMUs" + } + info = {cls.__name__: properties, + "compartments": compartment_props, + "dynamics": "outputs = [bmu_mask] ;" + "dW = VQ competitive Hebbian update", + "hyperparameters": hyperparams} + return info + +# if __name__ == '__main__': +# from ngcsimlib.context import Context +# with Context("Bar") as bar: +# Wab = VectorQuantizeSynapse("Wab", (2, 3), 4, 4, 1.) +# print(Wab) diff --git a/ngclearn/components/synapses/denseSynapse.py b/ngclearn/components/synapses/denseSynapse.py index d7980c4c..ee1ecb02 100755 --- a/ngclearn/components/synapses/denseSynapse.py +++ b/ngclearn/components/synapses/denseSynapse.py @@ -41,15 +41,23 @@ class DenseSynapse(JaxComponent): ## base dense synaptic cable """ def __init__( - self, name, shape, weight_init=None, bias_init=None, resist_scale=1., p_conn=1., mask=None, batch_size=1, + self, + name, + shape, + weight_init=None, + bias_init=None, + resist_scale=1., + p_conn=1., + mask=None, + batch_size=1, **kwargs ): super().__init__(name, **kwargs) self.batch_size = batch_size - self.mask = 1. - if mask is not None: - self.mask = mask + # self.mask = 1. + # if mask is not None: + # self.mask = mask ## Synapse meta-parameters self.shape = shape @@ -75,6 +83,10 @@ def __init__( self.inputs = Compartment(preVals) self.outputs = Compartment(postVals) self.weights = Compartment(weights) + _mask = 1. + if mask is not None: + _mask = mask + self.mask = Compartment(_mask) ## Set up (optional) bias values if bias_init is None: info(self.name, "is using default bias value of zero (no bias kernel provided)!") @@ -86,7 +98,7 @@ def __init__( @compilable def advance_state(self): weights = self.weights.get() - weights = weights * self.mask + weights = weights * self.mask.get() self.outputs.set((jnp.matmul(self.inputs.get(), weights) * self.resist_scale) + self.biases.get()) @compilable diff --git a/ngclearn/components/synapses/hebbian/BCMSynapse.py b/ngclearn/components/synapses/hebbian/BCMSynapse.py index ff669a07..088418a9 100755 --- a/ngclearn/components/synapses/hebbian/BCMSynapse.py +++ b/ngclearn/components/synapses/hebbian/BCMSynapse.py @@ -103,7 +103,7 @@ def evolve(self, t, dt): #t, dt, tau_w, tau_theta, w_bound, w_decay, pre, post, dtheta = jnp.mean(jnp.square(self.post.get()), axis=0, keepdims=True) ## batch avg theta = self.theta.get() + (-self.theta.get() + dtheta) * dt / self.tau_theta - #self.weights.set(weights) + self.weights.set(_W) ## TODO: this should update? self.theta.set(theta) self.dWeights.set(dWeights) self.post_term.set(post_term) diff --git a/ngclearn/components/synapses/hebbian/STDPSynapse.py b/ngclearn/components/synapses/hebbian/STDPSynapse.py new file mode 100755 index 00000000..b16df8db --- /dev/null +++ b/ngclearn/components/synapses/hebbian/STDPSynapse.py @@ -0,0 +1,224 @@ +from jax import random, numpy as jnp, jit +from ngclearn import compilable #from ngcsimlib.parser import compilable +from ngclearn import Compartment #from ngcsimlib.compartment import Compartment +from ngclearn.components.synapses import DenseSynapse +from ngclearn.utils import tensorstats + +class STDPSynapse(DenseSynapse): # power-law / trace-based STDP + """ + A synaptic cable that adjusts its efficacies via raw + spike-timing-dependent plasticity (STDP). + + | --- Synapse Compartments: --- + | inputs - input (takes in external signals) + | outputs - output signals (transformation induced by synapses) + | weights - current value matrix of synaptic efficacies + | key - JAX PRNG key + | --- Synaptic Plasticity Compartments: --- + | preSpike - pre-synaptic spike to drive long-term potentiation (takes in external signals) + | postSpike - post-synaptic spike to drive long-term depression (takes in external signals) + | pre_tols - pre-synaptic time-of-last-spike (takes in external signals) + | post_tols - post-synaptic time-of-last-spike (takes in external signals) + | dWeights - current delta matrix containing changes to be applied to synaptic efficacies + | eta - global learning rate (multiplier beyond A_plus and A_minus) + + | References: + | Markram, Henry, et al. "Regulation of synaptic efficacy by coincidence of + | postsynaptic APs and EPSPs." Science 275.5297 (1997): 213-215. + | + | Bi, Guo-qiang, and Mu-ming Poo. "Synaptic modification by correlated + | activity: Hebb's postulate revisited." Annual review of neuroscience 24.1 + | (2001): 139-166. + + Args: + name: the string name of this cell + + shape: tuple specifying shape of this synaptic cable (usually a 2-tuple + with number of inputs by number of outputs) + + A_plus: strength of long-term potentiation (LTP) + + A_minus: strength of long-term depression (LTD) + + tau_plus: time constant of long-term potentiation (LTP) + + tau_minus: time constant of long-term depression (LTD) + + eta: global learning rate initial value/condition (default: 1) + + tau_w: time constant for synaptic adjustment; setting this to zero + disables Euler-style synaptic adjustment (default: 0) + + weight_init: a kernel to drive initialization of this synaptic cable's values; + typically a tuple with 1st element as a string calling the name of + initialization to use + + resist_scale: a fixed scaling factor to apply to synaptic transform + (Default: 1.), i.e., yields: out = ((W * Rscale) * in) + + p_conn: probability of a connection existing (default: 1); setting + this to < 1. will result in a sparser synaptic structure + + w_bound: maximum value/magnitude any synaptic efficacy can be (default: 1) + """ + + # Define Functions + def __init__(self, name, shape, A_plus, A_minus, tau_plus=10., tau_minus=10., w_decay=0., + eta=1., tau_w=0., weight_init=None, resist_scale=1., p_conn=1., w_bound=1., + batch_size=1, **kwargs): + super().__init__(name, shape, weight_init, None, resist_scale, + p_conn, batch_size=batch_size, **kwargs) + assert self.batch_size == 1 ## note: STDP only supports online learning in this implementation + ## Synaptic hyper-parameters + self.shape = shape ## shape of synaptic efficacy matrix + self.Aplus = A_plus ## LTP strength + self.Aminus = A_minus ## LTD strength + self.tau_plus = tau_plus ## LTP time constant + self.tau_minus = tau_minus ## LTD time constant + self.Rscale = resist_scale ## post-transformation scale factor + self.w_bound = w_bound #1. ## soft weight constraint + self.tau_w = tau_w ## synaptic update time constant + self.w_decay = w_decay + + ## Compartment setup + preVals = jnp.zeros((self.batch_size, shape[0])) + postVals = jnp.zeros((self.batch_size, shape[1])) + self.preSpike = Compartment(preVals) + self.postSpike = Compartment(postVals) + self.pre_tols = Compartment(preVals) ## pre-synaptic time-of-last-spike + self.post_tols = Compartment(postVals) ## post-synaptic time-of-last-spike + self.dWeights = Compartment(self.weights.value * 0) + self.eta = Compartment(jnp.ones((1, 1)) * eta) ## global learning rate + + @staticmethod + def _compute_update(Aplus, Aminus, tau_plus, tau_minus, preSpike, postSpike, + pre_tols, post_tols, weights): + ## calculate time deltas matrix block --> (t_post - t_pre) + post_m = (post_tols > 0.) ## zero post-tols mask + pre_m = (pre_tols > 0.).T ## zero pre-tols mask + t_delta = ((weights * 0 + 1.) * post_tols) - pre_tols.T ## t_delta.shape = weights.shape + t_delta = t_delta * post_m * pre_m ## mask out zero tols and same-time spikes + pos_t_delta_m = (t_delta > 0.) ## positive t-delta mask + neg_t_delta_m = (t_delta < 0.) ## negative t-delta mask + #t_delta = t_delta * pos_t_delta_m + t_delta * neg_t_delta_m ## mask out same time spikes + ## calculate post-synaptic term + postTerm = jnp.exp(-t_delta/tau_plus) * pos_t_delta_m + dWpost = postTerm * (postSpike * Aplus) + dWpre = 0. + if Aminus > 0.: + ## calculate pre-synaptic term + preTerm = jnp.exp(-t_delta / tau_minus) * neg_t_delta_m + dWpre = -preTerm * (preSpike.T * Aminus) + ## calc final weighted adjustment + dW = (dWpost + dWpre) + return dW + + @compilable + def evolve(self, t, dt): + weights = self.weights.get() + preSpike = self.preSpike.get() + postSpike = self.postSpike.get() + pre_tols = self.pre_tols.get() + post_tols = self.post_tols.get() + dWeights = STDPSynapse._compute_update( + self.Aplus, + self.Aminus, + self.tau_plus, + self.tau_minus, + preSpike, + postSpike, + pre_tols, + post_tols, + weights + ) + ## shift/alter values of synaptic efficacies + if self.tau_w > 0.: ## triggers Euler-style synaptic update + weights = weights + (-weights * dt / self.tau_w + dWeights * self.eta) + else: ## raw simple ascent-style update + weights = weights + dWeights * self.eta - weights * self.w_decay + ## enforce non-negativity + eps = 0.001 # 0.01 + weights = jnp.clip(weights, eps, self.w_bound - eps) # jnp.abs(w_bound)) + + self.weights.set(weights) + self.dWeights.set(dWeights) + + @compilable + def reset(self): + preVals = jnp.zeros((self.batch_size, self.shape[0])) + postVals = jnp.zeros((self.batch_size, self.shape[1])) + inputs = preVals + outputs = postVals + preSpike = preVals + postSpike = postVals + pre_tols = preVals + post_tols = postVals + dWeights = jnp.zeros(self.shape) + + self.inputs.set(inputs) + self.outputs.set(outputs) + self.preSpike.set(preSpike) + self.postSpike.set(postSpike) + self.pre_tols.set(pre_tols) + self.post_tols.set(post_tols) + self.dWeights.set(dWeights) + + @classmethod + def help(cls): ## component help function + properties = { + "synapse_type": "STDPSynapse - performs an adaptable synaptic " + "transformation of inputs to produce output signals; " + "synapses are adjusted with classical " + "spike-timing-dependent plasticity (STDP)" + } + compartment_props = { + "inputs": + {"inputs": "Takes in external input signal values", + "preSpike": "Pre-synaptic spike compartment event for STDP (s_j)", + "postSpike": "Post-synaptic spike compartment event for STDP (s_i)", + "pre_tols": "Pre-synaptic time-of-last-spike (t_j)", + "post_tols": "Post-synaptic time-of-last-spike (t_i)"}, + "states": + {"weights": "Synapse efficacy/strength parameter values", + "biases": "Base-rate/bias parameter values", + "eta": "Global learning rate (multiplier beyond A_plus and A_minus)", + "key": "JAX PRNG key"}, + "analytics": + {"dWeights": "Synaptic weight value adjustment matrix produced at time t"}, + "outputs": + {"outputs": "Output of synaptic transformation"}, + } + hyperparams = { + "shape": "Shape of synaptic weight value matrix; number inputs x number outputs", + "batch_size": "Batch size dimension of this component", + "weight_init": "Initialization conditions for synaptic weight (W) values", + "resist_scale": "Resistance level scaling factor (applied to output of transformation)", + "p_conn": "Probability of a connection existing (otherwise, it is masked to zero)", + "A_plus": "Strength of long-term potentiation (LTP)", + "A_minus": "Strength of long-term depression (LTD)", + "tau_plus": "Time constant for long-term potentiation (LTP)", + "tau_minus": "Time constant for long-term depression (LTD)", + "eta": "Global learning rate initial condition", + "tau_w": "Time constant for synaptic adjustment (if Euler-style change used)" + } + info = {cls.__name__: properties, + "compartments": compartment_props, + "dynamics": "outputs = [(W * Rscale) * inputs] ;" + "dW_{ij}/dt = A_plus * exp(-(t_i - t_j)/tau_plus) * s_j -" + " A_minus exp(-(t_i - t_j)/tau_minus) * s_i", + "hyperparameters": hyperparams} + return info + + def __repr__(self): + comps = [varname for varname in dir(self) if Compartment.is_compartment(getattr(self, varname))] + maxlen = max(len(c) for c in comps) + 5 + lines = f"[{self.__class__.__name__}] PATH: {self.name}\n" + for c in comps: + stats = tensorstats(getattr(self, c).value) + if stats is not None: + line = [f"{k}: {v}" for k, v in stats.items()] + line = ", ".join(line) + else: + line = "None" + lines += f" {f'({c})'.ljust(maxlen)}{line}\n" + return lines diff --git a/ngclearn/components/synapses/hebbian/__init__.py b/ngclearn/components/synapses/hebbian/__init__.py index f39d556f..05bfd207 100644 --- a/ngclearn/components/synapses/hebbian/__init__.py +++ b/ngclearn/components/synapses/hebbian/__init__.py @@ -1,4 +1,5 @@ from .hebbianSynapse import HebbianSynapse +from .STDPSynapse import STDPSynapse from .traceSTDPSynapse import TraceSTDPSynapse from .expSTDPSynapse import ExpSTDPSynapse from .eventSTDPSynapse import EventSTDPSynapse diff --git a/ngclearn/components/synapses/hebbian/hebbianSynapse.py b/ngclearn/components/synapses/hebbian/hebbianSynapse.py index 1f6c9a07..d558e46c 100644 --- a/ngclearn/components/synapses/hebbian/hebbianSynapse.py +++ b/ngclearn/components/synapses/hebbian/hebbianSynapse.py @@ -241,7 +241,7 @@ def _compute_update( @compilable def calc_update(self): - # Get the variables + # Get the variables pre = self.pre.get() post = self.post.get() weights = self.weights.get() @@ -265,23 +265,33 @@ def evolve(self, dt): post = self.post.get() weights = self.weights.get() biases = self.biases.get() - opt_params = self.opt_params.get() - + opt_params = self.opt_params.get() + ## calculate synaptic update values dWeights, dBiases = HebbianSynapse._compute_update( self.w_bound, self.is_nonnegative, self.sign_value, self.prior_type, self.prior_lmbda, self.pre_wght, self.post_wght, pre, post, weights ) + #if "W1" in self.name: + # print("dWn: ", jnp.linalg.norm(dWeights)) + # print(" Wn: ", jnp.linalg.norm(weights)) + ## conduct a step of optimization - get newly evolved synaptic weight value matrix if self.bias_init != None: opt_params, [weights, biases] = self.opt(opt_params, [weights, biases], [dWeights, dBiases]) else: # ignore db since no biases configured opt_params, [weights] = self.opt(opt_params, [weights], [dWeights]) + #if "W1" in self.name: + # print("dWn: ", jnp.linalg.norm(dWeights)) + # print(" Wn: ", jnp.linalg.norm(weights)) + ## ensure synaptic efficacies adhere to constraints weights = _enforce_constraints(weights, self.w_bound, is_nonnegative=self.is_nonnegative) - + ## TODO: temporary fix + weights = weights * self.mask.get() + # Update compartments self.opt_params.set(opt_params) self.weights.set(weights) diff --git a/ngclearn/components/synapses/mpsSynapse.py b/ngclearn/components/synapses/mpsSynapse.py new file mode 100644 index 00000000..0b7efc7d --- /dev/null +++ b/ngclearn/components/synapses/mpsSynapse.py @@ -0,0 +1,225 @@ +from jax import random, numpy as jnp, jit +from ngclearn.components.jaxComponent import JaxComponent +from ngclearn.utils.matrix_utils import decompose_to_mps +from ngcsimlib.logger import info + +from ngclearn import compilable +from ngclearn import Compartment + +class MPSSynapse(JaxComponent): + """ + A Matrix Product State (MPS) compressed synaptic cable. + + This component represents a synaptic weight matrix decomposed into a + contracted chain of low-rank tensor cores (also known as a Tensor Train). + This architecture drastically reduces parameter counts for high-dimensional + layers—from O(N*M) to O(N*K + M*K)—while maintaining high expressive power + and biological plausibility through local error-driven updates. + + | References: + | Stoudenmire, E. Miles, and David J. Schwab. "Supervised learning with + | quantum-inspired tensor networks." Advances in neural information + | processing systems 29 (2016). + | + | Novikov, Alexander, et al. "Tensorizing neural networks." Advances in + | neural information processing systems 28 (2015). + | + | Nuijten, W. W. L., et al. "A Message Passing Realization of Expected + | Free Energy Minimization." arXiv preprint arXiv:2501.03154 (2025). + | + | Wilson, P. "Performing Active Inference with Explainable Tensor + | Networks." (2024). + | + | Fields, Chris, et al. "Control flow in active inference systems." + | arXiv preprint arXiv:2303.01514 (2023). + + | --- Synapse Compartments: --- + | inputs - external input signal values (shape: batch_size x in_dim) + | outputs - transformed signal values (shape: batch_size x out_dim) + | pre - pre-synaptic latent state values for learning (shape: batch_size x in_dim) + | post - post-synaptic error signal values for learning (shape: batch_size x out_dim) + | core1 - first MPS tensor core (shape: 1 x in_dim x bond_dim) + | core2 - second MPS tensor core (shape: bond_dim x out_dim x 1) + | key - JAX PRNG key used for stochasticity + + Args: + name: the string name of this component + + shape: tuple specifying the shape of the latent synaptic weight matrix + (number of inputs, number of outputs) + + bond_dim: the internal rank or "bond dimension" of the MPS compression. + Higher values increase expressive power at the cost of more parameters. + (Default: 16) + + batch_size: the number of samples in a concurrent batch (Default: 1) + """ + + def __init__(self, name, shape, bond_dim=16, batch_size=1, **kwargs): + super().__init__(name, **kwargs) + + self.batch_size = batch_size + self.shape = shape + self.bond_dim = bond_dim + + # Initialize synaptic cores using a small normal distribution + tmp_key, *subkeys = random.split(self.key.get(), 3) + + # Core 1: maps input dimension to the internal bond dimension + c1 = random.normal(subkeys[0], (1, shape[0], bond_dim)) * 0.05 + self.core1 = Compartment(c1) + + # Core 2: maps internal bond dimension to the output dimension + c2 = random.normal(subkeys[1], (bond_dim, shape[1], 1)) * 0.05 + self.core2 = Compartment(c2) + + # Initialize Port/Compartment values + preVals = jnp.zeros((self.batch_size, shape[0])) + postVals = jnp.zeros((self.batch_size, shape[1])) + + self.inputs = Compartment(preVals) + self.outputs = Compartment(postVals) + self.pre = Compartment(preVals) + self.post = Compartment(postVals) + + @compilable + def advance_state(self): + """ + Performs the forward synaptic transformation using MPS contraction. + + The full transformation is equivalent to: outputs = inputs @ (Core1 * Core2), + but computed via iterative contraction to maintain memory efficiency: + 1. z = inputs contracted with Core1 (Batch x Bond_Dim) + 2. outputs = z contracted with Core2 (Batch x Out_Dim) + """ + x = self.inputs.get() + c1 = self.core1.get() + c2 = self.core2.get() + + # Contraction 1: (Batch, In) @ (1, In, Bond) -> (Batch, Bond) + z = jnp.einsum('bi,mik->bk', x, c1) + + # Contraction 2: (Batch, Bond) @ (Bond, Out, 1) -> (Batch, Out) + out = jnp.einsum('bk,kno->bn', z, c2) + + self.outputs.set(out) + + @compilable + def project_backward(self, error_signal): + """ + Projects an error signal backwards through the compressed synaptic cable. + + This allows the passing of messages/gradients through the hierarchy + without ever reconstructing the full dense weight matrix, ensuring + O(N) complexity relative to the input/output dimensions. + """ + c1 = self.core1.get() + c2 = self.core2.get() + # 1. Project error through Core 2 to the bond space + e_back = jnp.einsum('bo,kno->bk', error_signal, c2) + # 2. Project from bond space through Core 1 to the input space + return jnp.einsum('bk,mik->bi', e_back, c1) + + @compilable + def evolve(self, eta=0.01): + """ + Updates the MPS tensor cores using local error-driven (Hebbian) gradients. + + This utilizes the 'pre' and 'post' compartments to update core1 and core2. + Because the weights are factorized, the update to each core depends on + the activity and errors projected through the other core, maintaining + global consistency through local message passing. + """ + x = self.pre.get() # Shape: (Batch, In) + err = self.post.get() # Shape: (Batch, Out) + c1 = self.core1.get() # Shape: (1, In, K) + c2 = self.core2.get() # Shape: (K, Out, 1) + + # 1. Compute latent bond activity for Core 2 update + z = jnp.einsum('bi,mik->bk', x, c1) + + # 2. Update Core 2 (Gradients relative to bond activity and output error) + dc2 = jnp.einsum('bk,bn->kn', z, err) + dc2 = jnp.expand_dims(dc2, axis=2) + + # 3. Update Core 1 (Gradients relative to input activity and back-projected error) + err_back = jnp.einsum('bn,kno->bk', err, c2) + dc1 = jnp.einsum('bi,bk->ik', x, err_back) + dc1 = jnp.expand_dims(dc1, axis=0) + + # Apply updates to synaptic cores + self.core1.set(c1 + eta * dc1) + self.core2.set(c2 + eta * dc2) + + @compilable + def reset(self): + """ + Resets input, output, and activity compartments to zero. + """ + if not self.inputs.targeted: + self.inputs.set(jnp.zeros((self.batch_size, self.shape[0]))) + + self.outputs.set(jnp.zeros((self.batch_size, self.shape[1]))) + + if not self.pre.targeted: + self.pre.set(jnp.zeros((self.batch_size, self.shape[0]))) + + if not self.post.targeted: + self.post.set(jnp.zeros((self.batch_size, self.shape[1]))) + + @property + def weights(self): + """ + Reconstructs the full dense matrix from the MPS cores for analysis. + Note: This is computationally expensive for high-dimensional layers. + """ + return Compartment(jnp.einsum('mik,kno->in', self.core1.get(), self.core2.get())) + + @weights.setter + def weights(self, W): + """ + Sets the synaptic cores by decomposing a provided dense matrix W + using Singular Value Decomposition (SVD). + """ + c1, c2 = decompose_to_mps(W, bond_dim=self.bond_dim) + self.core1.set(c1) + self.core2.set(c2) + + @classmethod + def help(cls): + """ + Returns an info dictionary describing the component. + """ + properties = { + "synapse_type": "MPSSynapse - performs a compressed synaptic " + "transformation of inputs to produce output signals via " + "Matrix Product State (MPS) core contractions." + } + compartment_props = { + "inputs": + {"inputs": "Takes in external input signal values", + "pre": "Pre-synaptic latent state values for learning", + "post": "Post-synaptic error signal values for learning"}, + "states": + {"core1": "First MPS tensor core (1, in_dim, bond_dim)", + "core2": "Second MPS tensor core (bond_dim, out_dim, 1)", + "key": "JAX PRNG key"}, + "outputs": + {"outputs": "Output of compressed synaptic transformation"}, + } + hyperparams = { + "shape": "Shape of latent weight matrix (in_dim, out_dim)", + "bond_dim": "The compression rank/bond-dimension of the MPS chain", + "batch_size": "Batch size dimension of this component" + } + info = {cls.__name__: properties, + "compartments": compartment_props, + "dynamics": "outputs = [inputs @ Core1] @ Core2", + "hyperparameters": hyperparams} + return info + +if __name__ == '__main__': + from ngcsimlib.context import Context + with Context("MPS_Test") as ctx: + Wab = MPSSynapse("Wab", (10, 5), bond_dim=4) + print(Wab) \ No newline at end of file diff --git a/ngclearn/components/synapses/patched/hebbianPatchedSynapse.py b/ngclearn/components/synapses/patched/hebbianPatchedSynapse.py index ae58c6ac..9ccaa8db 100644 --- a/ngclearn/components/synapses/patched/hebbianPatchedSynapse.py +++ b/ngclearn/components/synapses/patched/hebbianPatchedSynapse.py @@ -197,8 +197,8 @@ def __init__( pre_wght=1., post_wght=1., p_conn=1., resist_scale=1., batch_size=1, **kwargs ): super().__init__( - name, shape, n_sub_models, stride_shape, block_mask, weight_init, bias_init, resist_scale, p_conn, - batch_size=batch_size, **kwargs + name, shape, n_sub_models, stride_shape, weight_init, bias_init, resist_scale, p_conn, + batch_size, **kwargs ) prior_type, prior_lmbda = prior @@ -281,18 +281,24 @@ def evolve(self): self.dBiases.set(dBiases) @compilable - def reset(self): - preVals = jnp.zeros((self.batch_size, self.shape[0])) - postVals = jnp.zeros((self.batch_size, self.shape[1])) + def reset(self): ## closed, no-batch argument reset + ## write reset command to call inner batched_reset command + self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member + + @compilable + def batched_reset(self, batch_size): ## open, batch argument reset + preVals = jnp.zeros((batch_size, self.shape[0])) + postVals = jnp.zeros((batch_size, self.shape[1])) # BUG: the self.inputs here does not have the targeted field # NOTE: Quick workaround is to check if targeted is in the input or not - hasattr(self.inputs, "targeted") and not self.inputs.targeted and self.inputs.set(preVals) # inputs - self.outputs.set(postVals) # outputs - self.pre.set(preVals) # pre - self.post.set(postVals) # post - self.dWeights.set(jnp.zeros(self.shape)) # dW - self.dBiases.set(jnp.zeros(self.shape[1])) # db - + hasattr(self.inputs, "targeted") and not self.inputs.targeted and self.inputs.set(preVals) # inputs + self.outputs.set(postVals) # outputs + self.post_in.set(postVals) # post_in + self.pre_out.set(preVals) # pre_out + self.pre.set(preVals) # pre + self.post.set(postVals) # post + self.dWeights.set(jnp.zeros(self.shape)) # dW + self.dBiases.set(jnp.zeros(self.shape[1])) # db @classmethod def help(cls): ## component help function @@ -304,6 +310,7 @@ def help(cls): ## component help function compartment_props = { "inputs": {"inputs": "Takes in external input signal values", + "post_in": "Takes in external input signal values", "pre": "Pre-synaptic statistic for Hebb rule (z_j)", "post": "Post-synaptic statistic for Hebb rule (z_i)"}, "states": @@ -314,7 +321,8 @@ def help(cls): ## component help function {"dWeights": "Synaptic weight value adjustment matrix produced at time t", "dBiases": "Synaptic bias/base-rate value adjustment vector produced at time t"}, "outputs": - {"outputs": "Output of synaptic transformation"}, + {"outputs": "Output of synaptic transformation", + "pre_out": "Output of synaptic transformation"}, } hyperparams = { "shape": "Overall shape of synaptic weight value matrix; number inputs x number outputs", @@ -351,3 +359,10 @@ def help(cls): ## component help function plt.imshow(Wab.weights.get(), cmap='gray') plt.show() + + + + + + + diff --git a/ngclearn/components/synapses/patched/patchedSynapse.py b/ngclearn/components/synapses/patched/patchedSynapse.py index 540bd30a..6026cd51 100644 --- a/ngclearn/components/synapses/patched/patchedSynapse.py +++ b/ngclearn/components/synapses/patched/patchedSynapse.py @@ -4,78 +4,55 @@ from jax import random, numpy as jnp, jit from ngclearn.components.jaxComponent import JaxComponent from ngclearn.utils.distribution_generator import DistributionGenerator - from ngcsimlib.logger import info from ngclearn import compilable #from ngcsimlib.parser import compilable from ngclearn import Compartment #from ngcsimlib.compartment import Compartment -# from ngclearn.utils.weight_distribution import initialize_params - - -# def _create_multi_patch_synapses(key, shape, n_sub_models, sub_stride, weight_init): -# sub_shape = (shape[0] // n_sub_models, shape[1] // n_sub_models) -# di, dj = sub_shape -# si, sj = sub_stride - -# weight_shape = ((n_sub_models * di) + 2 * si, (n_sub_models * dj) + 2 * sj) -# #weights = initialize_params(key[2], {"dist": "constant", "value": 0.}, weight_shape, use_numpy=True) -# large_weight_init = DistributionGenerator.constant(value=0.) -# weights = large_weight_init(weight_shape, key[2]) - -# for i in range(n_sub_models): -# start_i = i * di -# end_i = (i + 1) * di + 2 * si -# start_j = i * dj -# end_j = (i + 1) * dj + 2 * sj - -# shape_ = (end_i - start_i, end_j - start_j) # (di + 2 * si, dj + 2 * sj) - -# ## FIXME: this line below might be wonky... -# weights.at[start_i: end_i, start_j: end_j].set( weight_init(shape_, key[2]) ) -# # weights[start_i : end_i, -# # start_j : end_j] = initialize_params(key[2], init_kernel=weight_init, shape=shape_, use_numpy=True) -# if si != 0: -# weights.at[:si,:].set(0.) ## FIXME: this setter line might be wonky... -# weights.at[-si:,:].set(0.) ## FIXME: this setter line might be wonky... -# if sj != 0: -# weights.at[:,:sj].set(0.) ## FIXME: this setter line might be wonky... -# weights.at[:, -sj:].set(0.) ## FIXME: this setter line might be wonky... - -# return weights - -def _create_multi_patch_synapses(key, shape, n_sub_models, sub_stride, weight_init): - sub_shape = (shape[0] // n_sub_models, shape[1] // n_sub_models) - di, dj = sub_shape - si, sj = sub_stride - - weight_shape = ((n_sub_models * di) + 2 * si, (n_sub_models * dj) + 2 * sj) - # weights = initialize_params(key[2], {"dist": "constant", "value": 0.}, weight_shape, use_numpy=True) - weights = DistributionGenerator.constant(value=0.)(weight_shape, key[2]) - - for i in range(n_sub_models): + +def _create_multi_patch_synapses(key, shape, n_modules, module_stride=(0, 0), initialization_type=DistributionGenerator.fan_in_gaussian()): + key, *subkey = random.split(key, n_modules+10) + + module_shape = (shape[0] // n_modules, shape[1] // n_modules) + di, dj = module_shape + si, sj = module_stride + + module_shape = di + (2 * si), dj + (2 * sj) + + + weight_shape = ((n_modules * di) + 2 * si, (n_modules * dj) + 2 * sj) + weights = jnp.zeros(weight_shape) + w_masks = jnp.zeros(weight_shape) + + for i in range(n_modules): start_i = i * di end_i = (i + 1) * di + 2 * si start_j = i * dj end_j = (i + 1) * dj + 2 * sj - shape_ = (end_i - start_i, end_j - start_j) # (di + 2 * si, dj + 2 * sj) + shape_ = (end_i - start_i, end_j - start_j) # (di + 2 * si, dj + 2 * sj) - # weights[start_i : end_i, - # start_j : end_j] = initialize_params(key[2], - # init_kernel=weight_init, - # shape=shape_, - # use_numpy=True) weights = weights.at[start_i : end_i, - start_j : end_j].set(weight_init(shape_, key[2])) + start_j : end_j].set(initialization_type(shape_, subkey[i])) + + w_masks = w_masks.at[start_i : end_i, + start_j : end_j].set(jnp.ones(shape_)) + if si!=0: weights = weights.at[:si,:].set(0.) weights = weights.at[-si:,:].set(0.) + + w_masks = w_masks.at[:si,:].set(0.) + w_masks = w_masks.at[-si:,:].set(0.) + if sj!=0: weights = weights.at[:,:sj].set(0.) weights = weights.at[:, -sj:].set(0.) - return weights + w_masks = weights.at[:,:sj].set(0.) + w_masks = weights.at[:, -sj:].set(0.) + return weights, module_shape, w_masks + class PatchedSynapse(JaxComponent): ## base patched synaptic cable """ A patched dense synaptic cables that creates multiple small dense synaptic cables; no form of synaptic evolution/adaptation @@ -114,7 +91,7 @@ class PatchedSynapse(JaxComponent): ## base patched synaptic cable bias_init: a kernel to drive initialization of biases for this synaptic cable (Default: None, which turns off/disables biases) - block_mask: weight mask matrix + w_masks: weight mask matrix pre_wght: pre-synaptic weighting factor (Default: 1.) @@ -127,8 +104,7 @@ class PatchedSynapse(JaxComponent): ## base patched synaptic cable this to < 1. will result in a sparser synaptic structure """ - def __init__( - self, name, shape, n_sub_models=1, stride_shape=(0,0), block_mask=None, weight_init=None, bias_init=None, + def __init__(self, name, shape, n_sub_models=1, stride_shape=(0,0), weight_init=None, bias_init=None, resist_scale=1., p_conn=1., batch_size=1, **kwargs ): super().__init__(name, **kwargs) @@ -144,20 +120,15 @@ def __init__( tmp_key, *subkeys = random.split(self.key.get(), 4) if self.weight_init is None: info(self.name, "is using default weight initializer!") - #self.weight_init = {"dist": "fan_in_gaussian"} self.weight_init = DistributionGenerator.fan_in_gaussian() - weights = _create_multi_patch_synapses( - key=subkeys, shape=shape, n_sub_models=self.n_sub_models, sub_stride=self.sub_stride, - weight_init=self.weight_init - ) - - self.block_mask = jnp.where(weights!=0, 1, 0) - self.sub_shape = (shape[0]//n_sub_models, shape[1]//n_sub_models) + weights, self.sub_shape, self.w_masks = _create_multi_patch_synapses( + key=tmp_key, shape=shape, n_modules=self.n_sub_models, module_stride=self.sub_stride, + initialization_type = self.weight_init + ) self.shape = weights.shape - self.sub_shape = self.sub_shape[0]+(2*self.sub_stride[0]), self.sub_shape[1]+(2*self.sub_stride[1]) - + if 0. < p_conn < 1.: ## only non-zero and <1 probs allowed mask = random.bernoulli(subkeys[1], p=p_conn, shape=self.shape) weights = weights * mask ## sparsify matrix @@ -165,39 +136,52 @@ def __init__( ## Compartment setup preVals = jnp.zeros((self.batch_size, self.shape[0])) postVals = jnp.zeros((self.batch_size, self.shape[1])) + self.inputs = Compartment(preVals) self.outputs = Compartment(postVals) self.weights = Compartment(weights) + self.post_in = Compartment(postVals) + self.pre_out = Compartment(preVals) + self.weights_T = Compartment(weights.T) + ## Set up (optional) bias values if self.bias_init is None: info(self.name, "is using default bias value of zero (no bias " "kernel provided)!") self.biases = Compartment(self.bias_init((1, self.shape[1]), subkeys[2]) if bias_init else 0.0) - #elf.biases = Compartment(initialize_params(subkeys[2], bias_init, (1, self.shape[1])) if bias_init else 0.0) @compilable def advance_state(self): # Get the variables inputs = self.inputs.get() + post_in = self.post_in.get() weights = self.weights.get() biases = self.biases.get() outputs = (jnp.matmul(inputs, weights) * self.Rscale) + biases + pre_out = jnp.matmul(post_in, weights.T) # Update compartment self.outputs.set(outputs) + self.pre_out.set(pre_out) @compilable - def reset(self): - preVals = jnp.zeros((self.batch_size, self.shape[0])) - postVals = jnp.zeros((self.batch_size, self.shape[1])) - inputs = preVals - outputs = postVals + def reset(self): ## closed, no-batch argument reset + ## write reset command to call inner batched_reset command + self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member + + @compilable + def batched_reset(self, batch_size): ## open, batch argument reset + preVals = jnp.zeros((batch_size, self.shape[0])) + postVals = jnp.zeros((batch_size, self.shape[1])) + # BUG: the self.inputs here does not have the targeted field # NOTE: Quick workaround is to check if targeted is in the input or not - hasattr(self.inputs, "targeted") and not self.inputs.targeted and self.inputs.set(inputs) - self.outputs.set(outputs) + hasattr(self.inputs, "targeted") and not self.inputs.targeted and self.inputs.set(preVals) + self.outputs.set(postVals) + self.post_in.set(postVals) + self.pre_out.set(preVals) @classmethod def help(cls): ## component help function @@ -208,13 +192,15 @@ def help(cls): ## component help function } compartment_props = { "inputs": - {"inputs": "Takes in external input signal values"}, + {"inputs": "Takes in external input signal values", + "post_in": "Takes in external input signal values"}, "states": {"weights": "Synapse efficacy/strength parameter values", "biases": "Base-rate/bias parameter values", "key": "JAX PRNG key"}, "outputs": - {"outputs": "Output of synaptic transformation"}, + {"outputs": "Output of synaptic transformation", + "pre_out": "Output of synaptic transformation"}, } hyperparams = { "shape": "Overall shape of synaptic weight value matrix; number inputs x number outputs", @@ -224,7 +210,7 @@ def help(cls): ## component help function "weight_init": "Initialization conditions for synaptic weight (W) values", "bias_init": "Initialization conditions for bias/base-rate (b) values", "resist_scale": "Resistance level scaling factor (Rscale); applied to output of transformation", - "block_mask": "weight mask matrix", + "w_masks": "weight mask matrix", "p_conn": "Probability of a connection existing (otherwise, it is masked to zero)" } info = {cls.__name__: properties, @@ -241,3 +227,8 @@ def help(cls): ## component help function plt.imshow(Wab.weights.get(), cmap='gray') plt.show() + + + + + diff --git a/ngclearn/utils/JaxProcessesMixin.py b/ngclearn/utils/JaxProcessesMixin.py index ae1a655c..3b849f09 100644 --- a/ngclearn/utils/JaxProcessesMixin.py +++ b/ngclearn/utils/JaxProcessesMixin.py @@ -2,13 +2,37 @@ from ngcsimlib.global_state import stateManager import jax from typing import TYPE_CHECKING + +from ngcsimlib._src.parser.utils import CompiledMethod + if TYPE_CHECKING: from ngcsimlib._src.process.baseProcess import BaseProcess +class JaxCompiledMethod(CompiledMethod): + def __init__(self, fn, fn_ast, auxiliary_ast, namespace, extra_globals): + super().__init__(fn, fn_ast, auxiliary_ast, namespace, extra_globals) + self._fn = jax.jit(fn) + self._fn_source = fn + + @property + def source_fn(self): + return self._fn_source + + @classmethod + def wrap(cls, compiledMethod: CompiledMethod): + return cls(compiledMethod._fn, + compiledMethod.ast, + compiledMethod.auxiliary_ast, + compiledMethod.namespace, + compiledMethod.extra_globals) + + class JaxProcessesMixin: - def __init__(self: "BaseProcess"): + def __init__(self: "BaseProcess", name, *args, use_jit=True, **kwargs): + super().__init__(name, *args, **kwargs) self._previous_result = None self._previous_state = None + self._use_jit = use_jit @property def previous_result(self): @@ -32,10 +56,14 @@ def scan(self: "BaseProcess", inputs, current_state=None, save_state: bool = Tru self._previous_result = result return final_state, result + def compile(self: "baseProcess"): + super().compile() + if self._use_jit: + self.run.compiled = JaxCompiledMethod.wrap(self.run.compiled) -class JaxJointProcess(JointProcess, JaxProcessesMixin): +class JaxJointProcess(JaxProcessesMixin, JointProcess): pass -class JaxMethodProcess(MethodProcess, JaxProcessesMixin): +class JaxMethodProcess(JaxProcessesMixin, MethodProcess): pass diff --git a/ngclearn/utils/__init__.py b/ngclearn/utils/__init__.py index 1d8c114e..b3a4b872 100644 --- a/ngclearn/utils/__init__.py +++ b/ngclearn/utils/__init__.py @@ -1,4 +1,5 @@ from .distribution_generator import DistributionGenerator from .JaxProcessesMixin import JaxJointProcess as JointProcess, JaxMethodProcess as MethodProcess from .model_utils import tensorstats +from .matrix_utils import decompose_to_mps diff --git a/ngclearn/utils/analysis/__init__.py b/ngclearn/utils/analysis/__init__.py index 0f97d6e4..082c68cd 100644 --- a/ngclearn/utils/analysis/__init__.py +++ b/ngclearn/utils/analysis/__init__.py @@ -1,3 +1,5 @@ ## point to supported analysis probes from .linear_probe import LinearProbe from .attentive_probe import AttentiveProbe +from .knn_probe import KNNProbe + diff --git a/ngclearn/utils/analysis/attentive_probe.py b/ngclearn/utils/analysis/attentive_probe.py index f721d69a..d55d0180 100644 --- a/ngclearn/utils/analysis/attentive_probe.py +++ b/ngclearn/utils/analysis/attentive_probe.py @@ -218,10 +218,25 @@ class AttentiveProbe(Probe): """ def __init__( - self, dkey, source_seq_length, input_dim, out_dim, num_heads=8, attn_dim=64, - target_seq_length=1, learnable_query_dim=32, batch_size=1, hid_dim=32, - use_LN=True, use_LN_input=False, use_softmax=True, dropout=0.5, eta=0.0002, - eta_decay=0.0, min_eta=1e-5, **kwargs + self, + dkey, + source_seq_length, + input_dim, + out_dim, + num_heads=8, + attn_dim=64, + target_seq_length=1, + learnable_query_dim=32, + batch_size=1, + hid_dim=32, + use_LN=True, + use_LN_input=False, + use_softmax=True, + dropout=0.5, + eta=0.0002, + eta_decay=0.0, + min_eta=1e-5, + **kwargs ): super().__init__(dkey, batch_size, **kwargs) assert attn_dim % num_heads == 0, f"`attn_dim` must be divisible by `num_heads`. Got {attn_dim} and {num_heads}." diff --git a/ngclearn/utils/analysis/knn_probe.py b/ngclearn/utils/analysis/knn_probe.py new file mode 100644 index 00000000..6935a3a0 --- /dev/null +++ b/ngclearn/utils/analysis/knn_probe.py @@ -0,0 +1,163 @@ +import jax +import numpy as np +from ngcsimlib import deprecate_args +from ngclearn.utils.analysis.probe import Probe +from ngclearn.utils.model_utils import kwta +from jax import jit, random, numpy as jnp, lax, nn +from functools import partial as bind +from ngclearn.utils.distribution_generator import DistributionGenerator + +@bind(jax.jit, static_argnums=[2, 3]) +def _run_knn_probe(_embeddings, Wx, K, dist_order=2): + ## Notes: + ### We do some 3D tensor math to handle a batch of predictions that need to be made + ### B = batch-size, D = embedding/input dim, C = number classes, N = number of memories + _Wx = jnp.expand_dims(Wx, axis=0) ## 3D tensor format of KNN params (1 x N x D) + embed_tensor = jnp.expand_dims(_embeddings, axis=1) ## 3D projection of input signals (B x 1 x D) + D = embed_tensor - _Wx ## compute 3D batched delta tensor (B x N x D) + ## get batched (negative) distance measurements + dist = jnp.linalg.norm(D, ord=dist_order, axis=2, keepdims=True) ## (B x N x 1) + ## else, default -> euclidean + ### Note: negative distance allows us to find minimal points w/ maximal functions + dist = -jnp.squeeze(dist, axis=2) ## (B x N) + ## now get K winners per sample in batch + values, indices = lax.top_k(dist, K) + return values, indices + +class KNNProbe(Probe): + """ + This implements a K-nearest neighbors (KNN) probe, which is useful for evaluating the quality of + encodings/embeddings in light of some superivsory downstream data (e.g., label one-hot + encodings or real-valued vector regression targets). + + Args: + dkey: init seed key + + source_seq_length: length of input sequence (e.g., height x width of the image feature) + + input_dim: input dimensionality of probe + + out_dim: output dimensionality of probe + + num_neighbors: number of nearest neighbors to perform estimate of output target with + + batch_size: size of batches to process per internal call to update (or process) + + K: number of nearest neighbors to estimate output target + + distance_function: tuple specifying distance function and its order for calculating nearest neighbors + (Default: ("minkowski", 2)). + usage guide: + ("minkowski", 2) or ("euclidean", ?) => use L2 norm (Euclidean) distance; + ("minkowski", 1) or ("manhattan", ?) => use L1 norm (taxi-cab/city-block) distance; + ("minkowksi", jnp.inf) or ("chebyshev", ?) => use Chebyshev distance; + ("minkowski", p > 2) => use a Minkowski distance of p-th order + + predictor_type: Str what type of problem is this K-NN solving? + + vote_style: + + """ + + @deprecate_args(K="num_neighbors") + def __init__( + self, + dkey, + source_seq_length, + input_dim, + out_dim, + batch_size=1, + num_neighbors=1, ## number of nearest neighbors (K) to find + distance_function=("minkowski", 2), + predictor_type="classifier", ## "classifier"; "regressor" + vote_style="mode", ## "mode", "mean" + **kwargs + ): + super().__init__(dkey, batch_size, **kwargs) + self.dkey, *subkeys = random.split(self.dkey, 3) + self.source_seq_length = source_seq_length + self.input_dim = input_dim + self.out_dim = out_dim + self.K = num_neighbors + self.vote_fx = 0 ## 0 -> mode prediction; 1 -> mean prediction + if vote_style == "mean": + self.vote_fx = 1 + self.distance_function = distance_function + dist_fun, dist_order = distance_function ## Default: ("minkowski", 2) -> Euclidean + if "euclidean" in dist_fun.lower(): + dist_order = 2 + elif "manhattan" in dist_fun.lower(): + dist_order = 1 + elif "chebyshev" in dist_fun.lower(): + dist_order = jnp.inf + ## TODO: add in cosine-distance (and maybe Mahalanobis distance) + self.dist_order = dist_order ## set distance order p + self.predictor_type = predictor_type + self.pred_fx = 0 + if "regressor" == predictor_type: + self.pred_fx = 1 + + #flat_input_dim = input_dim * source_seq_length + #W = jnp.zeros((flat_input_dim, out_dim)) + Wx = Wy = jnp.ones((1, 1)) ## Wy will be assumed to be one-hot encoded + self.probe_params = (Wx, Wy) + + def process(self, embeddings, dkey=None): ## TODO: JIT-i-fy this + _embeddings = embeddings + if len(_embeddings.shape) > 2: + flat_dim = embeddings.shape[1] * embeddings.shape[2] + _embeddings = jnp.reshape(_embeddings, (embeddings.shape[0], flat_dim)) + + Wx, Wy = self.probe_params ## pull out KNN parameters + values, indices = _run_knn_probe(_embeddings, Wx, self.K, self.dist_order) + + ## do K-neighbor voting scheme (find mode/frequency prediction) + Y_counts = jnp.zeros((_embeddings.shape[0], Wy.shape[1])) + for k in range(self.K): + winner_k_indx = indices[:, k] ## batch of k-th set of K winners + Y_k = Wy[winner_k_indx, :] ## predicted Y's of k-th winner batch + Y_counts = Y_counts + Y_k + ## do post-processing to conform to problem-type being solved by this K-NN + if self.pred_fx == 1: ## (regressor, contus outputs) + Y_pred = Y_counts * (1. / self.K) + else: ## pred_fx == 0 (classifier, discrete outputs) + Y_pred = Y_counts + if self.vote_fx == 1: ## calc mean prediction + Y_pred = Y_counts * (1. / self.K) + ## vote_fx == 0 (mode prediction) + Y_pred = nn.one_hot(jnp.argmax(Y_pred, axis=1), num_classes=Wy.shape[1]) # , keepdims=True) + return Y_pred ## (B, C) + + def update(self, embeddings, labels, dkey=None): + _embeddings = embeddings + if len(_embeddings.shape) > 2: + flat_dim = embeddings.shape[1] * embeddings.shape[2] + _embeddings = jnp.reshape(_embeddings, (embeddings.shape[0], flat_dim)) + + ## a K-NN's learning phase is just storing the data internally directly + Wx = _embeddings + Wy = labels + self.probe_params = (Wx, Wy) + +if __name__ == '__main__': + seed = 42 + D = 7 + C = 5 + dkey = random.PRNGKey(seed) + dkey, *subkeys = random.split(dkey, 3) + knn = KNNProbe( + subkeys[0], 1, input_dim=D, out_dim=C, K=1, dist_function="euclidean" + ) + X = random.uniform(subkeys[1], shape=(10, D)) + Y = jnp.concat( + [ + jnp.ones((2, C)) * jnp.array([[1., 0., 0., 0., 0.]]), + jnp.ones((2, C)) * jnp.array([[0., 1., 0., 0., 0.]]), + jnp.ones((2, C)) * jnp.array([[0., 0., 1., 0., 0.]]), + jnp.ones((2, C)) * jnp.array([[0., 0., 0., 1., 0.]]), + jnp.ones((2, C)) * jnp.array([[0., 0., 0., 0., 1.]]) + ], + axis=0 + ) + knn.update(X, Y) ## fit KNN to data + print(knn.process(X)) ## should construct the (smeared) identity matrix, exactly same as Y diff --git a/ngclearn/utils/analysis/linear_probe.py b/ngclearn/utils/analysis/linear_probe.py index a5546073..a4f5f693 100644 --- a/ngclearn/utils/analysis/linear_probe.py +++ b/ngclearn/utils/analysis/linear_probe.py @@ -73,7 +73,15 @@ class LinearProbe(Probe): """ def __init__( - self, dkey, source_seq_length, input_dim, out_dim, batch_size=1, use_LN=False, use_softmax=False, **kwargs + self, + dkey, + source_seq_length, + input_dim, + out_dim, + batch_size=1, + use_LN=False, + use_softmax=False, + **kwargs ): super().__init__(dkey, batch_size, **kwargs) self.dkey, *subkeys = random.split(self.dkey, 3) diff --git a/ngclearn/utils/diffeq/ode_utils.py b/ngclearn/utils/diffeq/ode_utils.py index 55a70ace..993edc9c 100755 --- a/ngclearn/utils/diffeq/ode_utils.py +++ b/ngclearn/utils/diffeq/ode_utils.py @@ -127,7 +127,7 @@ def _leapfrog(carry, dfq, dt, params): return new_carry, (new_carry, carry) @partial(jit, static_argnums=(3, 4)) -def leapfrog(t_curr, q_curr, p_curr, dfq, L, step_size, params): +def leapfrog(t_curr, q_curr, p_curr, dfq, L, step_size, params): ## leapfrog estimator step t = t_curr + 0. q = q_curr + 0. p = p_curr + 0. diff --git a/ngclearn/utils/matrix_utils.py b/ngclearn/utils/matrix_utils.py new file mode 100644 index 00000000..7eef3d26 --- /dev/null +++ b/ngclearn/utils/matrix_utils.py @@ -0,0 +1,26 @@ +import jax.numpy as jnp + +def decompose_to_mps(W, bond_dim=16): + """ + Decomposes a dense matrix W into two MPS cores using SVD. + + Args: + W: The dense matrix to decompose of shape (in_dim, out_dim). + + bond_dim: The internal rank/bond-dimension of the MPS compression. + + Returns: + A tuple containing: + core1: First tensor core of shape (1, in_dim, bond_dim). + core2: Second tensor core of shape (bond_dim, out_dim, 1). + """ + U, S, Vh = jnp.linalg.svd(W, full_matrices=False) + k = min(bond_dim, len(S)) + U_k = U[:, :k] + S_k = S[:k] + Vh_k = Vh[:k, :] + + s_sqrt = jnp.sqrt(S_k) + core1 = (U_k * s_sqrt).reshape(1, W.shape[0], k) + core2 = (s_sqrt[:, None] * Vh_k).reshape(k, W.shape[1], 1) + return core1, core2 diff --git a/ngclearn/utils/metric_utils.py b/ngclearn/utils/metric_utils.py index f91dda5b..457043cb 100755 --- a/ngclearn/utils/metric_utils.py +++ b/ngclearn/utils/metric_utils.py @@ -82,11 +82,24 @@ def measure_breadth_TC(spikes, preserve_batch=False): BTC = jnp.mean(BTC) return BTC -@jit -def measure_sparsity(codes, tolerance=0.): +@partial(jit, static_argnums=[2, 3]) +def measure_sparsity(codes, tolerance=0., preserve_batch=True, flip_measure=False): """ Calculates the sparsity (ratio) of an input matrix, assuming each row within - it is a non-negative vector. + this matrix is a non-negative vector. + + Formally, this means we compute, per i-th row: + | rho(x_i) = num_zeros(x_i) / dim(x_i) + and for a global score for matrix X with N codes/rows, we measure: + | rho_mean(X) = 1/N Sum^N_{i=1} rho(x_i) + where lower/closer to 0 means codes more sparse and closer to 1 means + codes are more dense. + + Note that this definition of sparsity aligns with Foldiak's definition of + the ratio of active neurons to inactive ones (assuming binary coding): + + | Foldiak, Peter. "Sparse and explicit neural coding." Principles of neural + | coding. CRC Press, 2013. 379-389. Args: codes: matrix (shape: N x D) of non-negative codes to measure @@ -94,11 +107,21 @@ def measure_sparsity(codes, tolerance=0.): tolerance: lowest number to consider as "empty"/non-existent (Default: 0.) + preserve_batch: if True, will return one score per sample (N x 1) in batch + (Default: True), otherwise, returns scalar average/mean score + + flip_measure: if True, will score sparsity via "1 - nzero/dim" (Default: False) + Returns: - sparsity measurements per code (output shape: N x 1) + sparsity measurements per code (shape: N x 1) or single score (shape: 1 x 1) """ + dim = codes.shape[1] m = (codes > tolerance).astype(jnp.float32) - rho = jnp.sum(m, axis=1, keepdims=True)/(codes.shape[1] * 1.) + rho = jnp.sum(m, axis=1, keepdims=True)/(dim * 1.) ## per-code sparsity + if flip_measure: ## closer to 1 = more sparse, closer to 0, more dense + rho = 1. - rho + if not preserve_batch: + rho = jnp.mean(rho) return rho #@partial(jit, static_argnums=[2]) diff --git a/ngclearn/utils/model_utils.py b/ngclearn/utils/model_utils.py index 0ba13ece..bf20079b 100755 --- a/ngclearn/utils/model_utils.py +++ b/ngclearn/utils/model_utils.py @@ -85,7 +85,10 @@ def create_function(fun_name, args=None): fx = tanh dfx = d_tanh elif fun_name == "bkwta": - fx = bkwta + ## NOTE: this requires an auxiliary arg to be set + ## which means this only supports binary WTA + fx = bkwta ## nWTA=1 + ## NOTE: this is an improper derivative proxy dfx = bkwta #d_identity elif fun_name == "sine": fx = sine @@ -119,7 +122,9 @@ def create_function(fun_name, args=None): dfx = d_softplus elif fun_name == "softmax": fx = softmax - dfx = d_identity ## TODO: currently Jacobian of softmax not supported! + ## NOTE: below is an improper derivative proxy + ## correct dfx is a Jacobian of softmax (not currently supported!) + dfx = d_identity elif fun_name == "unit_threshold": fx = threshold ## default threshold is 1 (thus unit) dfx = d_threshold ## STE approximation @@ -227,6 +232,26 @@ def one_hot(P): p_t = jnp.argmax(P, axis=1) return nn.one_hot(p_t, num_classes=nC, dtype=jnp.float32) +@partial(jit, static_argnums=[1, 2]) +def chebyshev_norm(d, axis=-1, keepdims=False): + """ + Calculate the Chebyshev distance between two tensor-arrays. + + Args: + d: tensor d to measure against the origin + + axis: axis to measure distance between the two tensors + + keepdims: preserve dimensions of d + + Returns: + the Chebyshev distance (values) within d + """ + abs_diff = jnp.abs(d) ## d could be (a - b) externally + dist_vals = jnp.max(abs_diff, axis=axis, keepdims=keepdims) + return dist_vals + +@jit def binarize(data, threshold=0.5): """ Converts the vector *data* to its binary equivalent @@ -458,7 +483,8 @@ def d_relu6(x): """ # df/dx = 1 if 0= a_min) *@ (z <= b_max) //create an indicator function a = 0 b = 6 - Ix1 = (x > 0.).astype(jnp.float32) #tf.cast(tf.math.greater_equal(x, 0.0),dtype=tf.float32) + #Ix1 = (x > 0.).astype(jnp.float32) #tf.cast(tf.math.greater_equal(x, 0.0),dtype=tf.float32) + Ix1 = (x >= 0.).astype(jnp.float32) Ix2 = (x <= 6.).astype(jnp.float32) #tf.cast(tf.math.less_equal(x, 6.0),dtype=tf.float32) Ix = Ix1 * Ix2 return Ix @@ -725,40 +751,206 @@ def clip(x, min_val, max_val): def d_clip(x, min_val, max_val): return jnp.where((x < min_val) | (x > max_val), 0.0, 1.0) +## block-matrix generation routine +def create_block_matrix(map_matrix, group_shape, alpha_inh=-1., alpha_exc=1.): + nrows, ncols = map_matrix.shape + gh, gw = group_shape + block = jnp.eye(gh, gw) * alpha_exc - (1. - jnp.eye(gh, gw)) * alpha_inh + gmat = [] + for r in range(nrows): + row = [] + for c in range(ncols): + element = map_matrix[r][c] + if element > 0.: + row.append(block) + else: + row.append(block * 0) + row = jnp.concatenate(row, axis=1) + gmat.append(row) + gmat = jnp.concatenate(gmat, axis=0) + return gmat + +@partial(jit, static_argnums=[1, 2, 3, 4]) +def normalize_block_matrix(matrix, block_size, order=2, axis=0, norm_targ=1.): + """ + Normalizes columns of blocks within a matrix. + + Args: + matrix: 2D JAX Array (M, N) + + block_size: Tuple (block_rows, block_cols) + + order: + + axis: (relative) axis for normalization within block; 0 -> by rows, 1 -> by cols + + norm_targ: + + Returns: + block-normalized (M, N) matrix + """ + _tensor_axis = (2, 3) ## assume row-axis for normalization + if axis == 1: + _tensor_axis = 3 ## get col-axis for normalization + elif axis == 0: + _tensor_axis = 2 ## assume row-axis for normalization + ## else, we leave row-axis as target for normalization + M, N = matrix.shape + r_blk, c_blk = block_size + # Reshape to 4D to isolate blocks: (num_blocks_row, block_rows, num_blocks_col, block_cols) + reshaped = matrix.reshape(M // r_blk, r_blk, N // c_blk, c_blk) + # Transpose to group block data: (num_blocks_row, num_blocks_col, block_rows, block_cols) + transposed = jnp.transpose(reshaped, (0, 2, 1, 3)) + # Calculate norm for each column "w/in" each block + ## (over axis 2 -> block_rows); (over axis 3 -> block_cols) + norms = jnp.linalg.norm(transposed, ord=order, axis=_tensor_axis, keepdims=True) + #normalized_blocks = jnp.divide(transposed, norms + 1e-8) ## normalize (w/ safe-division) + normalized_blocks = transposed * (norm_targ/(norms + 1e-8)) + # Reverse transpose: (num_blocks_row, block_rows, num_blocks_col, block_cols) + reverted = jnp.transpose(normalized_blocks, (0, 2, 1, 3)) + # Reshape back to original 2D shape (M, N) + return reverted.reshape(M, N) + +@partial(jit, static_argnums=[2, 3]) +def quantile_lkwta(x, m, nWTA=20, clipval=-1.): ## local k-WTA + """ + A quantile-based K-WTA function - NOTE: this is experimental and no guarantees are + offered at this point. + + Args: + x: data to apply quantile-KWTA function over + + m: masking tensor + + nWTA: number of winners + + clipval: + + Returns: + y = KWTA(x) + """ + ## expand to 3D tensor space and do logic in 3D + _x = jnp.expand_dims(x, axis=1) ## B x 1 x D + _M = jnp.expand_dims(m, axis=0) ## 1 x 1 x D + _x = _x * _M + (1. - _M) * (jnp.amin(_x) - 1.) + threshold = jnp.quantile( + _x, (_x.shape[2] - nWTA) / _x.shape[2], method='linear', axis=2, keepdims=True + ) + topK = (_x >= threshold) * 1. ## Do thresholding + topK = jnp.sum(topK, axis=1) * x + # if clipval > 0.: + # topK = jnp.clip(topK, -clipval, clipval) + return topK + +@partial(jit, static_argnums=[2, 3]) +def d_quantile_lkwta(x, m, nWTA=20, clipval=-1.): ## local k-WTA + """ + First derivative of quantile-based K-WTA function with respect to its input + - NOTE: this is experimental and no guarantees are + offered at this point. + + Args: + x: data to apply quantile-KWTA function over + + m: masking tensor + + nWTA: number of winners + + clipval: + + Returns: + y = KWTA(x) + """ + ## expand to 3D tensor space and do logic in 3D + _x = jnp.expand_dims(x, axis=1) ## B x 1 x D + _M = jnp.expand_dims(m, axis=0) ## 1 x 1 x D + _x = _x * _M + (1. - _M) * (jnp.amin(_x) - 1.) + threshold = jnp.quantile( + _x, (_x.shape[2] - nWTA) / _x.shape[2], method='linear', axis=2, keepdims=True + ) + topK = (_x >= threshold) * 1. ## Do thresholding + topK = jnp.sum(topK, axis=1) #* x + return topK + +@jit +def group_mean(x, masks): + ## expand to 3D tensor space and do logic in 3D (avoids a for-loop over groups in mask) + _x = jnp.expand_dims(x, axis=1) ## B x 1 x D + _M = jnp.expand_dims(masks, axis=0) ## 1 x 1 x D + x3D = _x * _M + mu = jnp.sum(x3D, axis=2, keepdims=True) / jnp.sum(_M, axis=2, keepdims=True) ## calc means over axis 2 of 3D tensor + mu = jnp.sum(mu * _M, axis=1) ## now contract back to 2D and smear group means to each dimension per group + return mu + +@partial(jit, static_argnums=[2]) +def kwta(x, m, nWTA=1): + return lkwta(x, m=m, nWTA=nWTA) + +@partial(jit, static_argnums=[2]) +def d_kwta(x, m, nWTA=1): + return d_lkwta(x, m=m, nWTA=nWTA) + +@partial(jit, static_argnums=[2, 3]) +def lkwta(x, m, nWTA=1, clipval=-1.): ## local/group K-WTA + """ + A group-based K-WTA function, i.e., local K-WTA (LKWTA), as proposed in: + + | Ororbia, Alexander, Karl Friston, and Rajesh PN Rao. "Meta-representational predictive coding: biomimetic + | self-supervised learning." arXiv preprint arXiv:2503.21796 (2025). + + Args: + x: data to apply quantile-KWTA function over -# def scanner(fn): -# """ -# A wrapper for Jax's scanner that handles the "getting" of the current -# state and "setting" of the final state to and from the model. -# -# | @scanner -# | def process(current_state, args): -# | t = args[0] -# | dt = args[1] -# | current_state = model.advance_state(current_state, t, dt) -# | current_state = model.evolve(current_state, t, dt) -# | return current_state, (current_state[COMPONENT.COMPARTMENT.path], ...) -# | -# | outputs = models.process(jnp.array([[ARG0, ARG1] for i in range(NUM_LOOPS)])) -# -# | Notes on the scanner function call: -# | 1) `current_state` is a hash-map mapped to all compartment values by path -# | 2) `args` is the external arguments defined in the passed Jax array -# | 3) `outputs` is a tuple containing time-concatenated Jax arrays of the -# | compartment statistics you want tracked -# -# Args: -# fn: function that is executed at every time step of a Jax-unrolled loop, -# it must take in the current state and external arguments -# -# Returns: -# wrapped (fast) function that is Jax-scanned/jit-i-fied -# """ -# def _scanned(_xs): -# vals, stacked = _scan(fn, init=Get_Compartment_Batch(), xs=_xs) -# Set_Compartment_Batch(vals) -# return stacked -# -# if get_current_context() is not None: -# get_current_context().__setattr__(fn.__name__, _scanned) -# return _scanned + m: masking tensor + + nWTA: number of winners + + clipval: + + Returns: + y = LKWTA(x) + """ + ## expand to 3D tensor space and do logic in 3D (avoids a for-loop over groups in mask) + ## this is as efficient as lax.top_k can be made for batches + _x = jnp.expand_dims(x, axis=1) ## B x 1 x D + _M = jnp.expand_dims(m, axis=0) ## 1 x 1 x D + _x = _x * _M + (1. - _M) * (jnp.amin(_x) - 1.) + values, indices = lax.top_k(_x, nWTA) # Note: we do not care to sort the indices + ## go back to 2D matrix space + kth = jnp.expand_dims(jnp.min(values, axis=(1, 2)), axis=1) # must do comparison per sample in potential mini-batch + topK = jnp.greater_equal(x, kth).astype(jnp.float32) # cast booleans to floats + topK = topK * x + if clipval > 0.: + topK = jnp.clip(topK, -clipval, clipval) + return topK + +@partial(jit, static_argnums=[2, 3]) +def d_lkwta(x, m, nWTA=1, clipval=-1.): ## derivative of local/group K-WTA w.r.t. input + """ + Derivative of group-based K-WTA function with respect to its input. This function, local K-WTA (LKWTA), + was proposed in: + + | Ororbia, Alexander, Karl Friston, and Rajesh PN Rao. "Meta-representational predictive coding: biomimetic + | self-supervised learning." arXiv preprint arXiv:2503.21796 (2025). + + Args: + x: data to apply quantile-KWTA function over + + m: masking tensor + + nWTA: number of winners + + clipval: + + Returns: + y = LKWTA(x) + """ + ## expand to 3D tensor space and do logic in 3D + _x = jnp.expand_dims(x, axis=1) ## B x 1 x D + _M = jnp.expand_dims(m, axis=0) ## 1 x 1 x D + _x = _x * _M + (1. - _M) * (jnp.amin(_x) - 1.) + values, indices = lax.top_k(_x, nWTA) # Note: we do not care to sort the indices + ## go back to 2D matrix space + kth = jnp.expand_dims(jnp.min(values, axis=(1, 2)), axis=1) # must do comparison per sample in potential mini-batch + topK = jnp.greater_equal(x, kth).astype(jnp.float32) # cast booleans to floats + return topK diff --git a/ngclearn/utils/patch_utils.py b/ngclearn/utils/patch_utils.py index a558e82e..205c86a9 100755 --- a/ngclearn/utils/patch_utils.py +++ b/ngclearn/utils/patch_utils.py @@ -121,8 +121,7 @@ def create_patches(self, add_frame=False, center=True): - -def generate_patch_set(x_batch, patch_size=(8, 8), max_patches=50, center=True, seed=1234, vis_mode=False): ## scikit +def generate_patch_set(x_batch, patch_size=(8, 8), max_patches=50, center=True, seed=1234, vis_mode=False, step_size=(1, 1)): ## scikit """ Generates a set of patches from an array/list of image arrays (via random sampling with replacement). This uses scikit-learn's patch creation @@ -149,7 +148,7 @@ def generate_patch_set(x_batch, patch_size=(8, 8), max_patches=50, center=True, for s in range(_x_batch.shape[0]): xs = _x_batch[s, :] xs = xs.reshape(px, py) - patches = extract_patches_2d(xs, patch_size, max_patches=max_patches, random_state=seed)#, random_state=69) + patches = extract_patches_2d(xs, patch_size, max_patches=max_patches, random_state=seed) #, extraction_step=step_size)#, random_state=69) patches = np.reshape(patches, (len(patches), -1)) # flatten each patch in set if s > 0: p_batch = np.concatenate((p_batch,patches),axis=0) @@ -201,3 +200,4 @@ def generate_pacthify_patch_set(x_batch_, patch_size=(5, 5), center=True): ## pa mu = np.mean(patchBatch, axis=1,keepdims=True) patchBatch = patchBatch - mu return patchBatch + diff --git a/pyproject.toml b/pyproject.toml index 057a86f5..bd1c7194 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta" # using setuptool building engine [project] name = "ngclearn" -version = "3.0.1" +version = "3.1.0" description = "Simulation software for building and analyzing computational neuroscience models, brain-inspired computing systems, and NeuroAI agents." authors = [ {name = "Alexander Ororbia", email = "ago@cs.rit.edu"}, diff --git a/requirements.txt b/requirements.txt index 1e871c1b..09ab6214 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ numpy>=1.26.4 scikit-learn>=1.6.1 -scipy>=1.15.2 -matplotlib>=3.10.1 +scipy>=1.14.1 +matplotlib>=3.9.4 # patchify # patchify has issues with pip installation jax>=0.4.28 jaxlib>=0.4.28 diff --git a/tests/components/neurons/graded/test_leakyNoiseCell.py b/tests/components/neurons/graded/test_leakyNoiseCell.py index 096c4f68..099c733f 100644 --- a/tests/components/neurons/graded/test_leakyNoiseCell.py +++ b/tests/components/neurons/graded/test_leakyNoiseCell.py @@ -16,7 +16,14 @@ def test_LeakyNoiseCell1(): dt = 1. # ms with Context(name) as ctx: a = LeakyNoiseCell( - name="a", n_units=1, tau_x=50., act_fx="identity", integration_type="euler", batch_size=1, sigma_rec=0., + name="a", + n_units=1, + tau_x=50., + act_fx="identity", + integration_type="euler", + batch_size=1, + sigma_pre=0., + sigma_post=0., leak_scale=0. ) advance_process = (MethodProcess("advance_proc") >> a.advance_state) diff --git a/tests/components/synapses/competitve/test_SOMSynapse.py b/tests/components/synapses/competitve/test_SOMSynapse.py new file mode 100644 index 00000000..defeec05 --- /dev/null +++ b/tests/components/synapses/competitve/test_SOMSynapse.py @@ -0,0 +1,112 @@ +from jax import numpy as jnp, random, jit +import numpy as np +np.random.seed(42) + +from ngclearn import Context, MethodProcess +from ngclearn.utils.distribution_generator import DistributionGenerator as dist +from ngclearn.components.synapses.competitive.SOMSynapse import SOMSynapse +from numpy.testing import assert_array_equal + +def test_SOMSynapse_batch_size_1(): + seed = 1234 + in_dim = 15 + lr = 0.05 + height = 15 + width = 15 + dkey = random.PRNGKey(seed) + dkey, *subkeys = random.split(dkey, 3) + with Context("som_ctx") as som_ctx: + som = SOMSynapse( + name="a", + n_inputs=in_dim, + n_units_x=height, + n_units_y=width, + eta=lr, ## initial learning-rate (alpha) + distance_function="euclidean", + neighbor_function="ricker", + weight_init=dist.uniform(0., 1.), + key=subkeys[0] + ) + evolve_process = (MethodProcess("evolve_process") + >> som.evolve) + advance_process = (MethodProcess("advance_proc") + >> som.advance_state) + reset_process = (MethodProcess("reset_proc") + >> som.reset) + + W = som.weights.get() + print(f"SOM.radius(0): {som.radius.get()[0,0]:.5f} " + f"SOM.eta(0): {som.eta.get()[0,0]:.5f} " + f"W.n(0): {jnp.linalg.norm(W)}") + + + x_n = np.random.normal(size=(1, in_dim)) # random input (B, in_dim) + reset_process.run() + som.inputs.set(x_n) ## clamp input to SOM input layer + advance_process.run(t=1., dt=1.) + evolve_process.run(t=1., dt=1.) + + i_tick = som.i_tick.get() ## each sample/update counts as an "up-tick" + print(f"\r{som.i_tick.get()} samps; " + f"SOM.radius: {som.radius.get()[0,0]:.5f} " + f"SOM.eta: {som.eta.get()[0,0]:.5f}", end="") + + +test_SOMSynapse_batch_size_1() + + +def test_SOMSynapse_batch_size_n(): + B = 4 # batch size + seed = 1234 + in_dim = 15 + lr = 0.05 + height = 15 + width = 15 + dkey = random.PRNGKey(seed) + dkey, *subkeys = random.split(dkey, 3) + ## set up a single layer SOM + with Context("som_ctx") as som_ctx: + som = SOMSynapse( + name="a", + n_inputs=in_dim, + n_units_x=height, + n_units_y=width, + eta=lr, ## initial learning-rate (alpha) + distance_function="euclidean", + neighbor_function="ricker", + weight_init=dist.uniform(0., 1.), + batch_size=B, + key=subkeys[0] + ) + evolve_process = (MethodProcess("evolve_process") + >> som.evolve) + advance_process = (MethodProcess("advance_proc") + >> som.advance_state) + reset_process = (MethodProcess("reset_proc") + >> som.reset) + + W = som.weights.get() + print(f"SOM.radius(0): {som.radius.get()[0,0]:.5f} " + f"SOM.eta(0): {som.eta.get()[0,0]:.5f} " + f"W.n(0): {jnp.linalg.norm(W)}") + + + x_n = np.random.normal(size=(B, in_dim)) # random input (B, in_dim) + reset_process.run() + som.inputs.set(x_n) ## clamp input to SOM input layer + advance_process.run(t=1., dt=1.) + evolve_process.run(t=1., dt=1.) + + assert som.bmu.get().shape == (B, 1) + assert som.neighbor_weights.get().shape == (B, height * width) + assert som.delta.get().shape == (B, in_dim, height * width) + assert som.outputs.get().shape == (B, height * width) + assert som.dWeights.get().shape == (in_dim, height * width) + + i_tick = som.i_tick.get() ## each sample/update counts as an "up-tick" + print(f"\r{som.i_tick.get()} samps; " + f"SOM.radius: {som.radius.get()[0,0]:.5f} " + f"SOM.eta: {som.eta.get()[0,0]:.5f}", end="") + +# test_SOMSynapse_batch_size_n() + diff --git a/tests/components/synapses/hebbian/test_BCMSynapse.py b/tests/components/synapses/hebbian/test_BCMSynapse.py index 7dbff4de..346525d3 100644 --- a/tests/components/synapses/hebbian/test_BCMSynapse.py +++ b/tests/components/synapses/hebbian/test_BCMSynapse.py @@ -19,7 +19,6 @@ def test_BCMSynapse1(): a = BCMSynapse( name="a", shape=(1,1), tau_w=40., tau_theta=20., key=subkeys[0] ) - evolve_process = (MethodProcess("evolve_process") >> a.evolve) @@ -42,4 +41,5 @@ def test_BCMSynapse1(): # print(truth) assert_array_equal(a.dWeights.get(), truth) -test_BCMSynapse1() +#test_BCMSynapse1() + diff --git a/tests/components/synapses/patched/test_hebbianPatchedSynapse.py b/tests/components/synapses/patched/test_hebbianPatchedSynapse.py index 4a33ae6f..afc2c85b 100644 --- a/tests/components/synapses/patched/test_hebbianPatchedSynapse.py +++ b/tests/components/synapses/patched/test_hebbianPatchedSynapse.py @@ -17,7 +17,7 @@ def test_hebbianPatchedSynapse(): dt = 1. # ms # model hyper - shape = (10, 5) + shape = (10, 10) n_sub_models = 2 stride_shape = (1, 1) batch_size = 1 @@ -64,6 +64,6 @@ def clamp_post(x): assert a.weights.get()[0, 0] == 0.5, "" -test_hebbianPatchedSynapse() +# test_hebbianPatchedSynapse() diff --git a/tests/components/synapses/patched/test_patchedSynapse.py b/tests/components/synapses/patched/test_patchedSynapse.py index e9b96d80..f7443566 100644 --- a/tests/components/synapses/patched/test_patchedSynapse.py +++ b/tests/components/synapses/patched/test_patchedSynapse.py @@ -36,6 +36,7 @@ def test_patchedSynapse(): advance_process = (MethodProcess("advance_proc") >> a.advance_state) reset_process = (MethodProcess("reset_proc") >> a.reset) + #batch_reset_process = (MethodProcess("batched_reset_proc") >> a.batched_reset) def clamp_inputs(x): a.inputs.set(x) @@ -46,6 +47,7 @@ def clamp_inputs(x): expected_outputs = (jnp.matmul(inputs_seq, weights) * resist_scale) + biases outputs_outs = [] reset_process.run() + #batch_reset_process.run(batch_size=batch_size) clamp_inputs(inputs_seq) advance_process.run(t=0., dt=dt) outputs_outs.append(a.outputs.get()) diff --git a/tests/components/synapses/test_mpsSynapse.py b/tests/components/synapses/test_mpsSynapse.py new file mode 100644 index 00000000..852c198e --- /dev/null +++ b/tests/components/synapses/test_mpsSynapse.py @@ -0,0 +1,97 @@ +from jax import numpy as jnp, random +import numpy as np +from ngcsimlib.context import Context +from ngclearn import MethodProcess +from ngclearn.components.synapses.mpsSynapse import MPSSynapse + +def test_mps_synapse_reconstruction(): + """ + Tests if MPSSynapse can be initialized from a dense matrix and + reproduce the transformation reasonably well. + """ + dkey = random.PRNGKey(42) + in_dim, out_dim = 20, 10 + bond_dim = 8 + + with Context("mps_test") as ctx: + mps = MPSSynapse("mps", (in_dim, out_dim), bond_dim=bond_dim) + advance = MethodProcess("advance") >> mps.advance_state + reset = MethodProcess("reset") >> mps.reset + + # Create a structured matrix + W_orig = random.normal(dkey, (in_dim, out_dim)) + + # Set weights via setter (uses decompose_to_mps) + mps.weights = W_orig + + # Check reconstruction fidelity + W_recon = mps.weights + error = jnp.linalg.norm(W_orig - W_recon) / jnp.linalg.norm(W_orig) + + # With bond_dim=8 and rank=10, error should be small but non-zero + assert error < 0.5 + + # Test transformation correctness + x = random.normal(dkey, (1, in_dim)) + mps.inputs.set(x) + advance.run() + + y_mps = mps.outputs.get() + y_dense = x @ W_recon + + np.testing.assert_allclose(y_mps, y_dense, atol=1e-2) + print(f"MPS Reconstruction Test Passed. Error: {error*100:.2f}%") + +def test_mps_synapse_learning(): + """ + Tests if MPSSynapse can learn from error signals via the evolve method. + """ + dkey = random.PRNGKey(123) + in_dim, out_dim = 10, 5 + bond_dim = 4 + + with Context("mps_learning_test") as ctx: + mps = MPSSynapse("mps", (in_dim, out_dim), bond_dim=bond_dim) + advance = MethodProcess("advance") >> mps.advance_state + evolve = MethodProcess("evolve") >> mps.evolve + reset = MethodProcess("reset") >> mps.reset + + # Target: Map x to target_y + x = random.normal(dkey, (1, in_dim)) + target_y = random.normal(dkey, (1, out_dim)) + + # 1. Initial prediction + mps.inputs.set(x) + advance.run() + initial_y = mps.outputs.get() + initial_error = jnp.sum((target_y - initial_y)**2) + + # 2. Learning step + # Hebbian learning expects pre and post + # error = target - predicted + error_signal = (target_y - initial_y) + + mps.pre.set(x) + mps.post.set(error_signal) + + # Run learning multiple times to see descent + for _ in range(5): + evolve.run(eta=0.1) + # Re-predict + advance.run() + current_y = mps.outputs.get() + current_error = jnp.sum((target_y - current_y)**2) + mps.post.set(target_y - current_y) # Update error signal for next step + + final_y = mps.outputs.get() + final_error = jnp.sum((target_y - final_y)**2) + + print(f"Initial Error: {initial_error:.6f}") + print(f"Final Error: {final_error:.6f}") + + assert final_error < initial_error + print("MPS Learning Test Passed.") + +if __name__ == "__main__": + test_mps_synapse_reconstruction() + test_mps_synapse_learning() From 7e5532b8a4177572d81a9899778e5a9d88e14393 Mon Sep 17 00:00:00 2001 From: Alexander Ororbia Date: Fri, 1 May 2026 12:30:05 -0400 Subject: [PATCH 2/7] minor edit to history --- history.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/history.txt b/history.txt index 4345a232..a8c1e724 100644 --- a/history.txt +++ b/history.txt @@ -99,4 +99,6 @@ History * new suite of competitive learning synapses (generalized formats), including vector-quantization, self-organizing map, adaptive resonance theory (contus-version), and modern hopfield network * revisions to metric and model utils * some additional clean-up, including supported retinal ganglion encoder + * fixed pkg-resource header (in both ngcsimlib and ngclearn) to account for newer python(s) + From 68bdd5ce4e9a43be393813268af33d7b7cb68840 Mon Sep 17 00:00:00 2001 From: Alexander Ororbia Date: Fri, 1 May 2026 12:34:03 -0400 Subject: [PATCH 3/7] fixed to header/requirements --- ngclearn/__init__.py | 3 ++- requirements.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ngclearn/__init__.py b/ngclearn/__init__.py index 6121286c..94cba56b 100644 --- a/ngclearn/__init__.py +++ b/ngclearn/__init__.py @@ -49,6 +49,7 @@ ## this prevents ngc-learn from messing with sphinx/building if not Path(argv[0]).name == "sphinx-build" or Path(argv[0]).name == "build.py": if "readthedocs" not in argv[0]: ## prevent readthedocs execution of preload - from ngcsimlib import configure + from ngcs +from importlib.metadata import distributionsimlib import configure configure() logger.init_logging() diff --git a/requirements.txt b/requirements.txt index 09ab6214..c8319b3e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,6 +5,6 @@ matplotlib>=3.9.4 # patchify # patchify has issues with pip installation jax>=0.4.28 jaxlib>=0.4.28 -ngcsimlib>=3.0.0 +ngcsimlib>=3.1.0 imageio>=2.37.0 pandas>=2.2.3 From d71beb7e5ac845d5eb7c0a966168d4bee0dd44d7 Mon Sep 17 00:00:00 2001 From: Alexander Ororbia Date: Fri, 1 May 2026 12:39:50 -0400 Subject: [PATCH 4/7] fixed to header/requirements --- ngclearn/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ngclearn/__init__.py b/ngclearn/__init__.py index 94cba56b..5670cfca 100644 --- a/ngclearn/__init__.py +++ b/ngclearn/__init__.py @@ -31,7 +31,7 @@ "currently installed!") ################################################################################## -## Needed to preload is called before anything in ngclearn +## Following are needed to preload is called before anything in ngclearn from pathlib import Path from sys import argv import numpy @@ -49,7 +49,6 @@ ## this prevents ngc-learn from messing with sphinx/building if not Path(argv[0]).name == "sphinx-build" or Path(argv[0]).name == "build.py": if "readthedocs" not in argv[0]: ## prevent readthedocs execution of preload - from ngcs -from importlib.metadata import distributionsimlib import configure + from ngcsimlib import configure configure() logger.init_logging() From 496cf1f7bf346d14689321f27d41db31f1df28e6 Mon Sep 17 00:00:00 2001 From: Alexander Ororbia Date: Fri, 1 May 2026 12:42:59 -0400 Subject: [PATCH 5/7] fixed to header/requirements --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index c8319b3e..978bd1fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,4 @@ jaxlib>=0.4.28 ngcsimlib>=3.1.0 imageio>=2.37.0 pandas>=2.2.3 +typing_extensions>=4.15.0 From 81dcb6e3a89dd9cfcfc18e7707acf87d19a973c8 Mon Sep 17 00:00:00 2001 From: Alexander Ororbia Date: Fri, 1 May 2026 12:51:38 -0400 Subject: [PATCH 6/7] cleanup of ganglion cell --- .../components/input_encoders/ganglionCell.py | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/ngclearn/components/input_encoders/ganglionCell.py b/ngclearn/components/input_encoders/ganglionCell.py index a35c7b0a..f3b2a41e 100644 --- a/ngclearn/components/input_encoders/ganglionCell.py +++ b/ngclearn/components/input_encoders/ganglionCell.py @@ -70,7 +70,10 @@ def _create_patches(obs, patch_shape, step_shape): class RetinalGanglionCell(JaxComponent): """ - A group of retinal ganglion cell that senses the input stimuli and sends out the filtered signal to the brain. + A group of retinal ganglion cell that sense input stimuli and send out filtered + signals (as output). Note that these simulated cells employ internal generalized + filters based on either Gaussian or difference-of-Gaussian kernels) to recover + historical receptive field processing effects. | --- Cell Input Compartments: --- | inputs - input (takes in external signals) @@ -85,32 +88,34 @@ class RetinalGanglionCell(JaxComponent): filter_type: string name of filter function (Default: identity) :Note: supported filters include "gaussian", "difference_of_gaussian" - sigma: standard deviation of gaussian kernel + sigma: standard deviation of (gaussian) kernel - area_shape: receptive field area of ganglion cells in this module all together + area_shape: shape of receptive field area of ganglion cells in this module (all together) n_cells: number of ganglion cells in this module - patch_shape: each ganglion cell receptive field area + patch_shape: shape of each ganglion cell's receptive field area - step_shape: the non-overlapping area between each two ganglion cells + step_shape: the non-overlapping area between each pair (two) of ganglion cells - batch_size: batch size dimension of this cell (Default: 1) + batch_size: batch size dimension of this cell/module (Default: 1) """ - def __init__(self, name: str, - filter_type: str, - area_shape: Tuple[int, int], - n_cells: int, - patch_shape: Tuple[int, int], - step_shape: Tuple[int, int], - batch_size: int = 1, - sigma: float = 1.0, - key: Union[jax.Array, None] = None, - **kwargs): + def __init__( + self, + name: str, + filter_type: str, + area_shape: Tuple[int, int], + n_cells: int, + patch_shape: Tuple[int, int], + step_shape: Tuple[int, int], + batch_size: int = 1, + sigma: float = 1.0, + key: Union[jax.Array, None] = None, + **kwargs + ): super().__init__(name=name, key=key) - ## Layer Size Setup self.filter_type = filter_type self.n_cells = n_cells @@ -143,14 +148,14 @@ def __init__(self, name: str, @compilable def advance_state(self, t): inputs = self.inputs.get() - filter = self.filter.get() + _filter = self.filter.get() px, py = self.patch_shape # ═══════════════════ extract pathches for filters ══════════════════ input_patches = _create_patches(inputs, patch_shape=self.patch_shape, step_shape=self.step_shape) # ═══════════════════ apply filter to all pathches ══════════════════ - filtered_input = input_patches * filter ## shape: (B | n_cells | px | py) + filtered_input = input_patches * _filter ## shape: (B | n_cells | px | py) # ════════════ reshape all cells responses to a single input to brain ════════════ filtered_input = filtered_input.reshape(-1, self.n_cells * (px * py)) ## shape: (B | n_cells * px * py) @@ -184,7 +189,7 @@ def reset(self): ## reset core components/statistics @classmethod def help(cls): ## component help function properties = { - "cell_type": "RetinalGanglionCell - filters the input stimuli, " + "cell_type": "RetinalGanglionCell - filters the input stimuli according retinal ganglion dynamics" } compartment_props = { "inputs": @@ -196,11 +201,11 @@ def help(cls): ## component help function } hyperparams = { "filter_type": "Type of the filter for preprocessing the input", - "sigma": "Standard deviation of gaussian kernel", + "sigma": "Standard deviation of gaussian kernel/filter", "area_shape": "Effective receptive field area shape of ganglion cells in this module", - "n_cells": "Number of Retinal Ganglion (center-surround) cells to model in this layer", - "patch_shape": "Classical Receptive field area shape of individual ganglion cells in this module", - "step_shape": "Extra-Classical Receptive field area shape each ganglion cell in this module", + "n_cells": "Number of retinal ganglion (center-surround) cells to model in this layer", + "patch_shape": "Classical receptive field area shape of individual ganglion cells in this module", + "step_shape": "Extra-classical receptive field area shape each ganglion cell in this module", "batch_size": "Batch size dimension of this component" } info = {cls.__name__: properties, @@ -212,13 +217,15 @@ def help(cls): ## component help function if __name__ == '__main__': from ngcsimlib.context import Context with Context("Bar") as bar: - X = RetinalGanglionCell("RGC", filter_type="gaussian", - sigma=2.3, - area_shape=(16, 26), - n_cells = 3, - patch_shape=(16, 16), - step_shape=(0, 5) - ) + X = RetinalGanglionCell( + "RGC", + filter_type="gaussian", + sigma=2.3, + area_shape=(16, 26), + n_cells = 3, + patch_shape=(16, 16), + step_shape=(0, 5) + ) print(X) From 2a542024c1e242995dff4a8dbccf7a43089dcb94 Mon Sep 17 00:00:00 2001 From: Alexander Ororbia Date: Fri, 1 May 2026 12:53:53 -0400 Subject: [PATCH 7/7] cleanup of metric util --- ngclearn/utils/metric_utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ngclearn/utils/metric_utils.py b/ngclearn/utils/metric_utils.py index 457043cb..ae3c6230 100755 --- a/ngclearn/utils/metric_utils.py +++ b/ngclearn/utils/metric_utils.py @@ -89,9 +89,13 @@ def measure_sparsity(codes, tolerance=0., preserve_batch=True, flip_measure=Fals this matrix is a non-negative vector. Formally, this means we compute, per i-th row: + | rho(x_i) = num_zeros(x_i) / dim(x_i) + and for a global score for matrix X with N codes/rows, we measure: + | rho_mean(X) = 1/N Sum^N_{i=1} rho(x_i) + where lower/closer to 0 means codes more sparse and closer to 1 means codes are more dense.

    Fg70?#m}P3k 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�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 z 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 cHvjM5T(bAM6yU~Avc!$zUwaJWga7~l literal 0 HcmV?d00001 diff --git a/docs/images/museum/hgpc/patch_input.png b/docs/images/museum/hgpc/patch_input.png new file mode 100644 index 0000000000000000000000000000000000000000..4b435212f70a91af5a41af453e4684eb8ff412bc GIT binary patch literal 103373 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