Custom STDP rule

Hi,
I am trying to implement the following STDP learning rule in brian2 between 2 groups of LIF neurons (784x400):

I have completed the implementation of the STDP part that updates w as follows:

from brian2 import *

defaultclock.dt = 0.001*us

tau1 = 10*us
tau2 = 20*us
mu = 1.7
gamma1 = 9.0
gamma2 = 15.0
wmax = 900.0

stdp='''
    w : 1
    '''     
on_pre='''
        lastspike_pre = t
        delta_t = (lastspike_pre - lastspike_post)
        w -= gamma2*((w/wmax)**mu)*exp(-delta_t/tau2)
        '''
on_post='''
        lastspike_post = t
        delta_t = (lastspike_post - lastspike_pre)
        w += gamma1*((1-w/wmax)**mu)*exp(-delta_t/tau1)
        '''

G = NeuronGroup(101, '''
spike_when : second (constant)
lastspike : second  # remove when model uses refractory
''',
threshold='timestep(t, dt) == timestep(spike_when, dt)') # spike at pre-defined time
G.lastspike = -1e9*second
G.spike_when[0] = 60*us
G.spike_when[1:] = np.linspace(10, 110, 100)*us

S = Synapses(G, G, stdp, on_pre= on_pre, on_post=on_post)


S.connect(i=0, j=np.arange(1, 101))  # Connect first neuron to all other neurons
S.w = 0

run(120*us)

plt.title('Potentiation curve at w = 0 (minimum)')
#plt.ylim(880, 900)
plt.plot((G.spike_when[1:] - G.spike_when[0])/us, S.w[:], color='r')
plt.axhline(linestyle=':', color='k')
plt.axvline(linestyle=':', color='k')
plt.show()

And I get the desired STDP behavior as per the paper.

But, I am still not sure about how equation (3) will be implemented. I thought of adding the line

I_post += I0*w*(exp(-(t-lastspike_pre)/tau_m) - exp(-(t-lastspike_post)/tau_s))

to both on_pre and on_post, but I am not sure if this is correct.

Thanks

Hi @mallard1707 . Indeed, your implementation of the STDP rule looks correct to me, and your approach to verifying it looks good as well :wink:

This will not quite work like this : the on_pre/on_post statements would set the post-synaptic current at a single time point, but the equation is meant to describe the current over time.

Since the shape of the synaptic current is the same for all synapses (only the height changes with w_{i,j}), you can include the synaptic current in the post-synaptic cell. The shape is a bi-exponential function of time, which you’d implement with two exponential functions as explained here: Converting from integrated form to ODEs — Brian 2 2.5.4 documentation In the documentation, this is a model of a bi-exponential postsynaptic potential, but in your case it would be a current, so the neuron equations would have something like:

''''
...
dI/dt = ((tau_S / tau_M) ** (tau_M / (tau_S - tau_M))*x-V)/tau_1 : amp
dx/dt = -x/tau_S                                                 : amp
'''

and the synapse would have on_pre = 'x_post += I0*w'. The somewhat complicated tau_S/tau_M stuff in the equation is only there as a normalization factor – it might be that this is not necessary in your equations.

Hi @mstimberg ,

Thank you for the detailed response. I had a question regarding the conversion of the biexponential synapse to ODE form:
I am trying to derive the expression mentioned in the wiki before proceeding to my own case. After differentiating the example, I get:
image
Now, the example has taken x to be:
image
Why haven’t they taken x to be a simpler term that is just the exponential? I didn’t quite understand what you meant by the normalization term.

Thank you Marcel, I was able to get the STDP and synaptic current to work properly.

1 Like