Skip to content

Commit 9517689

Browse files
author
Alexander Ororbia
committed
revised traces neurocog tutorial to v3
1 parent 80685ef commit 9517689

File tree

1 file changed

+23
-56
lines changed

1 file changed

+23
-56
lines changed

docs/tutorials/neurocog/traces.md

Lines changed: 23 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,17 @@
11
# Lecture 1B: Trace Variables and Filtering
22

3-
Traces represent one very important component tool in ngc-learn as these are
4-
often, in biophysical model simulations, used to produce real-valued
5-
representations of often discrete-valued patterns, e.g., spike vectors within
6-
a spike train, that can facilitate mechanisms such as online biological credit
7-
assignment. In this lesson, we will observe how one of ngc-learn's core
8-
trace components -- the `VarTrace` -- operates.
3+
Traces represent one very important component tool in ngc-learn as these are often, in biophysical model simulations, used to produce real-valued representations of often discrete-valued patterns, e.g., spike vectors within a spike train, that can facilitate mechanisms such as online biological credit assignment. In this lesson, we will observe how one of ngc-learn's core trace components -- the `VarTrace` -- operates.
94

105
## Setting Up a Variable Trace for a Poisson Spike Train
116

12-
To observe the value of a variable trace, we will pair it to another in-built
13-
ngc-component; the `PoissonCell`, which will be configured to emit spikes
14-
approximately at `63.75` Hertz (yielding a fairly sparse spike train). This means
15-
we will construct a two-component dynamical system, where the input
16-
compartment `outputs` of the `PoissonCell` will be wired directly into the
17-
`inputs` compartment of the `VarTrace`. Note that a `VarTrace` has an `inputs`
18-
compartment -- which is where raw signals typically go into -- and a `trace`
19-
output compartment -- which is where filtered signal values/by-products are emitted from.
7+
To observe the value of a variable trace, we will pair it to another in-built ngc-component; the `PoissonCell`, which will be configured to emit spikes approximately at `63.75` Hertz (yielding a fairly sparse spike train). This means we will construct a two-component dynamical system, where the input compartment `outputs` of the `PoissonCell` will be wired directly into the `inputs` compartment of the `VarTrace`. Note that a `VarTrace` has an `inputs` compartment -- which is where raw signals typically go into -- and a `trace` output compartment -- which is where filtered signal values/by-products are emitted from.
208

219
The code below will instantiate the paired Poisson cell and corresponding variable trace:
2210

2311
```python
2412
from jax import numpy as jnp, random, jit
25-
from ngclearn.utils import JaxProcess
26-
from ngcsimlib.context import Context
13+
14+
from ngclearn import Context, MethodProcess
2715
## import model-specific mechanisms
2816
from ngclearn.components.input_encoders.poissonCell import PoissonCell
2917
from ngclearn.components.other.varTrace import VarTrace
@@ -37,30 +25,24 @@ with Context("Model") as model:
3725
trace = VarTrace("tr0", n_units=1, tau_tr=30., a_delta=0.5)
3826

3927
## wire up cell z0 to trace tr0
40-
trace.inputs << cell.outputs
28+
cell.outputs >> trace.inputs
4129

42-
advance_process = (JaxProcess()
30+
advance_process = (MethodProcess("advance")
4331
>> cell.advance_state
4432
>> trace.advance_state)
45-
model.wrap_and_add_command(jit(advance_process.pure), name="advance")
4633

47-
reset_process = (JaxProcess()
34+
reset_process = (MethodProcess("reset")
4835
>> cell.reset
4936
>> trace.reset)
50-
model.wrap_and_add_command(jit(reset_process.pure), name="reset")
51-
5237

53-
@Context.dynamicCommand
54-
def clamp(x):
55-
cell.inputs.set(x)
38+
## set up some utility functions for the model context
39+
def clamp(x):
40+
cell.inputs.set(x)
5641
```
5742

5843
## Running the Paired Cell-Trace System
5944

60-
We can then run the above two-component dynamical system by injecting a fixed
61-
(valid) probability value into the Poisson input encoder and then record the
62-
resulting spikes and trace values. We will do this for `T = 200` milliseconds (ms)
63-
with the code below:
45+
We can then run the above two-component dynamical system by injecting a fixed (valid) probability value into the Poisson input encoder and then record the resulting spikes and trace values. We will do this for `T = 200` milliseconds (ms) with the code below:
6446

