Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always set filter on post ensemble in connection #45

Merged
merged 2 commits into from
Sep 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/examples/node_ens_ens.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ def a_fn(x):
nengo_loihi.set_defaults()
with nengo.Network(seed=seed) as model:
u = nengo.Node(
output=nengo.processes.WhiteSignal(tend, high=5, seed=seed + 1),
output=nengo.processes.WhiteSignal(tend, high=2, seed=seed + 1),
size_out=d)
up = nengo.Probe(u, synapse=None)

a = nengo.Ensemble(100, d, label='a')
nengo.Connection(u, a, synapse=None)
nengo.Connection(u, a)
ap = nengo.Probe(a)
anp = nengo.Probe(a.neurons)
avp = nengo.Probe(a.neurons[:5], 'voltage')
Expand Down
19 changes: 16 additions & 3 deletions nengo_loihi/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ def build_ensemble(model, ens):
group.bias[:] = bias
model.build(ens.neuron_type, ens.neurons, group)

# set default filter just in case no other filter gets set
group.configure_filter(INTER_TAU, dt=model.dt, default=True)

if ens.noise is not None:
Expand Down Expand Up @@ -492,7 +493,7 @@ def build_connection(model, conn):
transform = get_samples(
conn.transform, conn.size_out, d=conn.size_mid, rng=rng)

tau_s = 0.0
tau_s = 0.0 # `synapse is None` gets mapped to `tau_s = 0.0`
if isinstance(conn.synapse, nengo.synapses.Lowpass):
tau_s = conn.synapse.tau
elif conn.synapse is not None:
Expand Down Expand Up @@ -520,6 +521,13 @@ def build_connection(model, conn):
# (max_rate = INTER_RATE * INTER_N) is the spike rate we
# use to represent a value of +/- 1
weights = weights / (INTER_RATE * INTER_N * model.dt)

if conn.synapse is None:
warnings.warn(
"No synapse set on Node connection. Since Node values are "
"converted to spikes to transmit to Loihi, not having a "
"synapse can cause increased spike noise. Consider using "
"a synapse.")
elif (isinstance(conn.pre_obj, Ensemble) and
isinstance(conn.pre_obj.neuron_type, nengo.Direct)):
raise NotImplementedError()
Expand Down Expand Up @@ -549,6 +557,7 @@ def build_connection(model, conn):

mid_cx = pre_cx
mid_axon_inds = slice(None)
post_tau = tau_s
if needs_interneurons and not isinstance(conn.post_obj, Neurons):
# --- add interneurons
assert weights.ndim == 2
Expand Down Expand Up @@ -601,7 +610,9 @@ def build_connection(model, conn):
weights2 = 0.5 * gain * np.vstack([weights,
-weights] * INTER_N).T

# use tau_s for filter into interneurons, and INTER_TAU for filter out
dec_cx.configure_filter(tau_s, dt=model.dt)
post_tau = INTER_TAU

dec_syn.set_full_weights(weights2)
dec_cx.add_synapses(dec_syn)
Expand Down Expand Up @@ -655,7 +666,7 @@ def build_connection(model, conn):
ax.target = syn
mid_cx.add_axons(ax)

post_cx.configure_filter(tau_s, dt=model.dt)
post_cx.configure_filter(post_tau, dt=model.dt)

if conn.learning_rule_type is not None:
raise NotImplementedError()
Expand All @@ -677,7 +688,7 @@ def build_connection(model, conn):
ax.target = syn
mid_cx.add_axons(ax)

post_cx.configure_filter(tau_s, dt=model.dt)
post_cx.configure_filter(post_tau, dt=model.dt)

if conn.learning_rule_type is not None:
raise NotImplementedError()
Expand All @@ -690,6 +701,8 @@ def build_connection(model, conn):
mid_ax.target_inds = mid_axon_inds
mid_cx.add_axons(mid_ax)
model.objs[conn]['mid_axons'] = mid_ax

