Sustained Activity from online tutorial

Description of problem

I’ve been probing online tutorial from 2020 youtube footage. I am aware of the github solution. But I want to execute it step by step as explained in the slide to learn more precisely. So there are some steps I achieved, for the fourth step I defined inh population to the network. Based on the slide I am not sure that I should have sustained activity. What are your thoughts? Thanks.

Minimal code to reproduce problem

tau = 10*ms
# Noise strength
sigma_noise = 0.5
# stimulus parameters
theta_stim = 0.
# stimulus sensitivity
sigma_theta = pi/8
# Number of neurons
N_E = 400
N_I = 100

# Define the time-varying amp_stim values
amp_stim = TimedArray([1., 0.], dt=1000*ms)

# excitatory neurons
exc_neurons = NeuronGroup(N_E, '''dv/dt = (-v + I_stim)/tau + sigma_noise*xi*tau**-0.5: 1
                                  theta : 1 (constant)
                                  stimulus_diff = (theta - theta_stim + pi)%(2*pi) - pi : radian
                                  I_stim = amp_stim(t) * exp(-stimulus_diff**2 / (2*sigma_theta)**2) : 1
                                  ''', threshold='v>1', reset='v=0', method='euler')
# inhibitory neurons
inh_neurons = NeuronGroup(N_I, '''dv/dt = (-v + I_syn)/tau + sigma_noise*xi*tau**-0.5: 1
                                  I_syn: 1
                                  ''', threshold='v>1', reset='v=0', method='euler')

# Initialize the membrane potential randomly
exc_neurons.v = 'rand()*0.5'
inh_neurons.v = 'rand()*0.5'
# Uniformly distribute preferred stimuli between -pi and pi
exc_neurons.theta = '-pi + 2*pi*i/N_E'

# Creating synaptic connections
# Ext to Ext connections
E_to_E = Synapses(exc_neurons, exc_neurons, 'w : 1', on_pre='v += w')
E_to_E.connect(condition='i!=j', p='exp(-(i-j)**2/15.0**2)')
E_to_E.w = 0.04

# Ext to Inh connections
E_to_I = Synapses(exc_neurons, inh_neurons, 'w : 1', on_pre='v += w')
E_to_I.connect(p=0.5)
E_to_I.w = 1

# Inh to Inh connections
I_to_I = Synapses(inh_neurons, inh_neurons, 'w : 1', on_pre='v -= w')
I_to_I.connect(condition='i!=j')
I_to_I.w = 2

# Inh to Ext connections
I_to_E = Synapses(inh_neurons, exc_neurons, 'w : 1', on_pre='v -= w')
I_to_E.connect(condition='i!=j', p='exp(-(i-j)**2/15.0**2)')
I_to_E.w = 1

# Monitor neurons
exc_mon = SpikeMonitor(exc_neurons)

