Skip to content

Commit 13cfbd4

Browse files
author
Alexander Ororbia
committed
revised izh-cell, cleaned-up fn-cell, and revised lif neurocog docs
1 parent 08c788a commit 13cfbd4

File tree

3 files changed

+37
-77
lines changed

3 files changed

+37
-77
lines changed

docs/tutorials/neurocog/fitzhugh_nagumo_cell.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ w0 = -0.16983366 ## initial recovery value (for reset condition)
3535

3636
## create simple system with only one F-N cell
3737
with Context("Model") as model:
38-
cell = FitzhughNagumoCell("z0", n_units=1, tau_w=tau_w, alpha=alpha, beta=beta,
39-
gamma=gamma, v0=v0, w0=w0, integration_type="euler")
38+
cell = FitzhughNagumoCell(
39+
"z0", n_units=1, tau_w=tau_w, alpha=alpha, beta=beta, gamma=gamma, v0=v0, w0=w0, integration_type="euler"
40+
)
4041

4142
## create and compile core simulation commands
4243
advance_process = (MethodProcess("advance")

docs/tutorials/neurocog/izhikevich_cell.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ coupling_factor = 0.2
3838

3939
## create simple system with only one Izh Cell
4040
with Context("Model") as model:
41-
cell = IzhikevichCell("z0", n_units=1, tau_w=tau_w, v_reset=v_reset,
42-
w_reset=w_reset, coupling_factor=coupling_factor,
43-
integration_type="euler", v0=v0, w0=w0, key=subkeys[0])
41+
cell = IzhikevichCell(
42+
"z0", n_units=1, tau_w=tau_w, v_reset=v_reset, w_reset=w_reset, coupling_factor=coupling_factor,
43+
integration_type="euler", v0=v0, w0=w0, key=subkeys[0]
44+
)
4445

4546
## create and compile core simulation commands
4647
advance_process = (MethodProcess("advance")
@@ -123,8 +124,9 @@ n_plots = 1
123124
fig, ax = plt.subplots(1, n_plots, figsize=(5*n_plots,5))
124125

125126
ax_ptr = ax
126-
ax_ptr.set(xlabel='Time', ylabel='Voltage (v), Recovery (w)',
127-
title="Izhikevich (RS) Voltage/Recovery Dynamics")
127+
ax_ptr.set(
128+
xlabel='Time', ylabel='Voltage (v), Recovery (w)', title=f"Izhikevich ({cell_tag}) Voltage/Recovery Dynamics"
129+
)
128130

129131
v = ax_ptr.plot(time_span, mem_rec, color='C0')
130132
w = ax_ptr.plot(time_span, recov_rec, color='C1', alpha=.5)

docs/tutorials/neurocog/lif.md

Lines changed: 27 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,15 @@
11
# Lecture 2B: The Leaky Integrate-and-Fire Cell
22

3-
The leaky integrate-and-fire (LIF) cell component in ngc-learn is a stepping
4-
stone towards working with more biophysical intricate cell components when crafting
5-
your neuronal circuit models. This
6-
[cell](ngclearn.components.neurons.spiking.LIFCell) is markedly different from the
7-
[simplified LIF](ngclearn.components.neurons.spiking.sLIFCell) in both its
8-
implemented dynamics as well as what modeling routines that it offers, including
9-
the fact that it does not offer implicit fixed lateral inhibition like the
10-
`SLIF` does (one would need to explicitly model the lateral inhibition as a
11-
separate population of `LIF` cells, as we do in the
12-
[Diehl and Cook model museum spiking network](../../museum/snn_dc.md)). Furthermore,
13-
using this neuronal cell is a useful transition to using the more complicated and
14-
biophysically more accurate neuronal models such as the
15-
[adaptive exponential integrator cell](ngclearn.components.neurons.spiking.adExCell)
16-
or the
17-
[Izhikevich cell](ngclearn.components.neurons.spiking.izhikevichCell).
3+
The leaky integrate-and-fire (LIF) cell component in ngc-learn is a stepping stone towards working with more biophysical intricate cell components when crafting your neuronal circuit models. This [cell](ngclearn.components.neurons.spiking.LIFCell) is markedly different from the [simplified LIF](ngclearn.components.neurons.spiking.sLIFCell) in both its implemented dynamics as well as what modeling routines that it offers, including the fact that it does not offer implicit fixed lateral inhibition like the `SLIF` does (one would need to explicitly model the lateral inhibition as a separate population of `LIF` cells, as we do in the [Diehl and Cook model museum spiking network](../../museum/snn_dc.md)). Furthermore, using this neuronal cell is a useful transition to using the more complicated and biophysically more accurate neuronal models such as the [adaptive exponential integrator cell](ngclearn.components.neurons.spiking.adExCell) or the [Izhikevich cell](ngclearn.components.neurons.spiking.izhikevichCell).
184

195
## Instantiating the LIF Neuronal Cell
206

21-
To implement a single-component dynamical system made up of a single LIF
22-
cell, you would write code akin to the following:
7+
To implement a single-component dynamical system made up of a single LIF cell, you would write code akin to the following:
238

249
```python
2510
from jax import numpy as jnp, random, jit
2611

27-
from ngcsimlib.context import Context
28-
from ngclearn.utils import JaxProcess
12+
from ngclearn import Context, MethodProcess
2913
## import model-specific mechanisms
3014
from ngclearn.components.neurons.spiking.LIFCell import LIFCell
3115
from ngclearn.utils.viz.spike_plot import plot_spiking_neuron
@@ -42,35 +26,27 @@ tau_m = 100.
4226

4327
## create simple system with only one AdEx
4428
with Context("Model") as model:
45-
cell = LIFCell("z0", n_units=1, tau_m=tau_m, resist_m=tau_m/dt, thr=V_thr,
46-
v_rest=V_rest, v_reset=-60., tau_theta=300., theta_plus=0.05,
47-
refract_time=2., key=subkeys[0])
29+
cell = LIFCell(
30+
"z0", n_units=1, tau_m=tau_m, resist_m=tau_m/dt, thr=V_thr, v_rest=V_rest, v_reset=-60., tau_theta=300.,
31+
theta_plus=0.05, refract_time=2., key=subkeys[0]
32+
)
4833

4934
## create and compile core simulation commands
50-
advance_process = (JaxProcess()
35+
advance_process = (MethodProcess("advance")
5136
>> cell.advance_state)
52-
model.wrap_and_add_command(jit(advance_process.pure), name="advance")
5337

54-
reset_process = (JaxProcess()
38+
reset_process = (MethodProcess("reset")
5539
>> cell.reset)
56-
model.wrap_and_add_command(jit(reset_process.pure), name="reset")
5740

5841

59-
## set up non-compiled utility commands
60-
@Context.dynamicCommand
61-
def clamp(x):
62-
cell.j.set(x)
42+
## set up non-compiled utility commands
43+
def clamp(x):
44+
cell.j.set(x)
6345
```
6446

6547
## Simulating the LIF on Stepped Constant Electrical Current
6648

67-
Given our single-LIF dynamical system above, let us write some code to use
68-
our `LIF` node and visualize the resultant spiking pattern super-imposed
69-
over its membrane (voltage) potential by feeding
70-
into it a step current, where the electrical current `j` starts at $0$ then
71-
switches to $0.3$ at $t = 10$ ms (much as we did for the `SLIF` component
72-
in the previous lesson). We craft the simulation portion of our code like so:
73-
49+
Given our single-LIF dynamical system above, let us write some code to use our `LIF` node and visualize the resultant spiking pattern super-imposed over its membrane (voltage) potential by feeding into it a step current, where the electrical current `j` starts at $0$ then switches to $0.3$ at $t = 10$ ms (much as we did for the `SLIF` component in the previous lesson). We craft the simulation portion of our code like so:
7450

7551
```python
7652
# create a synthetic electrical step current
@@ -80,58 +56,39 @@ curr_in = []
8056
mem_rec = []
8157
spk_rec = []
8258

83-
model.reset()
59+
reset_process.run()
8460
for ts in range(current.shape[1]):
8561
j_t = jnp.expand_dims(current[0,ts], axis=0) ## get data at time ts
86-
model.clamp(j_t)
87-
model.advance(t=ts*1., dt=dt)
62+
clamp(j_t)
63+
advance_process.run(t=ts*1., dt=dt)
8864
## naively extract simple statistics at time ts and print them to I/O
89-
v = cell.v.value
90-
s = cell.s.value
65+
v = cell.v.get()
66+
s = cell.s.get()
9167
curr_in.append(j_t)
9268
mem_rec.append(v)
9369
spk_rec.append(s)
9470
print("\r {}: s {} ; v {}".format(ts, s, v), end="")
9571
print()
9672
```
9773

98-
Then, we can plot the input current, the neuron's voltage `v`, and its output
99-
spikes as follows:
74+
Then, we can plot the input current, the neuron's voltage `v`, and its output spikes as follows:
10075

10176
```python
10277
import numpy as np
10378
curr_in = np.squeeze(np.asarray(curr_in))
10479
mem_rec = np.squeeze(np.asarray(mem_rec))
10580
spk_rec = np.squeeze(np.asarray(spk_rec))
106-
plot_spiking_neuron(curr_in, mem_rec, spk_rec, None, dt, thr_line=V_thr, min_mem_val=V_rest-1.,
107-
max_mem_val=V_thr+2., spike_loc=V_thr, spike_spr=0.5, title="LIF-Node: Constant Electrical Input", fname="lif_plot.jpg")
81+
plot_spiking_neuron(
82+
curr_in, mem_rec, spk_rec, None, dt, thr_line=V_thr, min_mem_val=V_rest-1., max_mem_val=V_thr+2., spike_loc=V_thr,
83+
spike_spr=0.5, title="LIF-Node: Constant Electrical Input", fname="lif_plot.jpg"
84+
)
10885
```
10986

11087
which should produce the following plot (saved to disk):
11188

11289
<img src="../../images/tutorials/neurocog/lif_plot.jpg" width="600" />
11390

114-
As we might observe, the LIF operates very differently from the SLIF, notably
115-
that its dynamics live in the different space of values (one aspect of the
116-
SLIF is that its dynamics are effectively normalized/configured to live
117-
a non-negative membrane potential number space), specifically values that
118-
are a bit better aligned with those observed in experimental neuroscience.
119-
While more biophysically more accurate, the `LIF` typically involves consideration
120-
of multiple additional hyper-parameters/simulation coefficients, including
121-
the resting membrane potential value `v_rest` and the reset membrane value
122-
`v_reset` (upon occurrence of a spike/emitted action potential); the `SLIF`,
123-
in contrast, assumed a `v_reset = v_reset = 0.`. Note that the `LIF`'s
124-
`tau_theta` and `theta_plus` coefficients govern its particular adaptive threshold,
125-
which is a particular increment variable (one per cell in the `LIF` component)
126-
that gets adjusted according to its own dynamics and added to the fixed constant
127-
threshold `thr`, i.e., the threshold that a cell's membrane potential must
128-
exceed for a spike to be emitted.
129-
130-
The `LIF` cell component is particularly useful when more flexibility is required/
131-
desired in setting up neuronal dynamics, particularly when attempting to match
132-
various mathematical models that have been proposed in computational neuroscience.
133-
This benefit comes at the greater cost of additional tuning and experimental planning,
134-
whereas the `SLIF` can be a useful go-to initial spiking cell for building certain spiking
135-
models such as those proposed in machine intelligence research (we demonstrate
136-
one such use-case in the context of the
137-
[feedback alignment-trained spiking network](../../museum/snn_bfa.md) that we offer in the model museum).
91+
As we might observe, the LIF operates very differently from the SLIF, notably that its dynamics live in the different space of values (one aspect of the SLIF is that its dynamics are effectively normalized/configured to live a non-negative membrane potential number space), specifically values that are a bit better aligned with those observed in experimental neuroscience. While more biophysically more accurate, the `LIF` typically involves consideration of multiple additional hyper-parameters/simulation coefficients, including
92+
the resting membrane potential value `v_rest` and the reset membrane value `v_reset` (upon occurrence of a spike/emitted action potential); the `SLIF`, in contrast, assumed a `v_reset = v_reset = 0.`. Note that the `LIF`'s `tau_theta` and `theta_plus` coefficients govern its particular adaptive threshold, which is a particular increment variable (one per cell in the `LIF` component) that gets adjusted according to its own dynamics and added to the fixed constant threshold `thr`, i.e., the threshold that a cell's membrane potential must exceed for a spike to be emitted.
93+
94+
The `LIF` cell component is particularly useful when more flexibility is required/desired in setting up neuronal dynamics, particularly when attempting to match various mathematical models that have been proposed in computational neuroscience. This benefit comes at the greater cost of additional tuning and experimental planning, whereas the `SLIF` can be a useful go-to initial spiking cell for building certain spiking models such as those proposed in machine intelligence research (we demonstrate one such use-case in the context of the [feedback alignment-trained spiking network](../../museum/snn_bfa.md) that we offer in the model museum).

0 commit comments

Comments
 (0)