post_cx.configure_filter(post_tau, dt=model.dt)
elif isinstance(conn.post_obj, Node):
raise NotImplementedError()
else:
Expand Down
17 changes: 14 additions & 3 deletions nengo_loihi/tests/test_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def test_node_to_neurons(precompute, allclose, Simulator, plt):
a = nengo.Ensemble(len(y), 1, label='a',
neuron_type=neuron_type, gain=gain, bias=bias)
ap = nengo.Probe(a.neurons)
nengo.Connection(u, a.neurons, synapse=None, transform=A)
nengo.Connection(u, a.neurons, transform=A)

with Simulator(model, precompute=precompute) as sim:
sim.run(tfinal)
Expand Down Expand Up @@ -93,7 +93,7 @@ def test_neuron_to_neuron(Simulator, factor, seed, allclose):
n = 10
stim = nengo.Node(lambda t: [np.sin(t * 2 * np.pi)])
a = nengo.Ensemble(n, 1)
nengo.Connection(stim, a, synapse=None)
nengo.Connection(stim, a)

b = nengo.Ensemble(n, 1, neuron_type=nengo.SpikingRectifiedLinear(),
gain=np.ones(n), bias=np.zeros(n))
Expand All @@ -115,7 +115,7 @@ def test_ensemble_to_neurons(Simulator, seed, allclose, plt):
with nengo.Network(seed=seed) as net:
stim = nengo.Node(lambda t: [np.sin(t * 2 * np.pi)])
pre = nengo.Ensemble(20, 1)
nengo.Connection(stim, pre, synapse=None)
nengo.Connection(stim, pre)

post = nengo.Ensemble(2, 1,
gain=[1., 1.], bias=[0., 0.])
Expand Down Expand Up @@ -159,3 +159,14 @@ def test_ensemble_to_neurons(Simulator, seed, allclose, plt):
assert allclose(np.sum(sim.data[p_post], axis=0) * sim.dt,
np.sum(nengosim.data[p_post], axis=0) * nengosim.dt,
atol=5)


def test_node_no_synapse_warning(Simulator):
with nengo.Network() as model:
n = nengo.Node([0, 0])
a = nengo.Ensemble(100, 2)
nengo.Connection(n, a, synapse=None)

with pytest.warns(UserWarning):
with Simulator(model):
pass
17 changes: 13 additions & 4 deletions nengo_loihi/tests/test_ensemble.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ def test_relu_response_curves(Simulator, plt, allclose):
@pytest.mark.parametrize("amplitude", (0.1, 0.5, 1))
@pytest.mark.parametrize(
"neuron_type", (nengo.SpikingRectifiedLinear, nengo.LIF))
def test_amplitude(Simulator, amplitude, neuron_type, seed, allclose):
def test_amplitude(Simulator, amplitude, neuron_type, seed, plt, allclose):
with nengo.Network(seed=seed) as net:
a = nengo.Node([0.5])
n = 100
ens = nengo.Ensemble(
n, 1, neuron_type=neuron_type(amplitude=amplitude))
ens2 = nengo.Ensemble(n, 1, gain=np.ones(n), bias=np.zeros(n),
neuron_type=nengo.SpikingRectifiedLinear())
nengo.Connection(a, ens, synapse=None)
nengo.Connection(a, ens)

# note: slight boost on transform so that the post neurons are pushed
# over threshold, rather than ==threshold
Expand All @@ -99,14 +99,23 @@ def test_amplitude(Simulator, amplitude, neuron_type, seed, allclose):
with Simulator(net, precompute=True) as sim:
sim.run(1)

spikemean1 = np.mean(sim.data[neuron_p], axis=0)
spikemean2 = np.mean(sim.data[neuron2_p], axis=0)

plt.subplot(211)
plt.plot(sim.trange(), sim.data[ens_p])
plt.subplot(212)
i = np.argsort(spikemean1)
plt.plot(spikemean1[i])
plt.plot(spikemean2[i], linestyle='--')

