#!pip install ANNarchy
Homeostatic STDP: SORF model
Reimplementation of the SORF model published in:
Carlson, K.D.; Richert, M.; Dutt, N.; Krichmar, J.L., “Biologically plausible models of homeostasis and STDP: Stability and learning in spiking neural networks,” in Neural Networks (IJCNN), The 2013 International Joint Conference on , vol., no., pp.1-8, 4-9 Aug. 2013. doi: 10.1109/IJCNN.2013.6706961
import numpy as np
import ANNarchy as ann
= 4 # Number of exc and inh neurons
nb_neuron = (32, 32) # input size
size = 1.2 # nb_cycles/half-image
freq = 40 # Number of grating per epoch
nb_stim = 20 # Number of epochs
nb_epochs = 28. # Max frequency of the poisson neurons
max_freq = 10000. # Period for averaging the firing rate T
# Izhikevich Coba neuron with AMPA, NMDA and GABA receptors
= ann.Neuron(
RSNeuron = """
parameters a = 0.02 : population
b = 0.2 : population
c = -65. : population
d = 8. : population
tau_ampa = 5. : population
tau_nmda = 150. : population
tau_gabaa = 6. : population
tau_gabab = 150. : population
vrev_ampa = 0.0 : population
vrev_nmda = 0.0 : population
vrev_gabaa = -70.0 : population
vrev_gabab = -90.0 : population
""" ,
="""
equations # Inputs
I = g_ampa * (vrev_ampa - v) + g_nmda * nmda(v, -80.0, 60.0) * (vrev_nmda -v) + g_gabaa * (vrev_gabaa - v) + g_gabab * (vrev_gabab -v)
# Midpoint scheme
dv/dt = (0.04 * v + 5.0) * v + 140.0 - u + I : init=-65., min=-90., midpoint
du/dt = a * (b*v - u) : init=-13., midpoint
# Conductances
tau_ampa * dg_ampa/dt = -g_ampa : exponential
tau_nmda * dg_nmda/dt = -g_nmda : exponential
tau_gabaa * dg_gabaa/dt = -g_gabaa : exponential
tau_gabab * dg_gabab/dt = -g_gabab : exponential
""" ,
= """
spike v >= 30.
""",
= """
reset v = c
u += d
g_ampa = 0.0
g_nmda = 0.0
g_gabaa = 0.0
g_gabab = 0.0
""",
= """
functions nmda(v, t, s) = ((v-t)/(s))^2 / (1.0 + ((v-t)/(s))^2)
""",
=1.0
refractory )
# STDP with homeostatic regulation
= ann.Synapse(
homeo_stdp ="""
parameters # STDP
tau_plus = 60. : projection
tau_minus = 90. : projection
A_plus = 0.000045 : projection
A_minus = 0.00003 : projection
# Homeostatic regulation
alpha = 0.1 : projection
beta = 50.0 : projection # <- Difference with the original implementation
gamma = 50.0 : projection
Rtarget = 10. : projection
T = 10000. : projection
""",
= """
equations # Homeostatic values
R = post.r : postsynaptic
K = R/(T*(1.+fabs(1. - R/Rtarget) * gamma)) : postsynaptic
# Nearest-neighbour
stdp = if t_post >= t_pre: ltp else: - ltd
w += (alpha * w * (1- R/Rtarget) + beta * stdp ) * K : min=0.0, max=10.0
# Traces
tau_plus * dltp/dt = -ltp : exponential
tau_minus * dltd/dt = -ltd : exponential
""",
="""
pre_spike g_target += w
ltp = A_plus
""",
="""
post_spike ltd = A_minus
"""
)
# Input population
= ann.PoissonPopulation(size, rates=1.0)
OnPoiss = ann.PoissonPopulation(size, rates=1.0)
OffPoiss
# RS neuron for the input buffers
= ann.Population(size, RSNeuron)
OnBuffer = ann.Population(size, RSNeuron)
OffBuffer
# Connect the buffers
= ann.Projection(OnPoiss, OnBuffer, ['ampa', 'nmda'])
OnPoissBuffer 0.2, 0.6))
OnPoissBuffer.connect_one_to_one(ann.Uniform(= ann.Projection(OffPoiss, OffBuffer, ['ampa', 'nmda'])
OffPoissBuffer 0.2, 0.6))
OffPoissBuffer.connect_one_to_one(ann.Uniform(
# Excitatory and inhibitory neurons
= ann.Population(nb_neuron, RSNeuron)
Exc = ann.Population(nb_neuron, RSNeuron)
Inh
Exc.compute_firing_rate(T)
Inh.compute_firing_rate(T)
# Input connections
= ann.Projection(OnBuffer, Exc, ['ampa', 'nmda'], homeo_stdp)
OnBufferExc 0.004, 0.015))
OnBufferExc.connect_all_to_all(ann.Uniform(= ann.Projection(OffBuffer, Exc, ['ampa', 'nmda'], homeo_stdp)
OffBufferExc 0.004, 0.015))
OffBufferExc.connect_all_to_all(ann.Uniform(
# Competition
= ann.Projection(Exc, Inh, ['ampa', 'nmda'], homeo_stdp)
ExcInh 0.116, 0.403))
ExcInh.connect_all_to_all(ann.Uniform(
= 75.
ExcInh.Rtarget = 51.
ExcInh.tau_plus = 78.
ExcInh.tau_minus = -0.000041
ExcInh.A_plus = -0.000015
ExcInh.A_minus
= ann.Projection(Inh, Exc, ['gabaa', 'gabab'])
InhExc 0.065, 0.259))
InhExc.connect_all_to_all(ann.Uniform(
compile() ann.
Compiling ... OK
# Inputs
def get_grating(theta):
= np.linspace(-1., 1., size[0])
x = np.linspace(-1., 1., size[1])
y = np.meshgrid(x, y)
xx, yy = np.sin(2.*np.pi*(np.cos(theta)*xx + np.sin(theta)*yy)*freq)
z return np.maximum(z, 0.), -np.minimum(z, 0.0)
# Initial weights
= OnBufferExc.w
w_on_start = OffBufferExc.w
w_off_start
# Monitors
= ann.Monitor(Exc, 'r')
m = ann.Monitor(Inh, 'r')
n = ann.Monitor(OnBufferExc[0], 'w', period=1000.)
o = ann.Monitor(ExcInh[0], 'w', period=1000.)
p
# Learning procedure
from time import time
import random
= time()
tstart = list(range(nb_stim))
stim_order try:
for epoch in range(nb_epochs):
random.shuffle(stim_order)for stim in stim_order:
# Generate a grating randomly
= get_grating(np.pi*stim/float(nb_stim))
rates_on, rates_off # Set it as input to the poisson neurons
= max_freq * rates_on
OnPoiss.rates = max_freq * rates_off
OffPoiss.rates # Simulate for 2s
2000.)
ann.simulate(# Relax the Poisson inputs
= 1.
OnPoiss.rates = 1.
OffPoiss.rates # Simulate for 500ms
500.)
ann.simulate(print('Epoch', epoch+1, 'done.')
except KeyboardInterrupt:
print('Simulation stopped')
print('Done in ', time()-tstart)
# Recordings
= m.get('r')
datae = n.get('r')
datai = o.get('w')
dataw = p.get('w') datal
Epoch 1 done.
Epoch 2 done.
Epoch 3 done.
Epoch 4 done.
Epoch 5 done.
Epoch 6 done.
Epoch 7 done.
Epoch 8 done.
Epoch 9 done.
Epoch 10 done.
Epoch 11 done.
Epoch 12 done.
Epoch 13 done.
Epoch 14 done.
Epoch 15 done.
Epoch 16 done.
Epoch 17 done.
Epoch 18 done.
Epoch 19 done.
Epoch 20 done.
Done in 122.07915997505188
# Final weights
= OnBufferExc.w
w_on_end = OffBufferExc.w
w_off_end
# Plot
import matplotlib.pyplot as plt
=(12, 12))
plt.figure(figsize'Feedforward weights before and after learning')
plt.title(for i in range(nb_neuron):
3, nb_neuron, i+1)
plt.subplot(32,32)), aspect='auto', cmap='hot')
plt.imshow((np.array(w_on_start[i])).reshape((3, nb_neuron, nb_neuron + i +1)
plt.subplot(32,32)), aspect='auto', cmap='hot')
plt.imshow((np.array(w_on_end[i])).reshape((3, nb_neuron, 2*nb_neuron + i +1)
plt.subplot(32,32)), aspect='auto', cmap='hot')
plt.imshow((np.array(w_off_end[i])).reshape((
=(12, 8))
plt.figure(figsize0], label='Exc')
plt.plot(datae[:, 0], label='Inh')
plt.plot(datai[:, 'Mean FR of the Exc and Inh neurons')
plt.title(
plt.legend()
=(12, 8))
plt.figure(figsize121)
plt.subplot(='float').T, aspect='auto', cmap='hot')
plt.imshow(np.array(dataw, dtype'Timecourse of feedforward weights')
plt.title(
plt.colorbar()122)
plt.subplot(='float').T, aspect='auto', cmap='hot')
plt.imshow(np.array(datal, dtype'Timecourse of inhibitory weights')
plt.title(
plt.colorbar() plt.show()
/var/folders/6w/6msx49ws7k13cc0bbys0tt4m0000gn/T/ipykernel_8956/2229657718.py:11: MatplotlibDeprecationWarning: Auto-removal of overlapping axes is deprecated since 3.6 and will be removed two minor releases later; explicitly call ax.remove() as needed.
plt.subplot(3, nb_neuron, i+1)