How to Stabilize Synaptic Currents Without Modifying Fixed Weights in Brian2

Hello everyone,

I’m working on a neural network simulation in Brian2, where I have a Poisson input driving a layer of neurons with fixed synaptic weights. My goal is to model realistic excitatory (I_exc) and inhibitory (I_inh) synaptic currents without altering the weights during the simulation.

However, I’ve noticed that under certain conditions—like when the number of input neurons is high or their firing rates increase—the synaptic currents (I_exc and I_inh) can grow uncontrollably. Sometimes, I_exc reaches extremely high values (e.g., 80,000 mV), which leads to unphysiological behavior and destabilizes the network.

Here are the constraints and details of my setup:

  • Fixed synaptic weights: I want the synaptic weights (w) to remain constant throughout the simulation.
  • High-density connectivity: Many input neurons are connected to the target population.
  • Desired solution: I’m looking for strategies to stabilize I_exc and I_inh currents while maintaining the fixed weights and input rates.

I’ve considered options like:

  1. Clipping the synaptic currents (I_exc and I_inh) globally.
  2. Adding synaptic current decay terms.
  3. Normalizing the cumulative synaptic input to a fixed range.

However, they didnt work properly.

My Questions:

What are the recommended practices in Brian2 to stabilize synaptic currents while keeping weights fixed?

Here’s a snippet of my current setup for reference:

p_in_v1_l4 = PoissonGroup(512, rates=100*Hz, name='poisson_input_v1_l4')
p_syn_v1_l4 = Synapses(
    p_in_v1_l4, L4_v1.neuron_groups["Exc"].group,
    model='''w : 1  # Synaptic weight
             spike_count : 1  # Tracks spikes for each presynaptic neuron''',
    delay=0*ms,
    on_pre='''I_exc_post += w*mV  # Update postsynaptic current
               spike_count += 1  # Track presynaptic spikes''',
    method='euler', 
    name='poisson_syn_v1_l4'
)

p_syn_v1_l4.connect()
p_syn_v1_l4.w = weights  # Fixed synaptic weights

scaling_rule = '''
w = clip(w / (1 + spike_count), 0, 1)  # Scale weights and keep in [0, 1]
spike_count = 0  # Reset spike counter
'''

p_syn_v1_l4.run_regularly(scaling_rule, dt=defaultclock.dt)  # Apply scaling every 0.1 ms

I’d greatly appreciate any suggestions. Thanks in advance for your help!

I resolved the issue by scaling the weights, although this is not my preferred approach, as it disrupts the balance between excitation and inhibition.

# Pre-synaptic scaling: Normalize by the number of pre-synaptic neurons
    synaptic_weights = synaptic_weights/np.sqrt(num_pre_neurons)

    # Scale the synaptic weights using post-synaptic norms
    post_norm_squared = np.linalg.norm(post_weights.T, axis=1)**2  # Shape: [num_post_neurons]
    synaptic_weights = 2 * scale * synaptic_weights / post_norm_squared  # Element-wise scaling
'''

Hi @elnaz91. I did not completely understand the issue, but if the axes in your plot are really in mV, then your inputs seem to be several orders of magnitudes too strong, and lead to extremely pathological activity. With your setup, you have roughly 500 excitatory spikes incoming every 10ms, so I’d say the individual weights should be on the order of 0.1mV or less, maybe? I did not quite understand why you do not want to scale the weights.

In your initial code, you have a scaling rule that divides weights by 2 every time a synapse spikes, is that really what is intended? I did not see a trace of it in the plot, but maybe I am missing something.

One more remark: with p_syn_v1_l4.connect(), you are connecting the PoissonGroup to the NeuronGroup in an all-to-all fashion, which means that each neuron receives the input from each Poisson neuron, i.e. all neurons receive the exact same input spikes – is this what you want?

Sorry, this is probably not a very helpful answer, but maybe it gives you a few ideas what to look at.

1 Like

Hi Marcel

Thanks for the insight, Marcel! Actually, your suggestion to control the input rate was really effective. I managed to scale the rate such that, on average, one spike arrives at the neuron from the Poisson population. This adjustment helped in preventing those unrealistically high values I was dealing with before. I appreciate your help!

1 Like