Usage
Running on the Simulator
On your local machine you can run networks using the Python based simulator of the CRI hardware. Please refer to the Video Tutorial for a detailed walkthrough of how to interface with the hs_api
.
Defining a Network
Users are expected to provide three data structures in order to define a network
Defining the Configuration Dictionary
The configuration dictionary specifies a few properties that are shared by every neuron in the network
- neuron_type specifies the type of neuron model used to calculate membrane potentials
- global_neuron_params is a sub-dictionary of the configuration dictionary
- v_thr is an entry in the global_neuron_params dictionary, it sets the membrane potential threshold for all neurons in the network
= {}
configuration 'neuron_type'] = I&F
configuration['global_neuron_params'] = {}
configuration['global_neuron_params']['v_thr'] = 4 configuration[
Defining the Axons Dictionary
The axons dictionary configures inputs to the network. Axons are synapses connected to neurons in the network that the user can manually send spikes over at a given timestep. Each key in the dictionary is the name of an axon. Each value is a list of two element tuples. Each tuple defines an in-going synapse to a neuron. The first element is the name of a neuron in the network and the second element is the weight of the synaptic connection. Synapse weights must be integers, but they may be positive or negative.
= {'alpha': [('a', 3)], 'beta': [('d', 3)]} axons
Defining the Connections Dictionary:
The connections dictionary defines the neurons in the network and the connections between them. Each key in the dictionary is the name of a neuron. Of note the names of neurons in the connections dictionary and the names of axons in the axons dictionary must be mutually exclusive. Each value is a list of two element tuples. Each tuple defines a synapse between neurons in the network. The first element is the name of the postsynaptic neuron and the the second element is the weight of the synapse. Synapse weights must be integers but they may be positive or negative. If a neuron has no outgoing synapses it’s synapse list may be left empty.
= {'a': [('b', 1)], 'b': [], 'c': [], 'd': [('c', 1)]} connections
Defining the Outputs List:
The outputs list defines the neurons in the network the user wishes to receive spikes from. Each element in the list is the key of a neuron in the connections dictionary.
= ['a', 'b'] outputs
Defining Stochastic Behavior
HiAER-Spike supports randomly perturbing the membrane potential of neurons at each timestep of execution. To enable this perturbation the perturbMag (default = None
) variable needs to be set to some value other than None
and be < 17. Random noise is generated at each timestep for each neuron to be added to the neurons membrane potential. This noise in generated as a 17 bit signed integer. When perturbMag is specified the noise is either right or left shifted inorder to match the number of bits specified by perturbMag
= 2 perturbMag
Defining Leakage
Our systems supports Leaky Integrate and Fire (LIF) neurons. Users must set the leakage time constant. At any step for on-fired neurons, the membrane potential will be calculated using the following equation:
\[ V = V - \frac{V}{2^{leakage}} \]
where V is the membrane potential and leakage is the leakage time constant. Leakage must be an integer \(\leq 2^6\).
Initializing a network
Once we’ve defined the above dictionaries and list we must pass them to the CRI_network constructor to create a CRI_network object.
= CRI_network(
network =axons,
axons=connections,
connections=config,
config=outputs,
outputs=perturb,
perturb=perturbMag
perturbMag )
Running a Timestep
Once we’ve constructed an CRI_network object we can run a timestep. We do so by calling the step() method of CRI_network. This method expects a single input called inputs. Inputs defines the inputs to the network at the current timestep, in particular it is a list of names of axons that you wish to carry spikes into the network at the current timestep. Normally network.step() returns a list of the keys that correspond to neurons that spiked during the given timestep, however the membranePotential parameter can be set to True to additionally output the membranePotentials for all neurons in the network.
= ['alpha','beta']
inputs = network.step(inputs)
spikes
#Alternative
= network.step(inputs, membranePotential=True) potentials, spikes
This method will return a list of membrane potentials for all neurons in the network after the current timestep has elapsed.
Updating Synapse Weights
Once the CRI_network class the topology of the network is fixed, that is what axon and neurons are in the network and how they are connected via synapses may not be changed. However it is possible to update the weight of preexisting synapses in the network. This can be done by calling the write_synapse() method of CRI_network. write_synapse() takes three arguments, the presynaptic neuron name, the postsynaptic neuron name, and the new synapse weight.
'a', 'b', 2) network.write_synapse(
Updating Perturbation Magnitude
The perturbMag variable can also be updated after network creation. The new value is simply passed to a function call.
3) network.set_perturbMag(