def test_pes_error_clip(plt, seed, Simulator): dims = 2 n_per_dim = 120 tau = 0.01 error_scale = 5. # scale up error signal so it clips simtime = 0.3 model, probes = pes_network( n_per_dim, dims, seed, learn_synapse=tau, learning_rule_type=nengo.PES(learning_rate=1e-2 / error_scale), input_scale=np.array([1., -1.]), error_scale=error_scale, period=simtime) with pytest.warns(UserWarning, match=r'.*PES error.*Clipping.'): with Simulator(model) as loihi_sim: loihi_sim.run(simtime) t = loihi_sim.trange() post_tmask = t > simtime - 1.0 dec_tau = loihi_sim.model.decode_tau y = loihi_sim.data[probes['stim']] y_dpre = nengo.Lowpass(dec_tau).filt(y) y_dpost = nengo.Lowpass(tau).combine(nengo.Lowpass(dec_tau)).filt(y_dpre) y_loihi = loihi_sim.data[probes['post']] plt.plot(t, y_dpost, 'k', label='target') plt.plot(t, y_loihi, 'g', label='loihi') # --- assert that we've learned something, but not everything error = (rms(y_loihi[post_tmask] - y_dpost[post_tmask]) / rms(y_dpost[post_tmask])) assert error < 0.5 assert error > 0.05
def test_compare_solvers(Simulator, plt, seed, allclose): pytest.importorskip("sklearn") N = 70 decoder_solvers = [ Lstsq(), LstsqNoise(), LstsqL2(), LstsqL2nz(), LstsqL1(max_iter=5000), ] weight_solvers = [LstsqL1(weights=True, max_iter=5000), LstsqDrop(weights=True)] tfinal = 4 def input_function(t): return np.interp(t, [1, 3], [-1, 1], left=-1, right=1) model = nengo.Network(seed=seed) with model: u = nengo.Node(output=input_function) a = nengo.Ensemble(N, dimensions=1) nengo.Connection(u, a) ap = nengo.Probe(a) probes = [] names = [] for solver in decoder_solvers + weight_solvers: b = nengo.Ensemble(N, dimensions=1, seed=seed + 1) nengo.Connection(a, b, solver=solver) probes.append(nengo.Probe(b)) names.append( "%s(%s)" % (type(solver).__name__, "w" if solver.weights else "d") ) with Simulator(model) as sim: sim.run(tfinal) t = sim.trange() # ref = sim.data[up] ref = nengo.Lowpass(0.02).filtfilt(sim.data[ap], dt=sim.dt) outputs = np.array([sim.data[probe][:, 0] for probe in probes]).T outputs_f = nengo.Lowpass(0.02).filtfilt(outputs, dt=sim.dt) close = signals_allclose( t, ref, outputs_f, atol=0.07, rtol=0, buf=0.1, delay=0.007, plt=plt, labels=names, individual_results=True, allclose=allclose, ) for name, c in zip(names, close): assert c, "Solver '%s' does not meet tolerances" % name
def test_direct_window(legendre, Simulator, seed, plt): theta = 1.0 T = theta assert np.allclose(t_default, np.linspace(0, 1, 1000)) with Network() as model: stim = nengo.Node(output=lambda t: t) rw = RollingWindow(theta, n_neurons=1, dimensions=12, neuron_type=nengo.Direct(), process=None, legendre=legendre) assert rw.theta == theta assert rw.dt == 0.001 assert rw.process is None assert rw.synapse == nengo.Lowpass(0.1) assert rw.input_synapse == nengo.Lowpass(0.1) nengo.Connection(stim, rw.input, synapse=None) output = rw.add_output(function=lambda w: np.sum(w**3)**2) p_output = nengo.Probe(output, synapse=None) with Simulator(model) as sim: sim.run(T) actual = sim.data[p_output].squeeze() t = sim.trange() ideal = shift(np.cumsum(t**3)**2) plt.figure() plt.plot(t, actual, label="Output") plt.plot(t, ideal, label="Ideal", linestyle='--') plt.legend() assert nrmse(actual, ideal) < 0.005
def test_eval_points(Simulator, nl_nodirect, plt, seed, rng, logger): n = 100 d = 5 filter = 0.08 eval_points = np.logspace(np.log10(300), np.log10(5000), 11) eval_points = np.round(eval_points).astype("int") max_points = eval_points.max() n_trials = 1 rmses = np.nan * np.zeros((len(eval_points), n_trials)) for j in range(n_trials): points = rng.normal(size=(max_points, d)) points *= (rng.uniform(size=max_points) / norm(points, axis=-1))[:, None] rng_j = np.random.RandomState(348 + j) seed = 903824 + j # generate random input in unit hypersphere x = rng_j.normal(size=d) x *= rng_j.uniform() / norm(x) for i, n_points in enumerate(eval_points): model = nengo.Network(seed=seed) with model: model.config[nengo.Ensemble].neuron_type = nl_nodirect() u = nengo.Node(output=x) a = nengo.Ensemble(n * d, dimensions=d, eval_points=points[:n_points]) nengo.Connection(u, a, synapse=0) up = nengo.Probe(u) ap = nengo.Probe(a) with Timer() as timer: sim = Simulator(model) sim.run(10 * filter) sim.close() t = sim.trange() xt = nengo.Lowpass(filter).filtfilt(sim.data[up], dt=sim.dt) yt = nengo.Lowpass(filter).filtfilt(sim.data[ap], dt=sim.dt) t0 = 5 * filter t1 = 7 * filter tmask = (t > t0) & (t < t1) rmses[i, j] = rms(yt[tmask] - xt[tmask]) logger.info("trial %d", j) logger.info(" n_points: %d", n_points) logger.info(" duration: %0.3f s", timer.duration) # subtract out mean for each model rmses_norm = rmses - rmses.mean(0, keepdims=True) mean = rmses_norm.mean(1) low = rmses_norm.min(1) high = rmses_norm.max(1) plt.semilogx(eval_points, mean, "k-") plt.semilogx(eval_points, high, "r-") plt.semilogx(eval_points, low, "b-") plt.xlim([eval_points[0], eval_points[-1]]) plt.xticks(eval_points, eval_points)
def test_chip_to_host_function_points(Simulator, seed, plt, allclose): """Connection from chip to host that computes a function using points""" fn = lambda x: -x probe_syn = nengo.Lowpass(0.03) simtime = 0.3 with nengo.Network(seed=seed) as net: u = nengo.Node(lambda t: np.sin((2 * np.pi / simtime) * t)) a = nengo.Ensemble(100, 1) # v has a function so it doesn't get removed as passthrough v = nengo.Node(lambda t, x: x + 1e-8, size_in=1) nengo.Connection(u, a, synapse=None) x = np.linspace(-1, 1, 1000).reshape(-1, 1) y = fn(x) nengo.Connection(a, v, synapse=None, eval_points=x, function=y) up = nengo.Probe(u, synapse=probe_syn.combine(nengo.Lowpass(0.005))) vp = nengo.Probe(v, synapse=probe_syn) with Simulator(net) as sim: sim.run(simtime) y_ref = fn(sim.data[up]) plt.plot(sim.trange(), y_ref) plt.plot(sim.trange(), sim.data[vp]) assert allclose(sim.data[vp], y_ref, atol=0.1)
def test_network_copies_defaults(): original = nengo.Network() original.config[nengo.Ensemble].radius = 1.5 original.config[nengo.Connection].synapse = nengo.Lowpass(0.1) cp = original.copy() assert cp.config[nengo.Ensemble].radius == 1.5 assert cp.config[nengo.Connection].synapse == nengo.Lowpass(0.1)
def test_pes_comm_channel(dims, allclose, plt, seed, Simulator): n_per_dim = 120 tau = 0.01 simtime = 1.5 model, probes = pes_network( n_per_dim, dims, seed, learn_synapse=tau, learning_rule_type=nengo.PES(learning_rate=1e-2), period=simtime / 2) with nengo.Simulator(model) as nengo_sim: nengo_sim.run(simtime) with Simulator(model) as loihi_sim: loihi_sim.run(simtime) with Simulator(model, target='simreal') as real_sim: real_sim.run(simtime) t = nengo_sim.trange() pre_tmask = t > 0.1 post_tmask = t > simtime / 2 dec_tau = loihi_sim.model.decode_tau y = nengo_sim.data[probes['stim']] y_dpre = nengo.Lowpass(dec_tau).filt(y) y_dpost = nengo.Lowpass(tau).combine(nengo.Lowpass(dec_tau)).filt(y_dpre) y_nengo = nengo_sim.data[probes['post']] y_loihi = loihi_sim.data[probes['post']] y_real = real_sim.data[probes['post']] plt.subplot(211) plt.plot(t, y_dpost, 'k', label='target') plt.plot(t, y_nengo, 'b', label='nengo') plt.plot(t, y_loihi, 'g', label='loihi') plt.plot(t, y_real, 'r:', label='real') plt.legend() plt.subplot(212) plt.plot(t[post_tmask], y_loihi[post_tmask] - y_dpost[post_tmask], 'k') plt.plot(t[post_tmask], y_loihi[post_tmask] - y_nengo[post_tmask], 'b') x_loihi = loihi_sim.data[probes['pre']] assert allclose(x_loihi[pre_tmask], y_dpre[pre_tmask], atol=0.1, rtol=0.05) assert allclose(y_loihi[post_tmask], y_dpost[post_tmask], atol=0.1, rtol=0.05) assert allclose(y_loihi, y_nengo, atol=0.2, rtol=0.2) assert allclose(y_real[post_tmask], y_dpost[post_tmask], atol=0.1, rtol=0.05) assert allclose(y_real, y_nengo, atol=0.2, rtol=0.2)
def generate(net=None, n_neurons=200, alpha=1000.0, beta=1000.0/4.0, dt=0.001, analog=False): tau = 0.1 # synaptic time constant synapse = nengo.Lowpass(tau) # the A matrix for our point attractor A = np.array([[0.0, 1.0], [-alpha*beta, -alpha]]) # the B matrix for our point attractor B = np.array([[0.0], [alpha*beta]]) # if you have the nengolib library you can do it this way # from nengolib.synapses import ss2sim # C = np.eye(2) # D = np.zeros((2, 2)) # linsys = ss2sim((A, B, C, D), synapse=synapse, dt=None if analog else dt) # A = linsys.A # B = linsys.B if analog: # account for continuous lowpass filter A = tau * A + np.eye(2) B = tau * B else: # discretize state matrices Ad = expm(A*dt) Bd = np.dot(np.linalg.inv(A), np.dot((Ad - np.eye(2)), B)) # account for discrete lowpass filter a = np.exp(-dt/tau) A = 1.0 / (1.0 - a) * (Ad - a * np.eye(2)) B = 1.0 / (1.0 - a) * Bd if net is None: net = nengo.Network(label='Point Attractor') config = nengo.Config(nengo.Connection, nengo.Ensemble) config[nengo.Connection].synapse = nengo.Lowpass(tau) with config, net: net.ydy = nengo.Ensemble(n_neurons=n_neurons, dimensions=2, # set it up so neurons are tuned to one dimensions only encoders=nengo.dists.Choice([[1, 0], [-1, 0], [0, 1], [0, -1]])) # set up Ax part of point attractor nengo.Connection(net.ydy, net.ydy, transform=A) # hook up input net.input = nengo.Node(size_in=1, size_out=1) # set up Bu part of point attractor nengo.Connection(net.input, net.ydy, transform=B) # hook up output net.output = nengo.Node(size_in=1, size_out=1) # add in forcing function nengo.Connection(net.ydy[0], net.output, synapse=None) return net
def test_pes_overflow(plt, seed, Simulator): dims = 3 n_per_dim = 300 tau = 0.01 simtime = 0.6 model, probes = pes_network( n_per_dim, dims, seed, learn_synapse=tau, input_scale=np.linspace(1, 0.7, dims), learning_rule_type=nengo.PES(learning_rate=1e-2), period=simtime, ) loihi_model = Model() # set learning_wgt_exp low to create overflow in weight values loihi_model.pes_wgt_exp = -2 with Simulator( model, model=loihi_model, hardware_options={"allocator": RoundRobin()}, ) as loihi_sim: loihi_sim.run(simtime) t = loihi_sim.trange() post_tmask = t > simtime - 0.1 dec_tau = loihi_sim.model.decode_tau y = loihi_sim.data[probes["stim"]] y_dpre = nengo.Lowpass(dec_tau).filt(y) y_dpost = nengo.Lowpass(tau).combine(nengo.Lowpass(dec_tau)).filt(y_dpre) y_loihi = loihi_sim.data[probes["post"]] plt.plot(t, y_dpost, "k", label="target") plt.plot(t, y_loihi, "g", label="loihi") # --- fit output to scaled version of target output z_ref0 = y_dpost[post_tmask][:, 0] z_loihi = y_loihi[post_tmask] scale = np.linspace(0, 1, 50) E = np.abs(z_loihi - scale[:, None, None] * z_ref0[:, None]) errors = E.mean(axis=1) # average over time (errors is: scales x dims) for j in range(dims): errors_j = errors[:, j] i = np.argmin(errors_j) assert errors_j[i] < 0.1, ("Learning output for dim %d did not match " "any scaled version of the target output" % j) assert scale[i] > 0.25, "Learning output for dim %d is too small" % j assert scale[i] < 0.9, ( "Learning output for dim %d is too large " "(weights or traces not clipping as expected)" % j)
def test_equivalent_filters(self, minimise): """Test construction of filter regions from signals and keyspaces.""" # Create two keyspaces, two signal parameters and two reception # parameters with equivalent synapses. ks_a = mock.Mock(name="Keyspace[A]") signal_a = SignalParameters(keyspace=ks_a, latching=False) ks_b = mock.Mock(name="Keyspace[B]") signal_b = SignalParameters(keyspace=ks_b, latching=False) rp_a = ReceptionParameters(nengo.Lowpass(0.01), 3, None) rp_b = ReceptionParameters(nengo.Lowpass(0.01), 3, None) # Create the data structure that is expected as input specs = [ ReceptionSpec(signal_a, rp_a), ReceptionSpec(signal_b, rp_b), ] # Create the regions, with minimisation filter_region, routing_region = make_filter_regions( specs, 0.001, minimise=minimise, filter_routing_tag="spam", index_field="eggs") # Check that the filter region is as expected assert filter_region.dt == 0.001 if minimise: assert len(filter_region.filters) == 1 assert filter_region.filters[0] == LowpassFilter(3, False, 0.01) else: assert len(filter_region.filters) == 2 assert filter_region.filters[0] == LowpassFilter(3, False, 0.01) assert filter_region.filters[1] == LowpassFilter(3, False, 0.01) # Check that the routing region is as expected assert routing_region.filter_routing_tag == "spam" assert routing_region.index_field == "eggs" if minimise: assert (signal_a, 0) in routing_region.signal_routes assert (signal_b, 0) in routing_region.signal_routes else: if (signal_a, 0) in routing_region.signal_routes: assert (signal_b, 1) in routing_region.signal_routes else: assert (signal_b, 0) in routing_region.signal_routes
def test_forced_filter_width(self): """Test construction of filter regions from signals and keyspaces.""" # Create two keyspaces, two signals and two connections with equivalent # synapses. # Create two keyspaces, two signals and two reception parameters with # different synapses. ks_a = mock.Mock(name="Keyspace[A]") signal_a = SignalParameters(keyspace=ks_a, latching=False) ks_b = mock.Mock(name="Keyspace[B]") signal_b = SignalParameters(keyspace=ks_b, latching=False) rp_a = ReceptionParameters(nengo.Lowpass(0.01), 3, None) rp_b = ReceptionParameters(None, 5, None) # Create the type of dictionary that is expected as input specs = [ ReceptionSpec(signal_a, rp_a), ReceptionSpec(signal_b, rp_b), ] # Create the regions, with minimisation filter_region, routing_region = make_filter_regions(specs, 0.001, width=1) # Check that the filter region is as expected for f in filter_region.filters: assert (f == LowpassFilter(1, False, 0.01) or f == NoneFilter(1, False)) # noqa: E711
def test_weights(Simulator, nl, plt, seed): n1, n2 = 100, 50 def func(t): return [np.sin(4 * t), np.cos(12 * t)] transform = np.array([[0.6, -0.4]]) m = nengo.Network(label='test_weights', seed=seed) with m: m.config[nengo.Ensemble].neuron_type = nl() u = nengo.Node(output=func) a = nengo.Ensemble(n1, dimensions=2, radius=1.5) b = nengo.Ensemble(n2, dimensions=1) bp = nengo.Probe(b) nengo.Connection(u, a) nengo.Connection(a, b, transform=transform, solver=LstsqL2(weights=True)) with Simulator(m) as sim: sim.run(1.) t = sim.trange() x = np.array(func(t)).T y = np.dot(x, transform.T) z = nengo.Lowpass(0.005).filtfilt(sim.data[bp], dt=sim.dt) assert allclose(t, y, z, atol=0.1, buf=0.1, delay=0.01, plt=plt)
def test_passthrough_filter(Simulator, plt, seed, allclose): m = nengo.Network(seed=seed) with m: omega = 2 * np.pi * 5 u = nengo.Node(output=lambda t: np.sin(omega * t)) passthrough = nengo.Node(size_in=1) v = nengo.Node(output=lambda t, x: x, size_in=1) synapse = nengo.Lowpass(0.3) nengo.Connection(u, passthrough, synapse=None) nengo.Connection(passthrough, v, synapse=synapse) up = nengo.Probe(u) vp = nengo.Probe(v) with Simulator(m) as sim: sim.run(1.0) t = sim.trange() x = sim.data[up] y = synapse.filt(x, dt=sim.dt, y0=0) z = sim.data[vp] plt.plot(t, x) plt.plot(t, y) plt.plot(t, z) assert allclose(y[:-1], z[1:], atol=1e-7, rtol=1e-4)
def test_function_output_size(Simulator, plt, seed, allclose): """Try a function that outputs both 0-d and 1-d arrays""" def bad_function(x): return x if x > 0 else 0 model = nengo.Network(seed=seed) with model: u = nengo.Node(output=lambda t: (t - 0.1) * 10) a = nengo.Ensemble(n_neurons=100, dimensions=1) b = nengo.Ensemble(n_neurons=100, dimensions=1) nengo.Connection(u, a, synapse=None) nengo.Connection(a, b, synapse=None, function=bad_function) up = nengo.Probe(u) bp = nengo.Probe(b, synapse=0.03) with Simulator(model) as sim: sim.run(0.2) t = sim.trange() x = nengo.Lowpass(0.03).filt(sim.data[up].clip(0, np.inf), dt=sim.dt) y = sim.data[bp] plt.plot(t, x, "k") plt.plot(t, y) assert allclose(x, y, atol=0.1)
def test_combined_delay(Simulator, allclose): # ensure that two sequential filters has the same output # as combining their individual discrete transfer functions nt = 50 tau = 0.005 dt = 0.001 sys1 = nengo.Lowpass(tau) (num,), den, _ = cont2discrete((sys1.num, sys1.den), dt=dt) sys2 = nengo.LinearFilter(np.poly1d(num) ** 2, np.poly1d(den) ** 2, analog=False) with nengo.Network() as model: u = nengo.Node(1) x = nengo.Node(size_in=1) nengo.Connection(u, x, synapse=sys1) p1 = nengo.Probe(x, synapse=sys1) p2 = nengo.Probe(u, synapse=sys2) with Simulator(model, dt=dt) as sim: sim.run_steps(nt) assert allclose(sim.data[p1], sim.data[p2]) # Both have two time-step delays: # for sys1, this comes from two levels of filtering # for sys2, this comes from one level of filtering + delay in sys2 assert allclose(sim.data[p1][:2], 0) assert not allclose(sim.data[p1][2], 0, record_rmse=False)
def test_from_parameters_force_width(self, width, latching, tc): # Create the mock signal and connection signal = SignalParameters(latching=latching) rps = ReceptionParameters(nengo.Lowpass(tc), width, None) # Create the filter lpf = LowpassFilter.from_parameters(signal, rps, width=2) assert lpf == LowpassFilter(2, latching, tc)
def test_rls_repr(): assert repr(RLS()) == "RLS(learning_rate=1.0, pre_synapse=Lowpass(0.005))" assert (repr(RLS(learning_rate=1e-5)) == "RLS(learning_rate=1e-05, pre_synapse=Lowpass(0.005))") assert (repr( RLS(pre_synapse=None)) == "RLS(learning_rate=1.0, pre_synapse=None)") assert (repr(RLS(learning_rate=1e-2, pre_synapse=nengo.Lowpass(1e-4))) == "RLS(learning_rate=0.01, pre_synapse=Lowpass(0.0001))")
def test_neuron_probes(precompute, probe_target, Simulator, seed, plt, allclose): simtime = 0.3 with nengo.Network(seed=seed) as model: stim = nengo.Node(lambda t: [np.sin(t * 2 * np.pi / simtime)]) a = nengo.Ensemble( 1, 1, neuron_type=nengo.LIF(min_voltage=-1), encoders=nengo.dists.Choice([[1]]), max_rates=nengo.dists.Choice([100]), intercepts=nengo.dists.Choice([0.0]), ) nengo.Connection(stim, a, synapse=None) p_stim = nengo.Probe(stim, synapse=0.005) p_neurons = nengo.Probe(a.neurons, probe_target) probe_synapse = nengo.Alpha(0.01) p_stim_f = nengo.Probe(stim, synapse=probe_synapse.combine( nengo.Lowpass(0.005))) p_neurons_f = nengo.Probe(a.neurons, probe_target, synapse=probe_synapse) with Simulator(model, precompute=precompute) as sim: sim.run(simtime) scale = float(sim.data[p_neurons].max()) t = sim.trange() x = sim.data[p_stim] xf = sim.data[p_stim_f] y = sim.data[p_neurons] / scale yf = sim.data[p_neurons_f] / scale plt.plot(t, x, label="stim") plt.plot(t, xf, label="stim filt") plt.plot(t, y, label="loihi") plt.plot(t, yf, label="loihi filt") plt.legend() if probe_target == "input": # shape of current input should roughly match stimulus assert allclose(y, x, atol=0.4, rtol=0) # noisy, so rough match assert allclose(yf, xf, atol=0.05, rtol=0) # tight match elif probe_target == "voltage": # check for voltage fluctuations (spiking) when stimulus is positive, # and negative voltage when stimulus is most negative spos = (t > 0.1 * simtime) & (t < 0.4 * simtime) assert allclose(yf[spos], 0.5, atol=0.1, rtol=0.1) assert y[spos].std() > 0.25 sneg = (t > 0.7 * simtime) & (t < 0.9 * simtime) assert np.all(y[sneg] < 0)
def test_combine_linear_and_linear_filter(self): # Create the ingoing reception parameters reception_params_a = model.ReceptionParameters(nengo.Lowpass(0.05), 1) # Create the outgoing reception parameters reception_params_b = model.ReceptionParameters(nengo.Lowpass(0.01), 5) # Combine the parameter each way round for a, b in ((reception_params_a, reception_params_b), (reception_params_a, reception_params_b)): new_rps = model_utils._combine_reception_params(a, b) # Check filter type synapse = new_rps.filter assert synapse.num == [1] assert np.all(synapse.den == [0.05 * 0.01, 0.05 + 0.01, 1]) # Check width is the width of the receiving item assert new_rps.width == b.width
def test_dt(dt, pre_on_chip, Simulator, seed, plt, allclose): function = lambda x: -x simtime = 0.2 probe_synapse = nengo.Alpha(0.01) conn_synapse = nengo.Lowpass(0.005) stim_synapse = probe_synapse # stim synapse accounts for delays in connections/probes, so we can compare if pre_on_chip: stim_synapse = stim_synapse.combine(conn_synapse) ens_params = dict( intercepts=nengo.dists.Uniform(-0.9, 0.9), max_rates=nengo.dists.Uniform(100, 120), ) with nengo.Network(seed=seed) as model: nengo_loihi.add_params(model) stim = nengo.Node(lambda t: -(np.sin(2 * np.pi * t / simtime))) stim_p = nengo.Probe(stim, synapse=stim_synapse) pre = nengo.Ensemble(100, 1, **ens_params) model.config[pre].on_chip = pre_on_chip pre_p = nengo.Probe(pre, synapse=probe_synapse) post = nengo.Ensemble(101, 1, **ens_params) post_p = nengo.Probe(post, synapse=probe_synapse) nengo.Connection(stim, pre, synapse=None) nengo.Connection( pre, post, function=function, synapse=conn_synapse, solver=nengo.solvers.LstsqL2(weights=True), ) with Simulator(model, dt=dt) as sim: assert sim.model.decode_tau == conn_synapse.tau sim.run(simtime) x = sim.data[stim_p] y = function(x) if pre_on_chip: y = conn_synapse.filt(y, dt=dt) else: y = conn_synapse.combine(conn_synapse).filt(y, dt=dt) plt.plot(sim.trange(), x, "k--") plt.plot(sim.trange(), y, "k--") plt.plot(sim.trange(), sim.data[pre_p]) plt.plot(sim.trange(), sim.data[post_p]) assert allclose(sim.data[pre_p], x, rtol=0.1, atol=0.1) assert allclose(sim.data[post_p], y, rtol=0.1, atol=0.1)
def _test_temporal_solver(plt, Simulator, seed, neuron_type, tau, f, solver): dt = 0.002 # we are cheating a bit here because we'll use the same training data as # test data. this makes the unit testing a bit simpler since it's more # obvious what will happen when comparing temporal to default t = np.arange(0, 0.2, dt) stim = np.sin(2 * np.pi * 10 * t) function = (f(stim) if tau is None else nengo.Lowpass(tau).filt(f(stim), dt=dt)) with Network(seed=seed) as model: u = nengo.Node(output=nengo.processes.PresentInput(stim, dt)) x = nengo.Ensemble(100, 1, neuron_type=neuron_type) output_ideal = nengo.Node(size_in=1) post = dict(n_neurons=500, dimensions=1, neuron_type=nengo.LIFRate(), seed=seed + 1) output_temporal = nengo.Ensemble(**post) output_default = nengo.Ensemble(**post) nengo.Connection(u, output_ideal, synapse=tau, function=f) nengo.Connection(u, x, synapse=None) nengo.Connection(x, output_temporal, synapse=tau, eval_points=stim[:, None], function=function[:, None], solver=Temporal(synapse=tau, solver=solver)) nengo.Connection(x, output_default, synapse=tau, eval_points=stim[:, None], function=f, solver=solver) p_ideal = nengo.Probe(output_ideal, synapse=None) p_temporal = nengo.Probe(output_temporal, synapse=None) p_default = nengo.Probe(output_default, synapse=None) with Simulator(model, dt) as sim: sim.run(t[-1]) plt.plot(sim.trange(), sim.data[p_ideal] - sim.data[p_default], label="Default") plt.plot(sim.trange(), sim.data[p_ideal] - sim.data[p_temporal], label="Temporal") plt.legend() return (nrmse(sim.data[p_default], target=sim.data[p_ideal]) / nrmse(sim.data[p_temporal], target=sim.data[p_ideal]))
def test_neuron_probe_with_synapse(Simulator, seed, allclose): synapse = nengo.Lowpass(0.01) with nengo.Network(seed=seed) as net: ens = nengo.Ensemble(10, 1) p_nosynapse = nengo.Probe(ens.neurons, synapse=None) p_synapse = nengo.Probe(ens.neurons, synapse=synapse) with Simulator(net) as sim: sim.run(0.1) assert allclose(sim.data[p_synapse], synapse.filt(sim.data[p_nosynapse]))
def test_cchannelchain(Simulator, plt, rng, seed, outfile): dims = 2 layers = 5 n_neurons = 100 synapse = nengo.Lowpass(0.01) with nengo.Network(seed=seed) as model: value = nengo.dists.UniformHypersphere().sample(dims, 1, rng=rng)[:, 0] stim = nengo.Node(value) ens = [ nengo.Ensemble(n_neurons, dimensions=dims) for _ in range(layers) ] nengo.Connection(stim, ens[0]) for i in range(layers - 1): nengo.Connection(ens[i], ens[i + 1], synapse=synapse) p_input = nengo.Probe(stim) p_outputs = [ nengo.Probe(ens[i], synapse=synapse) for i in range(layers) ] sim = Simulator(model) sim.run(0.5) if type(plt).__name__ != 'Mock': figsize = (onecolumn, 4.0) if horizontal else (onecolumn * 2, 4.0) setup(figsize=figsize) colors = sns.cubehelix_palette(5) lines = [] for i, p_output in enumerate(p_outputs): l = plt.plot(sim.trange(), sim.data[p_output], c=colors[i % len(colors)]) lines.append(l[0]) plt.legend(lines, ["Ensemble %d" % i for i in range(1, 6)], loc='best') plt.plot(sim.trange(), sim.data[p_input], c='k', lw=1) plt.xlim(right=0.12) plt.yticks((-0.5, 0, 0.5)) plt.xticks((0, 0.05, 0.1)) plt.ylabel('Decoded output') plt.xlabel('Time (s)') sns.despine() plt.saveas = 'results-1.svg' outfile.write('"n_neurons": %d,\n' % sum(e.n_neurons for e in model.all_ensembles)) outfile.write('"simtime": 0.5,\n') outfile.write('"rmse": %f,\n' % (rmse(sim.data[p_outputs[-1]][sim.trange() > 0.4], value))) if hasattr(sim, 'close'): sim.close()
def test_synapse(): inp = tf.keras.Input(shape=(1, )) dense0 = tf.keras.layers.Dense(units=10, activation=tf.nn.relu)(inp) dense1 = tf.keras.layers.Dense(units=10, activation=None)(dense0) model = tf.keras.Model(inp, [dense0, dense1]) conv = converter.Converter(model, synapse=0.1) for conn in conv.net.all_connections: if conn.pre is conv.layers[dense0]: # synapse set on outputs from neurons assert conn.synapse == nengo.Lowpass(0.1) else: # synapse not set on other connections assert conn.synapse is None # synapse set on neuron probe assert conv.outputs[dense0].synapse == nengo.Lowpass(0.1) # not set on non-neuron probe assert conv.outputs[dense1].synapse is None
def test_combine_unknown_filter(self): # Create the ingoing reception parameters reception_params_a = model.ReceptionParameters(nengo.Lowpass(0.05), 1) # Create the outgoing reception parameters reception_params_b = model.ReceptionParameters(mock.Mock(), 1) # Combine the parameter each way round for a, b in ((reception_params_a, reception_params_b), (reception_params_a, reception_params_b)): with pytest.raises(NotImplementedError): new_rps = model_utils._combine_reception_params(a, b)
def generate(net=None, n_neurons=200, alpha=1000.0, beta=1000.0 / 4.0, dt=0.001, analog=False): tau = 0.1 # synaptic time constant # the A matrix for our point attractor A = np.array([[0.0, 1.0], [-alpha * beta, -alpha]]) # the B matrix for our point attractor B = np.array([[0.0, 0.0], [alpha * beta, 1.0]]) # discretize Ad = expm(A * dt) Bd = np.dot(np.linalg.inv(A), np.dot((Ad - np.eye(2)), B)) # account for discrete lowpass filter a = np.exp(-dt / tau) if analog: A = tau * A + np.eye(2) B = tau * B else: A = 1.0 / (1.0 - a) * (Ad - a * np.eye(2)) B = 1.0 / (1.0 - a) * Bd if net is None: net = nengo.Network(label='Point Attractor') config = nengo.Config(nengo.Connection, nengo.Ensemble) config[nengo.Connection].synapse = nengo.Lowpass(tau) # config[nengo.Ensemble].neuron_type = nengo.Direct() with config, net: net.ydy = nengo.Ensemble( n_neurons=n_neurons, dimensions=2, # set it up so neurons are tuned to one dimensions only encoders=nengo.dists.Choice([[1, 0], [-1, 0], [0, 1], [0, -1]])) # set up Ax part of point attractor nengo.Connection(net.ydy, net.ydy, transform=A) # hook up input net.input = nengo.Node(size_in=2) # set up Bu part of point attractor nengo.Connection(net.input, net.ydy, transform=B) # hook up output net.output = nengo.Node(size_in=1) # add in forcing function nengo.Connection(net.ydy[0], net.output, synapse=None) return net
def test_pes_error_clip(plt, seed, Simulator): dims = 2 n_per_dim = 120 tau = 0.01 error_scale = 5.0 # scale up error signal so it clips simtime = 0.3 model, probes = pes_network( n_per_dim, dims, seed, learn_synapse=tau, learning_rule_type=nengo.PES(learning_rate=1e-2 / error_scale), input_scale=np.array([1.0, -1.0]), error_scale=error_scale, period=simtime, ) with pytest.warns(UserWarning, match=r".*PES error.*pes_error_scale.*"): with Simulator(model, hardware_options={"allocator": RoundRobin()}) as loihi_sim: loihi_sim.run(simtime) t = loihi_sim.trange() post_tmask = t > simtime - 1.0 dec_tau = loihi_sim.model.decode_tau y = loihi_sim.data[probes["stim"]] y_dpre = nengo.Lowpass(dec_tau).filt(y) y_dpost = nengo.Lowpass(tau).combine(nengo.Lowpass(dec_tau)).filt(y_dpre) y_loihi = loihi_sim.data[probes["post"]] plt.plot(t, y_dpost, "k", label="target") plt.plot(t, y_loihi, "g", label="loihi") # --- assert that we've learned something, but not everything error = rms(y_loihi[post_tmask] - y_dpost[post_tmask]) / rms( y_dpost[post_tmask]) assert error < 0.5 assert error > 0.05
def test_alif(Simulator, plt): """Test ALIF and ALIFRate by comparing them to each other""" n = 100 max_rates = 50 * np.ones(n) intercepts = np.linspace(-0.99, 0.99, n) encoders = np.ones((n, 1)) nparams = dict(tau_n=1, inc_n=10e-3) eparams = dict(n_neurons=n, max_rates=max_rates, intercepts=intercepts, encoders=encoders) model = nengo.Network() with model: u = nengo.Node(output=0.5) a = nengo.Ensemble(neuron_type=AdaptiveLIFRate(**nparams), dimensions=1, **eparams) b = nengo.Ensemble(neuron_type=AdaptiveLIF(**nparams), dimensions=1, **eparams) nengo.Connection(u, a, synapse=0) nengo.Connection(u, b, synapse=0) ap = nengo.Probe(a.neurons) bp = nengo.Probe(b.neurons) dt = 1e-3 with Simulator(model, dt=dt) as sim: sim.run(2.) t = sim.trange() a_rates = sim.data[ap] spikes = sim.data[bp] b_rates = nengo.Lowpass(0.04).filtfilt(spikes) tmask = (t > 0.1) & (t < 1.7) rel_rmse = rms(b_rates[tmask] - a_rates[tmask]) / rms(a_rates[tmask]) ax = plt.subplot(311) implot(plt, t, intercepts[::-1], a_rates.T, ax=ax) ax.set_ylabel('input') ax = plt.subplot(312) implot(plt, t, intercepts[::-1], b_rates.T, ax=ax) ax.set_ylabel('input') ax = plt.subplot(313) implot(plt, t, intercepts[::-1], (b_rates - a_rates)[tmask].T, ax=ax) ax.set_xlabel('time [s]') ax.set_ylabel('input') assert rel_rmse < 0.07
def evaluate(self, p, sim, plt): sim.run(p.T) self.record_speed(p.T) ideal = np.array(sim.data[self.probe_ideal]) for i in range(3): ideal = nengo.Lowpass(p.pstc).filt(ideal, dt=p.dt, y0=0) if plt is not None: plt.plot(sim.trange(), sim.data[self.probe]) plt.plot(sim.trange(), ideal) rmse = np.sqrt(np.mean((sim.data[self.probe] - ideal)**2)) return dict(rmse=rmse)
def merge_synapses(self, syn1, syn2): """Return an equivalent synapse for the two provided synapses.""" if syn1 is None: return syn2 elif syn2 is None: return syn1 else: assert isinstance(syn1, nengo.Lowpass) and isinstance( syn2, nengo.Lowpass) warnings.warn( "Combining two Lowpass synapses, this may change the " "behaviour of the network (set `remove_passthrough=False` " "to avoid this).") return nengo.Lowpass(syn1.tau + syn2.tau)