6547
```python
6648
dt = 1. # ms # integration time constant
@@ -70,22 +52,21 @@ probs = jnp.asarray([[0.35]],dtype=jnp.float32)
7052
time_span = []
7153
spikes = []
7254
traceVals = []
73-
model.reset()
55+
reset_process.run()
7456
for ts in range(T):
75-
model.clamp(probs)
76-
model.advance(t=ts*1., dt=dt)
57+
clamp(probs)
58+
advance_process.run(t=ts*1., dt=dt)
7759

78-
print("{} {}".format(cell.outputs.value, trace.trace.value), end="")
79-
spikes.append( cell.outputs.value )
80-
traceVals.append( trace.trace.value )
60+
print(f"\r{cell.outputs.get()} {trace.trace.get()}", end="")
61+
spikes.append( cell.outputs.get() )
62+
traceVals.append( trace.trace.get() )
8163
time_span.append(ts * dt)
8264
print()
8365
spikes = jnp.concatenate(spikes,axis=0)
8466
traceVals = jnp.concatenate(traceVals,axis=0)
8567
```
8668

87-
We can plot the above simulation's trace outputs with the discrete spikes
88-
super-imposed at their times of occurrence with the code below:
69+
We can plot the above simulation's trace outputs with the discrete spikes super-imposed at their times of occurrence with the code below:
8970

9071
```python
9172
import matplotlib #.pyplot as plt
@@ -100,8 +81,7 @@ stat = jnp.where(spikes > 0.)
10081
indx = (stat[0] * 1. - 1.).tolist()
10182
spk = ax.vlines(x=indx, ymin=0.985, ymax=1.05, colors='black', ls='-', lw=5)
10283

103-
ax.set(xlabel='Time (ms)', ylabel='Trace Output',
104-
title='Variable Trace of Poisson Spikes')
84+
ax.set(xlabel='Time (ms)', ylabel='Trace Output', title='Variable Trace of Poisson Spikes')
10585
#ax.legend([zTr[0],spk[0]],['z','phi(z)'])
10686
ax.grid()
10787
fig.savefig("poisson_trace.jpg")
@@ -111,29 +91,16 @@ to get the following output saved to disk:
11191

11292
<img src="../../images/tutorials/neurocog/poisson_trace.jpg" width="400" />
11393

114-
Notice that every time a spike is produced by the Poisson encoding cell, the trace
115-
increments by `0.5` -- the result of the `a_delta` hyper-parameter we set when
116-
crafting the model and simulation object -- and then exponentially decays in
117-
the absence of a spike (with the time constant of `tau_tr = 30` milliseconds).
94+
Notice that every time a spike is produced by the Poisson encoding cell, the trace increments by `0.5` -- the result of the `a_delta` hyper-parameter we set when crafting the model and simulation object -- and then exponentially decays in the absence of a spike (with the time constant of `tau_tr = 30` milliseconds).
11895

119-
The variable trace can be further configured to filter signals in different ways
120-
if desired; specifically by manipulating its `decay_type` and `a_delta` arguments.
121-
Notably, if a piecewise-gated variable trace is desired (a very common choice
122-
in some neuronal circuit models), then all one would have to do is set `a_delta = 0`,
123-
yielding the following line in the model creation code earlier in this tutorial:
96+
The variable trace can be further configured to filter signals in different ways if desired; specifically by manipulating its `decay_type` and `a_delta` arguments. Notably, if a piecewise-gated variable trace is desired (a very common choice in some neuronal circuit models), then all one would have to do is set `a_delta = 0`, yielding the following line in the model creation code earlier in this tutorial:
12497

12598
```python
12699
trace = VarTrace("tr0", n_units=1, tau_tr=30., a_delta=0., decay_type="exp")
127100
```
128101

129-
Running the same code from before but with the above alteration would yield the
130-
plot below:
102+
Running the same code from before but with the above alteration would yield the plot below:
131103

132104
<img src="../../images/tutorials/neurocog/poisson_trace_gate.jpg" width="400" />
133105

134-
Notice that, this time, when a spike is emitted from the Poisson cell, the trace
135-
is "clamped" to the value of one and then exponentially decays. Such a trace
136-
configuration is useful if one requires the maintained trace to never increase
137-
beyond a value of one, preventing divergence or run-away values if a spike train
138-
is particularly dense and yielding friendlier values for biological learning
139-
rules.
106+
Notice that, this time, when a spike is emitted from the Poisson cell, the trace is "clamped" to the value of one and then exponentially decays. Such a trace configuration is useful if one requires the maintained trace to never increase beyond a value of one, preventing divergence or run-away values if a spike train is particularly dense and yielding friendlier values for biological learning rules.

0 commit comments

Comments
 (0)