# run simulation
run(2000*ms, report='text')
![Ekran Alıntısı|690x496](upload://mrebTz3q4LunWzzlasvrYbwMOo4.jpeg)

# Plot results
fig, ax = plt.subplots()
ax.plot(exc_mon.t/ms, exc_neurons.theta[exc_mon.i], '|')
ax.set(ylabel='preferred stim', xlabel='time (ms)')

What you have aready tried

I’ve tried to adjust weights, some parameters and number of neurons.

Expected output (if relevant)

Not sure having a sustained activity.

Actual output (if relevant)

Slides
● Switch off the stimulus after the end of the simulation and continue the simulation (Done)
● Connect the neurons among each other with synapses. Can you get sustained activity after the stimulus switches off? (Done)
● Instead of connecting all neurons to all other neurons, connect them preferrably (or with stronger weights) to neurons with similar stimulus preference. (Done)
● Introduce an inhibitory population and connect it to the excitatory population (Failed)
● Add a second stimulus or change the stimulus over time (Not tried)

Full traceback of error (if relevant)

Hey,

From my understanding, you connect EE with a high probability when they have a similar orientation (based on their index). You also did it for the I-to-E connection. But why? Inhibitory neurons do not have a preferred orientation, so it might be better to just connect them with a fixed probability, like p=0.5.

The other thing that I could not get is this:condition='i!=j', p='exp(-(i-j)**2/15.0**2)'
Could you please explain why you exclude the connectivity of the neuron to itself, and why you have 15.0**2 in your exponential?

Hi,

1- Not exactly the same case but I adopted it from Brunel&Wang paper below.

# E to E
C_E_E = Synapses(P_E, P_E, model=eqs_glut, on_pre=eqs_pre_glut, method='euler')
C_E_E.connect('i != j')
C_E_E.w[:] = 1

for pi in range(N_non, N_non + p * N_sub, N_sub):

    # internal other subpopulation to current nonselective
    C_E_E.w[C_E_E.indices[:, pi:pi + N_sub]] = w_minus

    # internal current subpopulation to current subpopulation
    C_E_E.w[C_E_E.indices[pi:pi + N_sub, pi:pi + N_sub]] = w_plus

# E to I
C_E_I = Synapses(P_E, P_I, model=eqs_glut, on_pre=eqs_pre_glut, method='euler')
C_E_I.connect()
C_E_I.w[:] = 1

# I to I
C_I_I = Synapses(P_I, P_I, on_pre=eqs_pre_gaba, method='euler')
C_I_I.connect('i != j')

# I to E
C_I_E = Synapses(P_I, P_E, on_pre=eqs_pre_gaba, method='euler')
C_I_E.connect()

2- You mentioned about the I-to-E connection probability, I couldn’t notice it to be related with the orientation of inh neurons. It is actually a Gaussian probability function which determines the connectivity in terms of the distance between neurons. If neurons are close to each other then they will have more likely synaptic connections. So based on your recommendation I changed it to fixed probability, unfurtunately it didn’t work.
3- Excluding the connectivity of the neuron to itself: This is also adopted from Brunel&Wang paper. Because in the Brian reproduced version they used it like:

# E to E
C_E_E = Synapses(P_E, P_E, model=eqs_glut, on_pre=eqs_pre_glut, method='euler')
C_E_E.connect('i != j')
C_E_E.w[:] = 1

So in the project ask to to assign a preferred orientation to each neuron you did it by this:
exc_neurons.theta = '-pi + 2*pi*i/N_E
which means that each excitatory neuron from index 0 to N_E-1 has a unique orientation from 0 to pi.
So, in the project task, "Instead of connecting all neurons to all other neurons, connect them preferrably (or with stronger weights) to neurons with similar stimulus preference."You can either define the mean of Gaussian probability using each neuron’s preferred orientation or just by their index. This is why we use Gaussian connections. I removed the sigma factor in your probability and I got activity only on neurons with similar orientations (around zero) while nothing else where.

Since you have a lot of fixed weight, setting proper weights is important.
Also, you can fix the probability of connectivity for your weights, like
I_to_I.connect(p=0.5)

Lastly, I noticed that you defined switching off your stimulus after 1000ms. That’s why you get background noise.

But, the aim of the project is to achieve sustained activity, so we need to switch off external input.

1 Like

Then that’s correct.

Hi everyone. It’s been a couple of years since I wrote this tutorial project, so I don’t remember everything in detail. It wasn’t meant to be a very accurate model of the real biological system, but rather an opportunity to try out some general things. What you should observe is that without inhibition, it is almost impossible to get sustained activity without getting “runaway firing”. You can increase the strength of the excitatory so that the network can excite itself enough so that it does not need input anymore, but then it will also recruit more and more excitatory neurons which in turn increases the excitation to the network, and everything blows up. What you should see is that you can use inhibition to balance this problem, in particular via the E->I->E feedback loop. With this loop in place, and by making the E->E weights stronger, you should be able to see sustained activity. As @elnaz91 said, in this type of model you would rather use unspecific connections to/from inhibitory neurons. Think of all inhibitory neurons as one global pool of inhibition that has its activity regulated by the strength of the activity of the excitatory neurons. You could probably remove the I->I connections from your model, which simply complicate things a bit without making any qualitative difference. Finding the right parameters for the connection is a bit of an art, but there are some ways to calculate the necessary values (as in the works of Nicolas Brunel from the early 2000s).

Let us know if that helps you get unstuck! I’ll move your post to a different category, since this is not so much about help with Brian itself, but more about modeling in general.

2 Likes

Hi, I made some changes about the structure of Sustained Activity (SA). I removed the periodic input and used an external current. With this changes it works well. Later I decided to see the effect of STDP on the network. As soon as I implement the STDP, it shows extreme activity even before the external current is applied. The code is simple actually, initially I am not applying the external current for 200 ms, then current is applied for 1000 ms, and then removed for 1000 ms. Thank you.

Any ideas will be appreciated. Thanks.