An implementation of the Self-Normalizing Spike-Timing-Dependent Plasticity (STDP) learning rule in Brian 2. This supports both SMAX and SMIN rule variants.
Original Paper: Genevieve C. Fahey, Samuel J. Ippolito, and Glenn I. Matthews, 'A linear self-normalizing spike-timing-dependent plasticity rule for online learning in spiking neural networks', Neurocomputing, 2026. DOI: https://doi.org/10.1016/j.neucom.2026.133419
This is NOT the code used to produce the results in the original paper. It is instead supplied as an example implementation for use with Brian 2 using the updated SNN experiment code from Diehl & Cook (DOI: https://doi.org/10.3389/fncom.2015.00099). The code used to produce the published results uses the SwiftSpike simulation framework which is not yet available on Github.
The Self-Normalizing STDP rule allows individual synapses to update their weights in such a way that the
The Self-Normalizing STDP rule updates all weights on each post-synaptic spike event and is given by:
where
When a post-synaptic spike occurs, all synapses update their weights and the
The 'SMAX' variant of the Self-Normalizing STDP rule is used for weight vectors containing only non-negative values. In this instance, $s_{min} is always set to 0. The
The 'SMIN' variant is used for weight vectors containing both negative and positive weight values and calculates
The Self-Normalizing STDP rule is intended for neuromorphic hardware where divisive weight normalization methods are difficult to implement. The self-normalizing aspect of our method (that of calculating and updating the scaling maximum and minimum terms) has O(1) space complexity compared to the O(n) space complexity of divisive weight normalization, improving its viability on systems with memory-access constraints.
During simulation, it was observed that if the inhibitory conductance
This code expands on the repository for the updated Diehl & Cook experiment here: https://github.com/GenevieveF/Diehl-Cook_2015_Brian2.
It also requires Python 3, Brian 2, and the MNIST dataset.
Installation instructions and directions for use are included in full in the readme of the linked repository. Please follow the instructions to install the required packages, then add the 'Self-Normalizing_STDP_Rule_B2.py' file alongside the python files. Run 'Self-Normalizing_STDP_Rule_B2.py' in place of 'Diehl&Cook_spiking_MNIST_B2.py'.
Installation instructions for Brain 2 can be found here: https://briansimulator.org/
The MNIST dataset can be found here: http://yann.lecun.com/exdb/mnist/
For training a network:
- Set test_mode = False on line 205 in 'Self-Normalizing_STDP_Rule_B2.py'.
- Set save_name to your preferred filename suffix for the saved weights and theta values. These will be saved to the 'weights/' folder.
- Run the code.
For testing a network:
- Set test_mode = True on line 205 in 'Self-Normalizing_STDP_Rule_B2.py'.
- Set load_name = save_name to use your trained weights. Set load_name = '' to run a test using the pre-trained weights from the original repository.
- Run the code.
- Result files for classification will be saved in the 'activity/' folder with num_examples as a suffix. Be sure to back them up somewhere safe if you do not wish for these to be over-written every time a new simulation is performed.
For evaluating a network's classification performance:
- In 'Diehl&Cook_MNIST_evaluation_B2.py' set training_ending = 'x' and testing_ending = 'y' where x is the number of examples used during training and y is the number of examples used during testing of the network. The defaults are x = '60000' and y = '10000'.
- Run the code.
-
How can I run this for networks with a different number of neurons?
Change n_e on line 241 to your desired number of neurons. Uncomment line 402 and comment out lines 404 and 405. This will force the code to generate random weights to initialise the network rather than load the pre-generated 400 weights from a file. -
The simulation is very slow on my computer, how can I make it faster?
Consider changing the default clock step size for the simulation. This will have an effect on the precision of the numerical integration calculations but for values near the default will still produce similar accuracy results. More information on the default clock can be found in the Brian 2 documentation: https://brian2.readthedocs.io/en/stable/user/running.html
The original normalize_weights() function can produce a division by zero error if this code is used to run other network experiments.
The simulation code may take many hours to run. Consider running for a smaller value of num_examples first to verify that it is working for you.
The neuron reset equation that updates the s_max and s_min variables throws a cython division by zero error at the beginning of the simulation if cython is set as the preferred codegen target. As a temporary workaround, the L_0 variable may be first incremented so that it is always non-zero or a different codegen target used.