assert allclose(sim.data[ens_p][sim.trange() > 0.9], 0.5, atol=0.05)
assert np.max(sim.data[neuron_p]) == amplitude / sim.dt

# the identity neuron-to-neuron connection causes `ens2` to fire at
# `amplitude` * the firing rate of `ens` (i.e., the same overall firing
# rate as `ens`)
assert allclose(np.mean(sim.data[neuron_p], axis=0),
np.mean(sim.data[neuron2_p], axis=0), atol=1)
assert allclose(spikemean1, spikemean2, atol=1)

# note: one-timestep delay, despite synapse=None
assert allclose(sim.data[neuron_p][:-1], sim.data[indirect_p][1:])
12 changes: 6 additions & 6 deletions nengo_loihi/tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ def test_node_ens_ens(allclose, plt):
plt.subplot(413)
plt.plot(t, a[:, 0] ** 2, c="b", label="a[0]**2")
plt.plot(t, b[:, 0], c="g", label="b[0]")
plt.ylim([-1, 1])
plt.ylim([-0.05, 1])
plt.legend(loc=0)

plt.subplot(414)
plt.plot(t, a[:, 0] ** 2, c="b", label="a[1]**2")
plt.plot(t, b[:, 0], c="g", label="b[1]")
plt.ylim([-1, 1])
plt.plot(t, a[:, 1] ** 2, c="b", label="a[1]**2")
plt.plot(t, b[:, 1], c="g", label="b[1]")
plt.ylim([-0.05, 1])
plt.legend(loc=0)

tmask = t > 0.1 # ignore transients at the beginning
assert allclose(a[tmask], np.clip(u[tmask], -1, 1), atol=0.4, rtol=0.25)
assert allclose(b[tmask], a[tmask]**2, atol=0.35, rtol=0.0)
assert allclose(a[tmask], np.clip(u[tmask], -1, 1), atol=0.1, rtol=0.1)
assert allclose(b[tmask], a[tmask]**2, atol=0.15, rtol=0.2)
2 changes: 1 addition & 1 deletion nengo_loihi/tests/test_learning.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_pes_comm_channel(allclose, Simulator, seed, plt, N):

b = nengo.Node(None, size_in=1, size_out=1)

nengo.Connection(stim, a, synapse=None)
nengo.Connection(stim, a)
conn = nengo.Connection(
a, b, function=lambda x: 0, synapse=0.01,
learning_rule_type=nengo.PES(learning_rate=1e-3))
Expand Down
2 changes: 1 addition & 1 deletion nengo_loihi/tests/test_probe.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_voltage_decode(allclose, Simulator, seed, plt, dim):

a = nengo.Ensemble(100 * 3, dim,
intercepts=nengo.dists.Uniform(-.95, .95))
nengo.Connection(stim, a, synapse=None)
nengo.Connection(stim, a)

p_a = nengo.Probe(a, synapse=0.01)

Expand Down
4 changes: 2 additions & 2 deletions nengo_loihi/tests/test_radius.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def test_radius_probe(Simulator, seed, radius):
ens = nengo.Ensemble(n_neurons=100, dimensions=1,
radius=radius,
intercepts=nengo.dists.Uniform(-0.95, 0.95))
nengo.Connection(stim, ens, synapse=None)
nengo.Connection(stim, ens)
p = nengo.Probe(ens, synapse=0.1)
with Simulator(model, precompute=True) as sim:
sim.run(0.5)
Expand All @@ -30,7 +30,7 @@ def test_radius_ens_ens(Simulator, seed, radius1, radius2, weights):
b = nengo.Ensemble(n_neurons=100, dimensions=1,
radius=radius2,
intercepts=nengo.dists.Uniform(-0.95, 0.95))
nengo.Connection(stim, a, synapse=None)
nengo.Connection(stim, a)
nengo.Connection(a, b, synapse=0.01, transform=radius2 / radius1,
solver=nengo.solvers.LstsqL2(weights=weights))
p = nengo.Probe(b, synapse=0.1)
Expand Down