Synaptic plasticityΒΆ
The default type of synaptic connection in PyNN is static, with fixed synaptic weights. To model dynamic synapses, for which the synaptic weight (and possibly other properties, such as rise-time) varies depending on the recent history of post- and/or pre-synaptic activity, we use the same idea as for neurons, of standardized, named models that have the same interface and behaviour across simulators, even if the underlying implementation may be very different.
Where the approach for dynamic synapses differs from that for neurons is that we attempt a greater degree of compositionality, i.e. we decompose models into a number of components, for example for short-term and long-term dynamics, or for the timing-dependence and the weight-dependence of STDP rules, that can then be composed in different ways.
The advantage of this is that if we have n
differerent models for component
‘’A’’ and m
models for component ‘’B’‘, then we require only n + m
models
rather than n x m
, which had advantages in terms of code-simplicity and in
shorter model names. The disadvantage is that not all combinations may exist, if
the underlying simulator implements composite models rather than using
components itself: in this situation, PyNN checks whether a given composite model
AB
exists for a given simulator and raises an Exception if it does not.
The composite approach may be extended to neuron models in future versions of the PyNN interface depending on the experience with composite synapse models.
To set the model of synapse dynamics to use for the connections of a given
Projection
, we pass a SynapseDynamics
object as the synapse_dynamics
keyword argument to the Projection
constructor.
The SynapseDynamics
object is simply a container that has attributes fast
,
which, if set, is an instance of a subclass of the abstract class
ShortTermPlasticityMechanism
, and slow
, which is an instance of a
subclass of the abstract class STDPMechanism
.
Only a single subclass of ShortTermPlasticityMechanism
is currently available in
PyNN: TsodkysMarkramMechanism
.
STDPMechanism
objects are further decomposed into components for the
timing-dependence, weight-dependence and post-synaptic voltage-dependence of
the mechanism.
An example of defining a Projection
with depressing synapses,
but no long-term plasticity:
>>> pre = post = Population(50, IF_cond_exp)
>>> params = {'U': 0.5, 'tau_rec': 100.0, 'tau_facil': 0.0}
>>> depressing_syn = SynapseDynamics(fast=TsodyksMarkramMechanism(**params))
>>> prj = Projection(pre, post, AllToAllConnector(),
... synapse_dynamics = depressing_syn)
and one with long-term plasticity, using a spike-pair rule and with additive weight updates (i.e. the weight change is independent of the current weight value):
>>> stdp_model = STDPMechanism(
... timing_dependence=SpikePairRule(tau_plus=20.0, tau_minus=20.0),
... weight_dependence=AdditiveWeightDependence(w_min=0, w_max=0.02,
... A_plus=0.01, A_minus=0.012)
... )
>>> prj2 = Projection(pre, post, FixedProbabilityConnector(p_connect=0.1),
... synapse_dynamics=SynapseDynamics(slow=stdp_model))
Just as with synaptic weights and delays for static synapses, the parameters of
dynamic synapses can be obtained and set with the getSynapseDynamics()
,
setSynapseDynamics()
and randomizeSynapseDynamics()
methods of the
Projection
class:
>>> prj.setSynapseDynamics('tau_rec', 50.0)
>>> prj.getSynapseDynamics('tau_rec')[:5]
[50.0, 50.0, 50.0, 50.0, 50.0]
>>> from pyNN.random import RandomDistribution
>>> distr = RandomDistribution('normal', [0.02, 0.05])
>>> prj2.randomizeSynapseDynamics('w_max', distr)
>>> prj2.getSynapseDynamics('w_max')[:5]
[-0.056605932509016577, 0.063197908706714212, 0.034940801886916589, 0.010755581262934901, 0.011700727992415299]
There are a number of examples of networks using synaptic plasticity in the examples
directory of the source distribution.