ngclearn 3.2.2__tar.gz → 3.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ngclearn-3.2.2/ngclearn.egg-info → ngclearn-3.2.4}/PKG-INFO +13 -14
- {ngclearn-3.2.2 → ngclearn-3.2.4}/README.md +12 -13
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/__init__.py +8 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/graded/rateCell.py +20 -8
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/__init__.py +7 -0
- ngclearn-3.2.4/ngclearn/components/synapses/attention/__init__.py +5 -0
- ngclearn-3.2.4/ngclearn/components/synapses/attention/attentionPatchedSynapse.py +295 -0
- ngclearn-3.2.4/ngclearn/components/synapses/attention/hebbianAttentionPatchedSynapse.py +398 -0
- ngclearn-3.2.4/ngclearn/components/synapses/attention/scoreAttentionPatchedSynapse.py +377 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/patched/__init__.py +1 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/patched/hebbianPatchedSynapse.py +20 -16
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/patched/patchedSynapse.py +58 -31
- ngclearn-3.2.4/ngclearn/components/synapses/patched/scorePatchedSynapse.py +352 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/patched/staticPatchedSynapse.py +2 -2
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/distribution_generator.py +64 -3
- {ngclearn-3.2.2 → ngclearn-3.2.4/ngclearn.egg-info}/PKG-INFO +13 -14
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn.egg-info/SOURCES.txt +5 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/pyproject.toml +1 -1
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/patched/test_hebbianPatchedSynapse.py +1 -1
- {ngclearn-3.2.2 → ngclearn-3.2.4}/AUTHORS +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/LICENSE +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/input_encoders/TTFSCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/input_encoders/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/input_encoders/bernoulliCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/input_encoders/ganglionCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/input_encoders/latencyCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/input_encoders/phasorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/input_encoders/poissonCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/jaxComponent.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/graded/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/graded/bernoulliErrorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/graded/gaussianErrorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/graded/laplacianErrorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/graded/leakyNoiseCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/graded/rewardErrorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/IFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/LIFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/LIFSRM.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/RAFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/RAFSRM.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/WTASCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/adExCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/fitzhughNagumoCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/hodgkinHuxleyCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/izhikevichCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/quadLIFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/neurons/spiking/sLIFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/other/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/other/expKernel.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/other/varTrace.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/STPDenseSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/alphaSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/competitive/ART2ASynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/competitive/SOMSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/competitive/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/competitive/hopfieldSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/competitive/vectorQuantizeSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/convSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/deconvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/hebbianConvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/hebbianDeconvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/ngcconv.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/staticConvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/staticDeconvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/traceSTDPConvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/convolution/traceSTDPDeconvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/denseSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/doubleExpSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/exponentialSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/BCMSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/STDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/eventSTDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/expSTDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/gerstnerHebbianSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/hebbianSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/inhibitorySTDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/ojaTensorSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/hebbian/traceSTDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/modulated/MSTDPETSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/modulated/REINFORCESynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/modulated/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/mpsSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/sparseTensorSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/staticSparseTensorSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/components/synapses/staticSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/modules/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/modules/regression/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/modules/regression/elastic_net.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/modules/regression/lasso.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/modules/regression/ridge.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/operations/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/JaxProcessesMixin.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/analysis/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/analysis/attentive_probe.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/analysis/effective_dim.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/analysis/kmeans_probe.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/analysis/knn_probe.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/analysis/linear_probe.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/analysis/probe.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/data_loader.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/density/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/density/bernoulliMixture.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/density/exponentialMixture.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/density/gaussianMixture.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/density/mixture.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/diffeq/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/diffeq/ode_utils.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/diffeq/odes.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/feature_dictionaries/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/feature_dictionaries/polynomialLibrary.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/filters/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/filters/cortical_gauss_filter.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/filters/gauss_filter.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/io_utils.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/masks/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/masks/multiblock2d.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/matrix_utils.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/metric_utils.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/model_utils.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/optim/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/optim/adam.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/optim/nag.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/optim/optim_utils.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/optim/sgd.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/patch.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/patch_utils.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/surrogate_fx.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/viz/__init__.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/viz/classification_analysis.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/viz/compartment_plot.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/viz/compartment_raster.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/viz/dim_reduce.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/viz/raster.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/viz/spike_plot.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn/utils/viz/synapse_plot.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn.egg-info/dependency_links.txt +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn.egg-info/requires.txt +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/ngclearn.egg-info/top_level.txt +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/prototypes/components/input_encoders/eventSensorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/prototypes/components/input_encoders/gridCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/prototypes/components/input_encoders/placeCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/prototypes/components/input_encoders/populationCoderCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/prototypes/components/synapses/competitive/simple_ART2ASynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/prototypes/components/synapses/hebbian/canonicalSTDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/prototypes/utils/filters/whitening_filter.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/requirements.txt +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/setup.cfg +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/input_encoders/test_bernoulliCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/input_encoders/test_latencyCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/input_encoders/test_phasorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/input_encoders/test_poissonCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/graded/test_RateCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/graded/test_bernoulliErrorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/graded/test_gaussianErrorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/graded/test_laplacianErrorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/graded/test_leakyNoiseCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/graded/test_rewardErrorCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_IFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_LIFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_RAFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_WTASCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_adExCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_fitzhughNagumoCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_hodgkinHuxleyCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_izhikevichCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_quadLIFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/neurons/spiking/test_sLIFCell.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/other/test_expKernel.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/other/test_varTrace.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/competitve/test_SOMSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/convolution/test_hebbianConvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/convolution/test_hebbianDeconvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/convolution/test_traceSTDPConvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/convolution/test_traceSTDPDeconvSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/hebbian/test_BCMSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/hebbian/test_eventSTDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/hebbian/test_expSTDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/hebbian/test_hebbianSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/hebbian/test_traceSTDPSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/modulated/test_MSTDPETSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/modulated/test_REINFORCESynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/patched/test_patchedSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/test_STPDenseSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/test_exponentialSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/components/synapses/test_mpsSynapse.py +0 -0
- {ngclearn-3.2.2 → ngclearn-3.2.4}/tests/test___init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ngclearn
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.4
|
|
4
4
|
Summary: Simulation software for building and analyzing computational neuroscience models, brain-inspired computing systems, and NeuroAI agents.
|
|
5
5
|
Author-email: Alexander Ororbia <ago@cs.rit.edu>, William Gebhardt <wdg1351@rit.edu>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -40,7 +40,8 @@ Dynamic: license-file
|
|
|
40
40
|
|
|
41
41
|
[](https://www.python.org/downloads)[](https://opensource.org/licenses/BSD-3-Clause)[](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)[](http://ngc-learn.readthedocs.io/en/latest/?badge=latest)[](https://zenodo.org/badge/latestdoi/483413212)
|
|
42
42
|
|
|
43
|
-
<img src="docs/images/ngc-learn-logo.png" width="300">
|
|
43
|
+
<!-- <img src="docs/images/ngc-learn-logo.png" width="300"> -->
|
|
44
|
+
<img src="https://raw.githubusercontent.com/NACLab/ngc-learn/main/docs/images/ngc-learn-logo.png" width="300">
|
|
44
45
|
|
|
45
46
|
<b>ngc-learn</b> is a Python library for building, simulating, and analyzing biophysical / neurobiological systems, spiking neuronal networks, predictive coding circuitry, and biomimetic (NeuroAI) agents that learn in a biologically-plausible manner. This simulation toolkit, meant to support computational neuroscience and brain-inspired computing research, is built on top of JAX and is distributed under the 3-Clause BSD license.
|
|
46
47
|
|
|
@@ -66,24 +67,22 @@ chosen as one of the <i>Editors' Highlights for Applied Physics and Mathematics<
|
|
|
66
67
|
### Dependencies
|
|
67
68
|
|
|
68
69
|
ngc-learn requires:
|
|
69
|
-
1) Python (>=3.
|
|
70
|
-
2) NumPy (>=
|
|
71
|
-
3) SciPy (>=1.
|
|
70
|
+
1) Python (>=3.12)
|
|
71
|
+
2) NumPy (>=2.5.2)
|
|
72
|
+
3) SciPy (>=1.18.1)
|
|
72
73
|
4) ngcsimlib (>=3.1.1), (visit official page <a href="https://github.com/NACLab/ngc-sim-lib">here</a>)
|
|
73
|
-
5) JAX (>=0.
|
|
74
|
+
5) JAX (>=0.11.1) (to enable GPU use, make sure to install one of the CUDA variants)
|
|
74
75
|
<!--
|
|
75
|
-
5) scikit-learn (>=1.3.1) if using `ngclearn.utils.density`
|
|
76
|
-
6) matplotlib (>=3.4.3) if using `ngclearn.utils.viz`
|
|
77
76
|
6) networkx (>=2.6.3) (currently optional but required if using `ngclearn.utils.experimental.viz_utils`)
|
|
78
77
|
7) pyviz (>=0.2.0) (currently optional but required if using `ngclearn.utils.experimental.viz_utils`)
|
|
79
78
|
-->
|
|
80
79
|
|
|
81
80
|
---
|
|
82
|
-
ngc-learn 3.2.
|
|
81
|
+
ngc-learn 3.2.4 and later require Python 3.12 or newer as well as ngcsimlib >=3.1.1.
|
|
83
82
|
ngc-learn's plotting capabilities (routines within `ngclearn.utils.viz`) require
|
|
84
|
-
Matplotlib (>=3.
|
|
85
|
-
tools (routines within ``ngclearn.utils.density``) will require Scikit-learn (>=
|
|
86
|
-
Many of the tutorials will require Matplotlib (>=3.
|
|
83
|
+
Matplotlib (>=3.11.1) and imageio (>=2.37.4) and both plotting and density estimation
|
|
84
|
+
tools (routines within ``ngclearn.utils.density``) will require Scikit-learn (>=1.9.0).
|
|
85
|
+
Many of the tutorials will require Matplotlib (>=3.11.1), imageio (>=2.37.4), and Scikit-learn (>=1.9.0).
|
|
87
86
|
|
|
88
87
|
<i>Note</i>: If you are working with Cuda 12 and want to use jax/jaxlib versions > 0.4.28, you might need to
|
|
89
88
|
check that you are working with the right version of Cudnn (e.g., `nvidia-cudnn-cu12==9.10.2.21`) to ensure
|
|
@@ -133,7 +132,7 @@ Python 3.12.13 (main, MONTH DAY YEAR, TIME) [GCC XX.X.X] on linux
|
|
|
133
132
|
Type "help", "copyright", "credits" or "license" for more information.
|
|
134
133
|
>>> import ngclearn
|
|
135
134
|
>>> ngclearn.__version__
|
|
136
|
-
'3.2.
|
|
135
|
+
'3.2.4'
|
|
137
136
|
```
|
|
138
137
|
|
|
139
138
|
<i>Note:</i> For access to the previous Tensorflow-2 version of ngc-learn (of
|
|
@@ -180,7 +179,7 @@ $ python install -e .
|
|
|
180
179
|
</pre>
|
|
181
180
|
|
|
182
181
|
**Version:**<br>
|
|
183
|
-
3.2.
|
|
182
|
+
3.2.4
|
|
184
183
|
|
|
185
184
|
Author:
|
|
186
185
|
Alexander G. Ororbia II<br>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
[](https://www.python.org/downloads)[](https://opensource.org/licenses/BSD-3-Clause)[](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)[](http://ngc-learn.readthedocs.io/en/latest/?badge=latest)[](https://zenodo.org/badge/latestdoi/483413212)
|
|
2
2
|
|
|
3
|
-
<img src="docs/images/ngc-learn-logo.png" width="300">
|
|
3
|
+
<!-- <img src="docs/images/ngc-learn-logo.png" width="300"> -->
|
|
4
|
+
<img src="https://raw.githubusercontent.com/NACLab/ngc-learn/main/docs/images/ngc-learn-logo.png" width="300">
|
|
4
5
|
|
|
5
6
|
<b>ngc-learn</b> is a Python library for building, simulating, and analyzing biophysical / neurobiological systems, spiking neuronal networks, predictive coding circuitry, and biomimetic (NeuroAI) agents that learn in a biologically-plausible manner. This simulation toolkit, meant to support computational neuroscience and brain-inspired computing research, is built on top of JAX and is distributed under the 3-Clause BSD license.
|
|
6
7
|
|
|
@@ -26,24 +27,22 @@ chosen as one of the <i>Editors' Highlights for Applied Physics and Mathematics<
|
|
|
26
27
|
### Dependencies
|
|
27
28
|
|
|
28
29
|
ngc-learn requires:
|
|
29
|
-
1) Python (>=3.
|
|
30
|
-
2) NumPy (>=
|
|
31
|
-
3) SciPy (>=1.
|
|
30
|
+
1) Python (>=3.12)
|
|
31
|
+
2) NumPy (>=2.5.2)
|
|
32
|
+
3) SciPy (>=1.18.1)
|
|
32
33
|
4) ngcsimlib (>=3.1.1), (visit official page <a href="https://github.com/NACLab/ngc-sim-lib">here</a>)
|
|
33
|
-
5) JAX (>=0.
|
|
34
|
+
5) JAX (>=0.11.1) (to enable GPU use, make sure to install one of the CUDA variants)
|
|
34
35
|
<!--
|
|
35
|
-
5) scikit-learn (>=1.3.1) if using `ngclearn.utils.density`
|
|
36
|
-
6) matplotlib (>=3.4.3) if using `ngclearn.utils.viz`
|
|
37
36
|
6) networkx (>=2.6.3) (currently optional but required if using `ngclearn.utils.experimental.viz_utils`)
|
|
38
37
|
7) pyviz (>=0.2.0) (currently optional but required if using `ngclearn.utils.experimental.viz_utils`)
|
|
39
38
|
-->
|
|
40
39
|
|
|
41
40
|
---
|
|
42
|
-
ngc-learn 3.2.
|
|
41
|
+
ngc-learn 3.2.4 and later require Python 3.12 or newer as well as ngcsimlib >=3.1.1.
|
|
43
42
|
ngc-learn's plotting capabilities (routines within `ngclearn.utils.viz`) require
|
|
44
|
-
Matplotlib (>=3.
|
|
45
|
-
tools (routines within ``ngclearn.utils.density``) will require Scikit-learn (>=
|
|
46
|
-
Many of the tutorials will require Matplotlib (>=3.
|
|
43
|
+
Matplotlib (>=3.11.1) and imageio (>=2.37.4) and both plotting and density estimation
|
|
44
|
+
tools (routines within ``ngclearn.utils.density``) will require Scikit-learn (>=1.9.0).
|
|
45
|
+
Many of the tutorials will require Matplotlib (>=3.11.1), imageio (>=2.37.4), and Scikit-learn (>=1.9.0).
|
|
47
46
|
|
|
48
47
|
<i>Note</i>: If you are working with Cuda 12 and want to use jax/jaxlib versions > 0.4.28, you might need to
|
|
49
48
|
check that you are working with the right version of Cudnn (e.g., `nvidia-cudnn-cu12==9.10.2.21`) to ensure
|
|
@@ -93,7 +92,7 @@ Python 3.12.13 (main, MONTH DAY YEAR, TIME) [GCC XX.X.X] on linux
|
|
|
93
92
|
Type "help", "copyright", "credits" or "license" for more information.
|
|
94
93
|
>>> import ngclearn
|
|
95
94
|
>>> ngclearn.__version__
|
|
96
|
-
'3.2.
|
|
95
|
+
'3.2.4'
|
|
97
96
|
```
|
|
98
97
|
|
|
99
98
|
<i>Note:</i> For access to the previous Tensorflow-2 version of ngc-learn (of
|
|
@@ -140,7 +139,7 @@ $ python install -e .
|
|
|
140
139
|
</pre>
|
|
141
140
|
|
|
142
141
|
**Version:**<br>
|
|
143
|
-
3.2.
|
|
142
|
+
3.2.4
|
|
144
143
|
|
|
145
144
|
Author:
|
|
146
145
|
Alexander G. Ororbia II<br>
|
|
@@ -73,5 +73,13 @@ from .synapses.modulated.REINFORCESynapse import REINFORCESynapse
|
|
|
73
73
|
## point to patched component types
|
|
74
74
|
from .synapses.patched.patchedSynapse import PatchedSynapse
|
|
75
75
|
from .synapses.patched.staticPatchedSynapse import StaticPatchedSynapse
|
|
76
|
+
from .synapses.patched.scorePatchedSynapse import ScorePatchedSynapse
|
|
76
77
|
from .synapses.patched.hebbianPatchedSynapse import HebbianPatchedSynapse
|
|
77
78
|
|
|
79
|
+
## point to attention patched synaptic components
|
|
80
|
+
from .synapses.attention.attentionPatchedSynapse import AttentionPatchedSynapse
|
|
81
|
+
from .synapses.attention.hebbianAttentionPatchedSynapse import HebbianAttentionPatchedSynapse
|
|
82
|
+
from .synapses.attention.scoreAttentionPatchedSynapse import ScoreAttentionPatchedSynapse
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
@@ -49,7 +49,6 @@ def _modulate(j, dfx_val):
|
|
|
49
49
|
"""
|
|
50
50
|
return j * dfx_val
|
|
51
51
|
|
|
52
|
-
# @partial(jit, static_argnames=["integType", "priorType"])
|
|
53
52
|
def _run_cell(dt, j, j_td, z, tau_m, leak_gamma=0., integType=0, priorType=0):
|
|
54
53
|
"""
|
|
55
54
|
Runs leaky rate-coded state dynamics one step in time.
|
|
@@ -166,7 +165,7 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
166
165
|
|
|
167
166
|
use_lateral: determines wheter the RateCell uses lateral pressure during inference (Default: False)
|
|
168
167
|
|
|
169
|
-
n_patch: the number of local patches in each layer (equivalent to
|
|
168
|
+
n_patch: the number of local patches in each layer (equivalent to n_patch in PatchedSynapse) (Default: 1)
|
|
170
169
|
|
|
171
170
|
adaptive_lateral: if True, lateral synaptic is adaptive using HebbianPatchedSynapse component,
|
|
172
171
|
if False, lateral synaptic is a static using StaticPatchedSynapse component
|
|
@@ -265,7 +264,7 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
265
264
|
|
|
266
265
|
if adaptive_lateral:
|
|
267
266
|
self.Wl = HebbianPatchedSynapse(f"Wl_{name}", shape=(n_units, n_units),
|
|
268
|
-
|
|
267
|
+
n_patch=n_patch,
|
|
269
268
|
weight_init=dist.diag_offdiag(on_diag=exc, off_diag=inh),
|
|
270
269
|
eta=Wl_eta,
|
|
271
270
|
prior=Wl_prior,
|
|
@@ -275,7 +274,7 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
275
274
|
)
|
|
276
275
|
else:
|
|
277
276
|
self.Wl = StaticPatchedSynapse(f"Wl_{name}", shape=(n_units, n_units),
|
|
278
|
-
|
|
277
|
+
n_patch=n_patch,
|
|
279
278
|
weight_init=dist.diag_offdiag(on_diag=exc, off_diag=inh),
|
|
280
279
|
batch_size=batch_size,
|
|
281
280
|
)
|
|
@@ -288,6 +287,8 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
288
287
|
self.zF = Compartment(restVals, display_name="Transformed Rate Activity") # rate-coded output - activity
|
|
289
288
|
self.j_td = Compartment(restVals, display_name="Modulatory Stimulus Current", units="mA") # top-down electrical current - pressure
|
|
290
289
|
self.z = Compartment(restVals, display_name="Rate Activity", units="mA") # rate activity
|
|
290
|
+
self.mu_top = Compartment(restVals, display_name="Rate Activity", units="mA") # rate activity
|
|
291
|
+
self.mu_top_zF = Compartment(restVals, display_name="Transformed Rate Activity") # rate-coded output - activity
|
|
291
292
|
## lateral compartments
|
|
292
293
|
if use_lateral:
|
|
293
294
|
self.j_lat = Compartment(restVals, display_name="Lateral Stimulus Current", units="mA") # lateral current
|
|
@@ -309,6 +310,7 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
309
310
|
j = self.j.get()
|
|
310
311
|
j_td = self.j_td.get()
|
|
311
312
|
z = self.z.get()
|
|
313
|
+
mu_top = self.mu_top.get()
|
|
312
314
|
|
|
313
315
|
if self.is_stateful:
|
|
314
316
|
## ════════════════════════════════════════════════════════════════
|
|
@@ -320,7 +322,6 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
320
322
|
dfx_val = self.dfx(z)
|
|
321
323
|
j = _modulate(j, dfx_val)
|
|
322
324
|
j = j * self.resist_scale
|
|
323
|
-
|
|
324
325
|
## ══════════════════════════
|
|
325
326
|
## Calculate lateral pressure
|
|
326
327
|
if self.use_lateral:
|
|
@@ -355,6 +356,7 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
355
356
|
## ════════════════════════════════════════════════════════════════
|
|
356
357
|
## run in "stateless" mode (when no membrane time constant provided)
|
|
357
358
|
z = _run_cell_stateless(j + j_td) ## (j+j_td) >> z
|
|
359
|
+
mu_top = _run_cell_stateless(mu_top)
|
|
358
360
|
|
|
359
361
|
## ═══════════════════════════════════════════════
|
|
360
362
|
## fx(z) >> zF post-activation function value(s)
|
|
@@ -363,11 +365,16 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
363
365
|
zF_lat = self.fx_lat(z) * self.output_scale
|
|
364
366
|
|
|
365
367
|
## ════════════════════
|
|
368
|
+
mu_top_zF = self.fx(mu_top) * self.output_scale
|
|
369
|
+
|
|
370
|
+
## ═══════════════════════════════════════════════
|
|
366
371
|
## Update compartments
|
|
367
372
|
self.j.set(j)
|
|
368
373
|
self.j_td.set(j_td)
|
|
369
374
|
self.z.set(z)
|
|
370
375
|
self.zF.set(zF)
|
|
376
|
+
self.mu_top.set(mu_top)
|
|
377
|
+
self.mu_top_zF.set(mu_top_zF)
|
|
371
378
|
if self.use_lateral:
|
|
372
379
|
self.j_lat.set(j_lat)
|
|
373
380
|
self.zF_lat.set(zF_lat)
|
|
@@ -391,6 +398,8 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
391
398
|
self.j_td.set(restVals)
|
|
392
399
|
self.z.set(restVals)
|
|
393
400
|
self.zF.set(restVals)
|
|
401
|
+
self.mu_top.set(restVals)
|
|
402
|
+
self.mu_top_zF.set(restVals)
|
|
394
403
|
|
|
395
404
|
if self.use_lateral:
|
|
396
405
|
self.Wl.reset()
|
|
@@ -417,13 +426,16 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
417
426
|
"inputs":
|
|
418
427
|
{"j": "External input stimulus value(s)",
|
|
419
428
|
"j_td": "External top-down input stimulus value(s); these get "
|
|
420
|
-
"multiplied by the derivative of f(x), i.e., df(x)"
|
|
429
|
+
"multiplied by the derivative of f(x), i.e., df(x)",
|
|
430
|
+
"mu_top": "Top-down Prediction"},
|
|
421
431
|
"states":
|
|
422
432
|
{"z": "Update to rate-coded continuous dynamics; value at time t"},
|
|
423
433
|
"outputs":
|
|
424
434
|
{"zF": "Nonlinearity/function applied to rate-coded dynamics; f(z)",
|
|
425
435
|
"zF_lat": "(if use_lateral is True) zF for lateral fx_lat(z)",
|
|
426
|
-
"j_lat": "(if use_lateral is True) lateral pressure"
|
|
436
|
+
"j_lat": "(if use_lateral is True) lateral pressure",
|
|
437
|
+
"mu_top_zF": "Nonlinearity/function applied to the top-down prediction",
|
|
438
|
+
},
|
|
427
439
|
}
|
|
428
440
|
hyperparams = {
|
|
429
441
|
"n_units": "Number of neuronal cells to model in this layer",
|
|
@@ -434,7 +446,7 @@ class RateCell(JaxComponent): ## Rate-coded/real-valued cell
|
|
|
434
446
|
"threshold": "What kind of iterative thresholding function to place over neuronal dynamics?",
|
|
435
447
|
"integration_type": "Type of numerical integration to use for the cell dynamics",
|
|
436
448
|
"use_lateral": "If lateral synaptic is active for inference",
|
|
437
|
-
"n_patch": "Number of block-diagonal local lateral synaptic patch (
|
|
449
|
+
"n_patch": "Number of block-diagonal local lateral synaptic patch (n_patch of `Wl`)",
|
|
438
450
|
"adaptive_lateral": "Adaptive lateral synapses (HebbianPatchedSynapse) or static lateral synaptic (StaticPatchedSynapse)",
|
|
439
451
|
"Wl_eta": "Learning rate for the lateral synapses",
|
|
440
452
|
"exc_inh": "(exc, inh) lateral synapses initial values. On-diagonal takes exc>0 and off-diagonal takes inh<0",
|
|
@@ -39,5 +39,12 @@ from .modulated.MSTDPETSynapse import MSTDPETSynapse
|
|
|
39
39
|
## patched synaptic components
|
|
40
40
|
from .patched.patchedSynapse import PatchedSynapse
|
|
41
41
|
from .patched.staticPatchedSynapse import StaticPatchedSynapse
|
|
42
|
+
from .patched.scorePatchedSynapse import ScorePatchedSynapse
|
|
42
43
|
from .patched.hebbianPatchedSynapse import HebbianPatchedSynapse
|
|
43
44
|
|
|
45
|
+
## attention patched synaptic components
|
|
46
|
+
from .attention.attentionPatchedSynapse import AttentionPatchedSynapse
|
|
47
|
+
from .attention.hebbianAttentionPatchedSynapse import HebbianAttentionPatchedSynapse
|
|
48
|
+
from .attention.scoreAttentionPatchedSynapse import ScoreAttentionPatchedSynapse
|
|
49
|
+
|
|
50
|
+
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# %%
|
|
2
|
+
from jax import random, numpy as jnp, nn
|
|
3
|
+
from ngclearn.components.jaxComponent import JaxComponent
|
|
4
|
+
from ngclearn.utils.distribution_generator import DistributionGenerator
|
|
5
|
+
from ngcsimlib.logger import info
|
|
6
|
+
from ngclearn import compilable, Compartment
|
|
7
|
+
|
|
8
|
+
def _create_attention_synapses(key, shape, n_patch, use_value=True, init_type=DistributionGenerator.fan_in_gaussian()):
|
|
9
|
+
key, *subkey = random.split(key, 10)
|
|
10
|
+
|
|
11
|
+
patch_shape = (shape[0] // n_patch, shape[1] // n_patch)
|
|
12
|
+
di, dj = patch_shape
|
|
13
|
+
n_weight = 3 if use_value else 2 ## synapses: query, key, value (optional)
|
|
14
|
+
|
|
15
|
+
weight_shape = (di, n_weight * dj)
|
|
16
|
+
weights = jnp.zeros(weight_shape)
|
|
17
|
+
w_masks = jnp.zeros(weight_shape)
|
|
18
|
+
|
|
19
|
+
for i in range(n_weight): ## W = (Wq, Wk, Wv)
|
|
20
|
+
start_j = i * dj
|
|
21
|
+
end_j = (i + 1) * dj
|
|
22
|
+
|
|
23
|
+
weights = weights.at[:, start_j : end_j].set(init_type(patch_shape, subkey[i]))
|
|
24
|
+
w_masks = w_masks.at[:, start_j : end_j].set(jnp.ones(patch_shape))
|
|
25
|
+
|
|
26
|
+
return weights, patch_shape, w_masks
|
|
27
|
+
|
|
28
|
+
def _split_heads(t, n_heads):
|
|
29
|
+
"""
|
|
30
|
+
(batch_size, n_patch, d) -> (batch_size, n_heads, n_patch, d / n_heads)
|
|
31
|
+
"""
|
|
32
|
+
return t.reshape(t.shape[0], t.shape[1], n_heads, -1).transpose(0, 2, 1, 3)
|
|
33
|
+
|
|
34
|
+
def _merge_heads(t):
|
|
35
|
+
"""
|
|
36
|
+
(batch_size, n_heads, n_patch, d / n_heads) -> (batch_size, n_patch, d)
|
|
37
|
+
"""
|
|
38
|
+
return t.transpose(0, 2, 1, 3).reshape(t.shape[0], t.shape[2], -1)
|
|
39
|
+
|
|
40
|
+
def _attend(inputs, W, b, n_patch, n_heads=1, use_value=True):
|
|
41
|
+
"""
|
|
42
|
+
(zF W + b) -> y = softmax(q k.T / sqrt(d_h)) v
|
|
43
|
+
"""
|
|
44
|
+
zF = inputs.reshape(inputs.shape[0], n_patch, -1) ## (B, n, d)
|
|
45
|
+
q_k_v = (zF @ W) + b ## q_k_v: (B, n, d)
|
|
46
|
+
|
|
47
|
+
if use_value:
|
|
48
|
+
q, k, v = jnp.split(q_k_v, 3, axis=2) ## q, k v projections of every patch
|
|
49
|
+
else:
|
|
50
|
+
q, k = jnp.split(q_k_v, 2, axis=2) ## v = zF
|
|
51
|
+
v = zF
|
|
52
|
+
|
|
53
|
+
q = _split_heads(q, n_heads) ## Reshape: (B, n, d) -> (B, H, n, d/H)
|
|
54
|
+
k = _split_heads(k, n_heads) ## Reshape: (B, n, d) -> (_, H, _, d/H)
|
|
55
|
+
v = _split_heads(v, n_heads) ## Reshape: (B, n, d) -> (_, H, _, d/H)
|
|
56
|
+
## attention score
|
|
57
|
+
rd = jnp.sqrt(q.shape[3])
|
|
58
|
+
s = (q @ k.transpose(0, 1, 3, 2)) / rd ## (B, H, n, d/H) @ (B, H, d/H, n)
|
|
59
|
+
## probability
|
|
60
|
+
A = nn.softmax(s, axis=-1)
|
|
61
|
+
y = _merge_heads(A @ v) ## Reshape.T: (B, H, n, d/H) -> (B, n, d)
|
|
62
|
+
return y.reshape(y.shape[0], -1), (zF, q, k, v, s, A)
|
|
63
|
+
|
|
64
|
+
def _attend_backward(e, attention_params, n_heads=1):
|
|
65
|
+
"""
|
|
66
|
+
d_qkv = (chain rule through softmax(q k.T / sqrt(d_h)) v)
|
|
67
|
+
Passes a post-synaptic signal back through the attention mixing to the (q, k, v) projections of every patch
|
|
68
|
+
"""
|
|
69
|
+
zF, q, k, v, s, A = attention_params
|
|
70
|
+
rd = jnp.sqrt(q.shape[3])
|
|
71
|
+
e = _split_heads(e.reshape(e.shape[0], zF.shape[1], -1), n_heads) ## Reshape: (B, n, d) -> (_, H, _, d/H)
|
|
72
|
+
dv = A.transpose(0, 1, 3, 2) @ e
|
|
73
|
+
dA = e @ v.transpose(0, 1, 3, 2)
|
|
74
|
+
dS = A * (dA - jnp.sum(dA * A, axis=-1, keepdims=True)) / rd
|
|
75
|
+
dq = dS @ k
|
|
76
|
+
dk = dS.transpose(0, 1, 3, 2) @ q
|
|
77
|
+
return jnp.concatenate([_merge_heads(dq), ## Reshape.T: (B, H, n, d/H) -> (B, n, d)
|
|
78
|
+
_merge_heads(dk), ## Reshape.T: (B, H, n, d/H) -> (B, n, d)
|
|
79
|
+
_merge_heads(dv)], ## Reshape.T: (B, H, n, d/H) -> (B, n, d)
|
|
80
|
+
axis=2)
|
|
81
|
+
|
|
82
|
+
def _backtransmit(e, attention_params, W, n_heads=1, use_value=True):
|
|
83
|
+
"""
|
|
84
|
+
pre_out = dq * Wq.T + dk * Wk.T + dv (v = zF) (chain rule through the weights)
|
|
85
|
+
"""
|
|
86
|
+
d_qkv = _attend_backward(e, attention_params, n_heads)
|
|
87
|
+
dzF = d_qkv[:, :, 0:W.shape[1]] @ W.T
|
|
88
|
+
if not use_value: ## (v = zF): the value signal passes straight back
|
|
89
|
+
dzF = dzF + d_qkv[:, :, W.shape[1]:]
|
|
90
|
+
return dzF.reshape(dzF.shape[0], -1)
|
|
91
|
+
|
|
92
|
+
class AttentionPatchedSynapse(JaxComponent): ## base attention patched synaptic cable
|
|
93
|
+
"""
|
|
94
|
+
A patched self-attention synaptic cable that lets the patches (tokens) of a layer attend to one another, i.e., it
|
|
95
|
+
transforms inputs via multi-head self-attention through a single set of query, key, and value synapses that is
|
|
96
|
+
shared by every patch, no form of synaptic evolution/adaptation is in-built to this component.
|
|
97
|
+
|
|
98
|
+
| --- Synapse Compartments: ---
|
|
99
|
+
| inputs - input (takes in external signals)
|
|
100
|
+
| outputs - output signals (transformation induced by synapses)
|
|
101
|
+
| project_input - input of the projection pathway (takes in external signals)
|
|
102
|
+
| project_output - output signals of the projection pathway (transformation induced by synapses)
|
|
103
|
+
| post_in - post-synaptic input of the backward pathway (takes in external signals)
|
|
104
|
+
| pre_out - pre-synaptic output signals of the backward pathway (post_in carried back across the synapses)
|
|
105
|
+
| weights - current value matrix of synaptic efficacies, the query, key, and value synapses W = (Wq, Wk, Wv)
|
|
106
|
+
| biases - current value vector of synaptic bias values, b = (bq, bk, bv)
|
|
107
|
+
| key - JAX PRNG key
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
name: the string name of this cell
|
|
111
|
+
|
|
112
|
+
shape: tuple specifying shape of this synaptic cable (usually a 2-tuple
|
|
113
|
+
with number of inputs by number of outputs), every patch gets
|
|
114
|
+
shape[0] / n_patch input and shape[1] / n_patch output
|
|
115
|
+
features (these must be equal if use_value=False)
|
|
116
|
+
|
|
117
|
+
n_patch: The number of patches (tokens) in each layer (Default: 1)
|
|
118
|
+
|
|
119
|
+
n_heads: The number of attention heads, each head attends over
|
|
120
|
+
(shape[1] / n_patch) / n_heads features (Default: 1)
|
|
121
|
+
|
|
122
|
+
use_value: if False, the value synapses are fixed to the identity (v = zF)
|
|
123
|
+
and are left out of `weights`, i.e., W = (Wq, Wk) (Default: True)
|
|
124
|
+
|
|
125
|
+
weight_init: a kernel to drive initialization of this synaptic cable's values;
|
|
126
|
+
typically a tuple with 1st element as a string calling the name of
|
|
127
|
+
initialization to use
|
|
128
|
+
|
|
129
|
+
bias_init: a kernel to drive initialization of biases for this synaptic cable
|
|
130
|
+
(Default: None, which turns off/disables biases)
|
|
131
|
+
|
|
132
|
+
resist_scale: a fixed scaling factor to apply to synaptic transform
|
|
133
|
+
(Default: 1.), i.e., yields: out = attention(in; W, b) * Rscale
|
|
134
|
+
|
|
135
|
+
p_conn: probability of a connection existing (default: 1.); setting
|
|
136
|
+
this to < 1. will result in a sparser synaptic structure
|
|
137
|
+
|
|
138
|
+
batch_size: the size of each mini batch
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
def __init__(self, name, shape, n_patch=1, n_heads=1, use_value=True, weight_init=None, bias_init=None,
|
|
142
|
+
resist_scale=1., p_conn=1., batch_size=1, **kwargs
|
|
143
|
+
):
|
|
144
|
+
super().__init__(name, **kwargs)
|
|
145
|
+
|
|
146
|
+
self.Rscale = resist_scale
|
|
147
|
+
self.batch_size = batch_size
|
|
148
|
+
self.weight_init = weight_init
|
|
149
|
+
self.bias_init = bias_init
|
|
150
|
+
|
|
151
|
+
self.n_patch = n_patch
|
|
152
|
+
self.n_heads = n_heads
|
|
153
|
+
self.use_value = use_value
|
|
154
|
+
|
|
155
|
+
tmp_key, *subkeys = random.split(self.key.get(), 4)
|
|
156
|
+
if self.weight_init is None:
|
|
157
|
+
info(self.name, "is using default weight initializer!")
|
|
158
|
+
self.weight_init = DistributionGenerator.fan_in_gaussian()
|
|
159
|
+
|
|
160
|
+
weights, self.patch_shape, self.w_masks = _create_attention_synapses(
|
|
161
|
+
key=tmp_key, shape=shape, n_patch=self.n_patch, use_value=self.use_value,
|
|
162
|
+
init_type=self.weight_init
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
self.shape = shape ## input x output same for all weights (Wq, Wk, Wv)
|
|
166
|
+
|
|
167
|
+
if 0. < p_conn < 1.: ## only non-zero and <1 probs allowed
|
|
168
|
+
mask = random.bernoulli(subkeys[1], p=p_conn, shape=weights.shape)
|
|
169
|
+
weights = weights * mask ## sparsify matrix
|
|
170
|
+
|
|
171
|
+
## Compartment setup
|
|
172
|
+
self.weights = Compartment(weights)
|
|
173
|
+
|
|
174
|
+
preVals = jnp.zeros((self.batch_size, self.shape[0]))
|
|
175
|
+
postVals = jnp.zeros((self.batch_size, self.shape[1]))
|
|
176
|
+
|
|
177
|
+
self.inputs = Compartment(preVals)
|
|
178
|
+
self.outputs = Compartment(postVals)
|
|
179
|
+
|
|
180
|
+
self.project_input = Compartment(preVals)
|
|
181
|
+
self.project_output = Compartment(postVals)
|
|
182
|
+
|
|
183
|
+
self.post_in = Compartment(postVals)
|
|
184
|
+
self.pre_out = Compartment(preVals)
|
|
185
|
+
|
|
186
|
+
## Set up (optional) bias values
|
|
187
|
+
if self.bias_init is None:
|
|
188
|
+
info(self.name, "is using default bias value of zero (no bias kernel provided)!")
|
|
189
|
+
self.biases = Compartment(self.bias_init((1, weights.shape[1]), subkeys[2]) if bias_init else 0.0)
|
|
190
|
+
|
|
191
|
+
@compilable
|
|
192
|
+
def advance_state(self):
|
|
193
|
+
# Get the variables
|
|
194
|
+
weights = self.weights.get()
|
|
195
|
+
biases = self.biases.get()
|
|
196
|
+
|
|
197
|
+
################### inputs → attention(W)= A @ v → outputs
|
|
198
|
+
inputs = self.inputs.get() ## zF
|
|
199
|
+
## Compute (zF @ W) -> softmax(q k.T / sqrt(d_h)) v
|
|
200
|
+
outputs, attention_params = _attend(inputs, weights, biases, self.n_patch, self.n_heads, self.use_value)
|
|
201
|
+
_, q, k, v, s, A = attention_params
|
|
202
|
+
outputs = outputs * self.Rscale
|
|
203
|
+
## Update outputs compartment
|
|
204
|
+
self.outputs.set(outputs)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
################### post_in → (d_qkv @ W.T) → pre_out
|
|
208
|
+
post_in = self.post_in.get()
|
|
209
|
+
## Compute attention(post_in, W.T)
|
|
210
|
+
pre_out = _backtransmit(post_in, attention_params, weights, self.n_heads, self.use_value)
|
|
211
|
+
## Update pre_out compartment
|
|
212
|
+
self.pre_out.set(pre_out)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
################### project_input → attention(W) → project_output
|
|
216
|
+
project_input = self.project_input.get()
|
|
217
|
+
## Compute attention(project_input, W)
|
|
218
|
+
project_output, _ = _attend(project_input, weights, biases, self.n_patch, self.n_heads, self.use_value)
|
|
219
|
+
project_output = project_output * self.Rscale
|
|
220
|
+
## Update project_output compartment
|
|
221
|
+
self.project_output.set(project_output)
|
|
222
|
+
|
|
223
|
+
@compilable
|
|
224
|
+
def reset(self): ## closed, no-batch argument reset
|
|
225
|
+
## write reset command to call inner batched_reset command
|
|
226
|
+
self.batched_reset(batch_size=self.batch_size) ## arg = batch_size data-member
|
|
227
|
+
|
|
228
|
+
@compilable
|
|
229
|
+
def batched_reset(self, batch_size): ## open, batch argument reset
|
|
230
|
+
preVals = jnp.zeros((batch_size, self.shape[0]))
|
|
231
|
+
postVals = jnp.zeros((batch_size, self.shape[1]))
|
|
232
|
+
|
|
233
|
+
# BUG: the self.inputs here does not have the targeted field
|
|
234
|
+
# NOTE: Quick workaround is to check if targeted is in the input or not
|
|
235
|
+
hasattr(self.inputs, "targeted") and not self.inputs.targeted and self.inputs.set(preVals)
|
|
236
|
+
self.outputs.set(postVals)
|
|
237
|
+
self.post_in.set(postVals)
|
|
238
|
+
self.pre_out.set(preVals)
|
|
239
|
+
self.project_input.set(preVals)
|
|
240
|
+
self.project_output.set(postVals)
|
|
241
|
+
|
|
242
|
+
@classmethod
|
|
243
|
+
def help(cls): ## component help function
|
|
244
|
+
properties = {
|
|
245
|
+
"synapse_type": "AttentionPatchedSynapse - performs a synaptic transformation "
|
|
246
|
+
"of inputs to produce output signals (e.g., a multi-head "
|
|
247
|
+
"self-attention transformation across the patches of a layer)"
|
|
248
|
+
}
|
|
249
|
+
compartment_props = {
|
|
250
|
+
"inputs":
|
|
251
|
+
{"inputs": "Takes in external input signal values",
|
|
252
|
+
"project_input": "Takes in external input signal values",
|
|
253
|
+
"post_in": "Takes in external input signal values",
|
|
254
|
+
},
|
|
255
|
+
"states":
|
|
256
|
+
{"weights": "Synapse efficacy/strength parameter values (query, key, and value synapses)",
|
|
257
|
+
"biases": "Base-rate/bias parameter values (query, key, and value biases)",
|
|
258
|
+
"key": "JAX PRNG key"},
|
|
259
|
+
"outputs":
|
|
260
|
+
{"outputs": "Output of synaptic transformation",
|
|
261
|
+
"project_output": "Output of synaptic transformation",
|
|
262
|
+
"pre_out": "Output of synaptic transformation",
|
|
263
|
+
},
|
|
264
|
+
}
|
|
265
|
+
hyperparams = {
|
|
266
|
+
"shape": "Overall shape of synaptic cable, number inputs x number outputs",
|
|
267
|
+
"n_patch": "The number of patches (tokens) in each layer",
|
|
268
|
+
"n_heads": "The number of attention heads",
|
|
269
|
+
"use_value": "Are the value synapses adaptive? (otherwise, they are fixed to the identity)",
|
|
270
|
+
"batch_size": "Batch size dimension of this component",
|
|
271
|
+
"weight_init": "Initialization conditions for synaptic weight (W) values",
|
|
272
|
+
"bias_init": "Initialization conditions for bias/base-rate (b) values",
|
|
273
|
+
"resist_scale": "Resistance level scaling factor (Rscale), applied to output of transformation",
|
|
274
|
+
"w_masks": "weight mask matrix",
|
|
275
|
+
"p_conn": "Probability of a connection existing (otherwise, it is masked to zero)"
|
|
276
|
+
}
|
|
277
|
+
info = {cls.__name__: properties,
|
|
278
|
+
"compartments": compartment_props,
|
|
279
|
+
"dynamics": "outputs = [softmax((inputs * Wq + bq) * (inputs * Wk + bk).T / sqrt(d)) * (inputs * Wv + bv)] * Rscale",
|
|
280
|
+
"hyperparameters": hyperparams}
|
|
281
|
+
return info
|
|
282
|
+
|
|
283
|
+
if __name__ == '__main__':
|
|
284
|
+
from ngcsimlib.context import Context
|
|
285
|
+
|
|
286
|
+
with Context("Bar") as bar:
|
|
287
|
+
Wab = AttentionPatchedSynapse("Wab", (9, 9), 3)
|
|
288
|
+
print(Wab)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|