Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add symmetric stdp synapse to NEST #218

Merged
merged 29 commits into from
Jul 5, 2016

Conversation

sanjayankur31
Copy link
Contributor

Reference:
Vogels et al. (2011) Inhibitory Plasticity Balances Excitation and
Inhibition in Sensory Pathways and Memory Networks. Science Vol. 334,
Issue 6062, pp. 1569-1573 DOI: 10.1126/science.1211095

http://www.sciencemag.org/content/334/6062/1569.abstract
Also adds a python test file to the manualtests folders.

@sanjayankur31
Copy link
Contributor Author

The test python file in manualtests generates this graph:
https://github.com/sanjayankur31/nest-symmetric-stdp-test/blob/master/results/gnuplot.png

Things I'm not sure about:

  • I'm not so sure of the case where spikes are co-incident. Even when I didn't have the conditional, I didn't get any facilitation. I'm wondering if this has something with the way nest does things?
  • Do I need to implement the hpc variant too? And a hom variant?

@@ -0,0 +1,300 @@
/*
* stdp_connection.h
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the copyright notice, the correct file name should be stated: stdp_symmetric_connection.h. This is why regressiontests/ticket-659-copyright.py fails.

@tammoippen
Copy link
Contributor

Also the formatting of some of the file seems to be off, e.g. see TravisCI output. Please make sure, that you use clang-format version 3.6 for the formatting.

Reference:
Vogels et al. (2011) Inhibitory Plasticity Balances Excitation and
Inhibition in Sensory Pathways and Memory Networks.  Science Vol. 334,
Issue 6062, pp. 1569-1573 DOI: 10.1126/science.1211095

http://www.sciencemag.org/content/334/6062/1569.abstract

Also adds a python test file to the manualtests folders.
The version in Fedora is 3.7.x which was causing the tests to fail.
@sanjayankur31
Copy link
Contributor Author

@tammoippen - Thank you for notes on the test failures. The new set of commits seem to be OK.

@jakobj
Copy link
Contributor

jakobj commented Feb 15, 2016

@flinz @suku248 would be good second reviewers. @sanjayankur31 : a non-manual test would be a great addition.

@sanjayankur31
Copy link
Contributor Author

Thanks @jakobj - I'll look into writing a non-manual test.

facilitate_( double_t w, double_t kplus )
{
double_t norm_w = ( w / Wmax_ ) + ( lambda_ * eta_ * kplus );
return norm_w < 1.0 ? norm_w * Wmax_ : Wmax_;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe there is a small error, caused by the weight maximization. Let me demonstrate here, but the same holds for depression.

For given values of w and kplus, you are assigning the new w to be (assuming you don't hit the norm_w < 1.0):

w_returned 
= [( w_old / Wmax_ ) + ( lambda_ * eta_ * kplus )] * Wmax_ 
= w_old + lambda_ * eta_ * kplus * Wmax

This makes the weight updates scale additionally with Wmax, which I believe should not be the case. For facilitation this should rather be:

w_returned 
= w_old + lambda_ * eta_ * kplus 

You can change the lines to something akin to this implementation.

Just as a remark: Looking at the corresponding line in stdp_connection for the additive case (mu_plus=0) I think we get the same scaling with Wmax. @abigailm @mhelias am I getting something wrong or is this an intended behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure about this either, but decided to go with the way stdp_connection is implemented (as you observe above).

@seeholza
Copy link
Contributor

Hey @sanjayankur31, I had a quick look at your code and the paper.

Before you go on diggin into the details below, here is a general point to consider: The Vogels learning rule is indeed not implementable by the current stdp_connection (there is a constant depression term, independent of k_minus), so this class of learning rules is a sensible addition. However, for the sake of keeping NEST more general, and this class more reusable, it could be beneficial to instead make this a STDP connection (using both tau_plus and tau_minus) with optional constant terms for both depression and facilitation (alpha_fac and alpha_dep). For tau_plus=tau_minus and alpha_fac=0 the current model would be contained as a special case.
@heplesser @jougs what's your opinion on this?

Besides, here are comments on the current class:

  1. Naming: I think the class should be named stdp_connection_symmetric in accordance with, e.g. stdp_connection_hom. One could think about naming this stdp_connection_vogels, since it is a little more specialized than being simply symmetric: it has a constant depression term (see also the general remark above).
  2. Redundancy of lambda: I think the parameter lambda might be redundant. You already introduce the parameter eta (the learning rate, as in the paper) and both only occur as lambda * eta. In this case, to adhere to paper notation, remove lambda from the implementation.
  3. Update description: You should mention in the model description that the essential difference to stdp_connection is the constant depression of synapses, independent of the actual spike times. I think this could be helpful for people browsing models, that are not familiar with the Vogels model.
  4. Expose alpha instead of rho_0: The following might be a matter of discussion, since its rather a question of how general we want NEST models to be implemented.
    The analysis in the paper and identification of rho_0 (named kappa in your implementation) with a target firing rate relies on the feedforward setup of inhibition (Fig. S1).
    I would personally prefer to use for the model implementation only the more general parameter alpha (Eq. 4 in the supplement) and then mention that for alpha = 2 * tau * rho_0 one would recover the exact implementation of Vogels' feedforward scenario.
    This has the advantage that the inhibitory offset alphais directly exposed and controllable, since it does not change with both tau and kappa.
  5. Testing: As you already mentioned above, you should include a proper automated test for the synapse. You can simply adapt for example this test for the triplet rule to check for correct weight changes against the actual equations of Vogels Eqs. S4 & S5.

@sanjayankur31
Copy link
Contributor Author

Hi @flinz - thank you very much for your comments. I'm travelling over the next week or so and will address them as soon as get back.

@sanjayankur31
Copy link
Contributor Author

One question before I make any more changes - is the suggested practice in nest to simply add more commits on top of the current ones - thus maintaining the complete review and code history, or should I squash commits up to make it all tidy (and then maybe force push)?

@jougs
Copy link
Contributor

jougs commented Feb 15, 2016

@sanjayankur31: we think it's nicer to just add commits to your branch in order to have a nice and transparent history of code review process.

@flinz: many thanks for your nice and solid review and the quick reaction.

@heplesser: could you make sure the copyright transfer is handled properly? Thanks!

@sanjayankur31
Copy link
Contributor Author

I've fixed some of the minor issues and pushed commits. I'll fix the major issues as soon as I can.


# set up the synapse
syn_spec_synapse = {'weight': weight_pre, 'Wmax': 100.,
'kappa': 0.1, 'eta': 0.001,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I run this test, I get Unused dictionary items: kappa.
Looking into the default parameter reveals that kappa is indeed not a parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kappa was replaced by alpha after the review. The manual test file hasn't been updated since it'll be replaced by an automated test (I'm working on the latter)

@sanjayankur31
Copy link
Contributor Author

TODO - add source files to models/CMakeLists.txt

@heplesser
Copy link
Contributor

@sanjayankur31 Would you pull the newest changes from master so that Travis can check this PR properly now that #391 is merged?

@sanjayankur31
Copy link
Contributor Author

Hiya, I've updated the source to use an implementation similar to the triplet synapse in #284. So this is finally ready for a complete review and merge :)

@@ -112,6 +112,7 @@
#include "stdp_triplet_connection.h"
#include "stdp_dopa_connection.h"
#include "stdp_pl_connection_hom.h"
#include "vogels_sprekeler_connection.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you put this in alphabetical order?

@heplesser
Copy link
Contributor

@sanjayankur31 The code looks clean except for two little details, see inline comments.

@flinz @suku248 Would you have a final look before we merge?

@heplesser heplesser added the T: Enhancement New functionality, model or documentation label Jun 20, 2016
@suku248
Copy link
Contributor

suku248 commented Jul 5, 2016

Seems fine to me 👍

@heplesser
Copy link
Contributor

@sanjayankur31 And merging :).

@heplesser heplesser merged commit 62c019b into nest:master Jul 5, 2016
@sanjayankur31 sanjayankur31 deleted the symmetric_stdp_synapse branch July 5, 2016 15:30
@seeholza
Copy link
Contributor

seeholza commented Aug 9, 2016

@heplesser sorry I was on holidays. Too late for the party 👍

aserenko added a commit to aserenko/nest-simulator that referenced this pull request Dec 6, 2017
Add three types of nearest-neighbour STDP: symmetric (but not to be
confused with PR nest#218), presynaptic-centered, and restricted
symmetric. These are worth implementing because described in a highly-
cited review [Morrison A., Diesmann M., and Gerstner W. (2008)
Phenomenological models of synaptic plasticity based on spike timing,
Biol. Cybern. 98, 459--478].

In these models a spike is taken into account in the weight change
rule not with all preceding spikes, but only with some of the
nearest, see the three pairing schemes in Fig. 7 in [Morrison et
al., 2008].

The implementation relies on two additional variables - presynaptic
and postsynaptic traces, like in stdp_synapse. However, their update
rules differ from those of the latter. That's why the archiving_node
was modified to add one more state variable, nearest_neighbor_Kminus.
It is not stored in the node, just computed on the fly when
requested. To return nearest_neighbor_Kminus I changed the
archiving_node.get_K_values() function signature, because, as fas as
I can see, this function is not currently used anywhere.

The tests for all three models reside in a single file (but as three
separate tests), and are the following: generate two Poisson spike
sequences as presynaptic and postsynaptic, feed them to NEST to get
the synaptic weight change, then reproduce the weight change
independently outside of NEST and check whether the expected weight
equals the obtained one.
aserenko added a commit to aserenko/nest-simulator that referenced this pull request Dec 6, 2017
Add three types of nearest-neighbour STDP: symmetric (but not to be
confused with PR nest#218), presynaptic-centered, and restricted
symmetric. These are worth implementing because described in a highly-
cited review [Morrison A., Diesmann M., and Gerstner W. (2008)
Phenomenological models of synaptic plasticity based on spike timing,
Biol. Cybern. 98, 459--478].

In these models a spike is taken into account in the weight change
rule not with all preceding spikes, but only with some of the
nearest, see the three pairing schemes in Fig. 7 in [Morrison et
al., 2008].

The implementation relies on two additional variables - presynaptic
and postsynaptic traces, like in stdp_synapse. However, their update
rules differ from those of the latter. That's why the archiving_node
was modified to add one more state variable, nearest_neighbor_Kminus.
It is not stored in the node, just computed on the fly when
requested. To return nearest_neighbor_Kminus I changed the
archiving_node.get_K_values() function signature, because, as fas as
I can see, this function is not currently used anywhere.

The tests for all three models reside in a single file (but as three
separate tests), and are the following: generate two Poisson spike
sequences as presynaptic and postsynaptic, feed them to NEST to get
the synaptic weight change, then reproduce the weight change
independently outside of NEST and check whether the expected weight
equals the obtained one.
aserenko added a commit to aserenko/nest-simulator that referenced this pull request Dec 6, 2017
Add three types of nearest-neighbour STDP: symmetric (but not to be
confused with PR nest#218), presynaptic-centered, and restricted
symmetric. These are worth implementing because described in a highly-
cited review [Morrison A., Diesmann M., and Gerstner W. (2008)
Phenomenological models of synaptic plasticity based on spike timing,
Biol. Cybern. 98, 459--478].

In these models a spike is taken into account in the weight change
rule not with all preceding spikes, but only with some of the
nearest, see the three pairing schemes in Fig. 7 in [Morrison et
al., 2008].

The implementation relies on two additional variables - presynaptic
and postsynaptic traces, like in stdp_synapse. However, their update
rules differ from those of the latter. That's why the archiving_node
was modified to add one more state variable, nearest_neighbor_Kminus.
It is not stored in the node, just computed on the fly when
requested. To return nearest_neighbor_Kminus I changed the
archiving_node.get_K_values() function signature, because, as fas as
I can see, this function is not currently used anywhere.

The tests for all three models reside in a single file (but as three
separate tests), and are the following: generate two Poisson spike
sequences as presynaptic and postsynaptic, feed them to NEST to get
the synaptic weight change, then reproduce the weight change
independently outside of NEST and check whether the expected weight
equals the obtained one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T: Enhancement New functionality, model or documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants