How can i control the initial state of the neuron membrane?

Hi !!!

I am trying to implement a CPG in nengo, my inputs are vectors formed with 0 and 1. I need to control the initial value of the neuron membrane so that different neurons are activated at a given time.

Hi @Ricardo, and welcome to the Nengo forums! :smiley:

You are able to set the initial state for most of the neuron types in Nengo (some neuron types don’t have initial states, so they can’t be set). The neuron construction contains an initial_state parameter which accepts a dictionary mapping a key value (state property) to a distribution (or array) specifying what the values of said state property should be.

The state properties vary between neuron types and you can see what each neuron type’s states are by looking at the Nengo source code (e.g., here it is for the default LIF neuron type)

You can then use these custom neuron types in the nengo.Ensemble constructor to create Nengo ensembles containing neurons with the custom initial states. As an example, the following code will create an ensemble with 10 neurons where the membrane voltages are initialized to 0:

ens = nengo.Ensemble(10, 1
    neuron_type=nengo.LIF(initial_state={"voltage": nengo.dists.Choice([0])}))

I should note that by default, the LIF neuron type initializes neurons with a random membrane voltage from the Uniform distribution from 0 to 1 (see the source code). That means that the default LIF neurons already have unique starting states.

Here’s some code where I compare two “identical” ensembles, both seeded with the same value (so the gain and biases are the same), but one having the default initial states, and the other having all of the initial membrane voltage values starting at 0.
test_ens_initial_state.py (784 Bytes)

And here’s the graph you should get when you run the code. You can see that the top plot (the default ensemble) has membrane voltages starting between 0 and 1, while the bottom plot has membrane voltages all starting at 0. Note that due to the way the Nengo simulator works with probes, probe data for the t=0 is not recorded (it’s a limitation).

1 Like

Hello, if I define the initial state of the LIF neuron with a value of 1, I would expect the neuron to fire when simulating. However, it does not do it; I only get it if I inject an external input with the Node function. I would like to know what parameter I should modify so that a neuron fires without stimulus if the membrane potential exceeds the threshold.

import numpy as np            
import nengo
import matplotlib.pyplot as plt
from nengo.utils.matplotlib import rasterplot

model = nengo.Network()
with model:
    inicial = nengo.Ensemble(                  
        1,                    
        dimensions = 1,          
        intercepts = [0],      
        max_rates = [400],        

        neuron_type=nengo.LIF(initial_state={"voltage": np.ones(1)}),
        encoders = [[1]],        
        seed=0,
    )

with model:

    #  without external input (the array has 0 as input)
    # i need that this neuron firing when the external input = 0
    start =     np.array([0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) # Change the first value to 1 to neuron firing
    
    Start_N = nengo.Node(nengo.processes.PresentInput(start, 0.002))

with model:
    nengo.Connection(Start_N, inicial, synapse = 0.0)  

with model:
    Input_Start     = nengo.Probe( Start_N)                    
    filtered_Start  = nengo.Probe(inicial, synapse=0.0001)    
    spikes_Start   = nengo.Probe(inicial.neurons)  
    voltage_Start   = nengo.Probe(inicial.neurons,"voltage")            

   

with nengo.Simulator(model) as sim:
    sim.run(0.049)

    plt.figure(1)
    plt.subplot(411)
    plt.plot(sim.trange(), sim.data[Input_Start],label='Input data')
    plt.plot(sim.trange(), sim.data[filtered_Start],label='Spikes filtered')  
    plt.xlabel("Time"), plt.title(" Start Injection")  
    plt.legend()
    plt.xlim(-0.01,0.1)

    plt.subplot(412)
    plt.plot(sim.trange(), sim.data[voltage_Start])
    plt.title("LIF neuron with 1 initial voltage")
    plt.grid()
    plt.xlim(-0.01,0.05)

    plt.subplot(413)
    rasterplot(sim.trange(), sim.data[spikes_Start])  
    plt.xlabel("Spike time"), plt.title("Fist Spike Volt_LIF = 1")
    plt.tight_layout()
    plt.xlim(-0.01,0.05)
    plt.grid()
    plt.show()

Hi @Ricardo,

My first thought would be to assign the voltage an initial state where it is > 1, because the condition for creating a spike is:

spiked_mask = voltage > 1

However, running that code immediately runs into problems, with the error:

Traceback (most recent call last):
  File "test_neuron_initial_state_spike.py", line 39, in <module>
    sim.step()
  File "/mnt/d/xchoo/Git/nengo/nengo/simulator.py", line 421, in step
    step_fn()
  File "/mnt/d/xchoo/Git/nengo/nengo/builder/neurons.py", line 97, in step_simneurons
    self.neurons.step(dt, J, output, **state)
  File "/mnt/d/xchoo/Git/nengo/nengo/neurons.py", line 682, in step
    t_spike = dt + tau_rc * np.log1p(
FloatingPointError: invalid value encountered in log1p

Basically, when Nengo is attempting to compute the spike timings, this line of code is getting values not valid to the computation.

After experimenting with your code a bit, it looks like it’s just a quirk of how you have set up the neuron itself. The problem is that the input J (or the input current to the neuron) is 1 at t==0. If you look at the equation being computed at line 677, when J==1, the denominator becomes 1-1 which then leads to a division by 0 error.

Tracing the problem further back, the reason why this is happening is because the neuron’s intercepts have been set to 0. This, coupled with the fixed input (Start_N) of 0 means that the neuron is right in the discontinuity of firing and not-firing, and the error in the computation on line 677 reflects that.

In typical operation, the neuron’s voltage never gets to a state where this can happen because there are checks after the spike is generated. However, as we are setting the neuron’s initial state manually, it’s apparently possible to get the neuron in the ambiguous state where the spike time computation can fail.

Fixing your issue, is, fortunately, quite straightforward. Simply change the intercept so that it is not exactly 0. :smiley:

If you set the intercept to a slightly negative number (e.g., -0.0001), you can leave the initial voltage state at 1 since the neuron is in the “firing” regime (because the input is 0). If you set the intercept to a slightly positive number (e.g., 0.0001), you’ll need to bump up the initial voltage state to > 1 to get the neuron into the firing regime to produce that first spike.

1 Like

Hello :slightly_smiling_face:

Currently I have managed to develop and validate the project I proposed using Nengo, however, when I change the simulator from Nengo to Nengo_Loihi I can’t get the same expected result. I have tried to adjust the parameters of the ensembles without success. I would like to know why this happens and if there is a way to switch from a project designed in Nengo to Nengo_Loihi. I leave as an example the following code fragment.

import numpy as np                 
import nengo    
import nengo_loihi                   

model = nengo.Network(label="Neuron") 
with model:                             
    neuron = nengo.Ensemble(                   
        1,                       
        dimensions = 1,          
        intercepts = [-0.0001],        
        max_rates  = [400],       
        neuron_type=nengo.LIF(initial_state={"voltage": np.ones(1)}),
        encoders = [[1]],       
    )

with model:
    my_spikes = np.array([1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0])     
    Input1    = nengo.Node(nengo.processes.PresentInput(my_spikes, 0.002)) 

with model:
    nengo.Connection(Input1,neuron, synapse= None)
     
with model:
    spikes = nengo.Probe(neuron.neurons)     

#with nengo_loihi.Simulator(model) as sim:  
with nengo.Simulator(model) as sim:  
    sim.run(0.048)                   
    

st = (np.where(np.any(sim.data[spikes]==1000, axis=1)))
st = (st[0]+1)/1000
print(st)

Expected correct result:

Captura de pantalla de 2022-07-29 13-14-36

Using the Nengo_Loihi simulator:

with nengo_loihi.Simulator(model) as sim:  
    sim.run(0.048)

Hi @Ricardo,

The reason is in your screenshot actually. :grinning:
If you look at the warning message that is given:

NengoLoihi does not support initial values for 'voltage" being non-zero on LIF neurons. On the chip, all values will be initialized to zero.

Due to hardware limitations, the neuron’s initial state can only be set in Nengo, but cannot be done so in NengoLoihi. The neurons implemented in the Loihi hardware itself doesn’t support this feature.