On Github tbekolay / fnme2015
Hello! I'm Trevor, as you all know by now, and today I'm going to go a bit more in-depth into the underlying Nengo library – not the GUI. Specifically, I'm going to talk Nengo's test suite and how we might use that test suite to do benchmarking of neural software and hardware, especially for neuromorphic hardware like SpiNNaker.
In order to talk about Nengo's test suite, I first need to talk a little bit about the architecture of Nengo.
with nengo.Network() as model: ... sim = nengo.Simulator(model) sim.run(2.0) # Run for 2 seconds sim.run(1.0) # Run for another second sim.trange() # [0.001, 0.002, 0.003, ...] sim.data[probe] # [[0.0, 0.0], [0.02, -0.02], ...]
import nengo def test_ensemble(): with nengo.Network() as model: ens = nengo.Ensemble(40, dimensions=1) assert model.ensembles[0] is ens
. 1 passed in 0.02 seconds
sim.run(1.0) decoded_value = sim.data[my_probe] assert decoded_value == 1.0
# Fuzzy testing assert np.allclose( decoded_value[sim.trange() > 0.8], 1.0, atol=0.1)
sim1 = nengo.Simulator(model) assert sim1.data[a.encoders] == [[-0.7311976, -0.3121639], [ 0.1879579, 0.1909519]] # passes
sim2 = nengo.Simulator(model) assert sim2.data[a.encoders] == [[-0.7311976, -0.3121639], [ 0.1879579, 0.1909519]] # fails
model.seed = 1 sim = nengo.Simulator(model) assert sim.data[a.encoders] == [[-0.7311976, -0.3121639], [ 0.1879579, 0.1909519]] # always passes
import nengo; import numpy as np def test_ensemble(): with nengo.Network(seed=1) as model: stim = nengo.Node([0.5]) ens = nengo.Ensemble(40, dimensions=1) nengo.Connection(stim, ens) probe = nengo.Probe(ens, synapse=0.05) sim = nengo.Simulator(model) sim.run(0.5) assert np.allclose( sim.data[probe][sim.trange() > 0.4], 0.5, atol=0.1)
. 1 passed in 0.19 seconds
import pytest @pytest.fixture def my_fixture(): return 'This is my fixture' def test_something(my_fixture): print(my_fixture) # prints 'This is my fixture'
import nengo; import numpy as np from nengo.tests.conftest import Simulator def test_ensemble(Simulator): with nengo.Network(seed=1) as model: stim = nengo.Node([0.5]) ens = nengo.Ensemble(40, dimensions=1) nengo.Connection(stim, ens) probe = nengo.Probe(ens, synapse=0.05) sim = Simulator(model) sim.run(0.5) assert np.allclose( sim.data[probe][sim.trange() > 0.4], 0.5, atol=0.1)
. 1 passed in 0.18 seconds
import nengo; import numpy as np from nengo.tests.conftest import Simulator from nengo.tests.conftest import pytest_generate_tests def test_ensemble(Simulator, nl): with nengo.Network(seed=1) as model: model.config[nengo.Ensemble].neuron_type = nl() stim = nengo.Node([0.5]) ens = nengo.Ensemble(40, dimensions=1) nengo.Connection(stim, ens) probe = nengo.Probe(ens, synapse=0.05) sim = Simulator(model) sim.run(0.5) assert np.allclose( sim.data[probe][sim.trange() > 0.4], 0.5, atol=0.1)
..... 5 passed in 0.71 seconds
import nengo; import numpy as np from nengo.tests.conftest import Simulator, seed from nengo.tests.conftest import pytest_generate_tests def test_ensemble(Simulator, nl, seed): with nengo.Network(seed=seed) as model: model.config[nengo.Ensemble].neuron_type = nl() stim = nengo.Node([0.5]) ens = nengo.Ensemble(40, dimensions=1) nengo.Connection(stim, ens) probe = nengo.Probe(ens, synapse=0.05) sim = Simulator(model) sim.run(0.5) assert np.allclose( sim.data[probe][sim.trange() > 0.4], 0.5, atol=0.1)
..... 5 passed in 0.72 seconds
Benchmarks are commonly
But benchmarks can drive progress.
Let's use Nengo's testing infrastructure to benchmark backends
import nengo; import numpy as np from nengo.tests.conftest import Simulator, plt, seed from nengo.tests.conftest import pytest_generate_tests def test_ensemble(Simulator, nl, seed, plt): with nengo.Network(seed=seed) as model: model.config[nengo.Ensemble].neuron_type = nl() stim = nengo.Node([0.5]) ens = nengo.Ensemble(40, dimensions=1) nengo.Connection(stim, ens) probe = nengo.Probe(ens, synapse=0.05) sim = Simulator(model) sim.run(0.5) plt.plot(sim.trange(), sim.data[probe]) assert np.allclose( sim.data[probe][sim.trange() > 0.4], 0.5, atol=0.1)
..... 5 passed in 1.89 seconds
nengo.simulator.plots ├── Direct │ └── test_ensemble.pdf ├── LIF │ └── test_ensemble.pdf ├── LIFRate │ └── test_ensemble.pdf ├── RectifiedLinear │ └── test_ensemble.pdf └── Sigmoid └── test_ensemble.pdf 5 directories, 5 files
import nengo; import numpy as np from nengo.tests.conftest import (Simulator, analytics, plt, seed, pytest_generate_tests) def test_ensemble(Simulator, nl, seed, analytics, plt): with nengo.Network(seed=seed) as model: model.config[nengo.Ensemble].neuron_type = nl() stim = nengo.Node([0.5]) ens = nengo.Ensemble(40, dimensions=1) nengo.Connection(stim, ens) probe = nengo.Probe(ens, synapse=0.05) sim = Simulator(model) sim.run(0.5) plt.plot(sim.trange(), sim.data[probe]) analytics.add_data('out', sim.data[probe], "decoded out") assert np.allclose( sim.data[probe][sim.trange() > 0.4], 0.5, atol=0.1)
..... 5 passed in 1.80 seconds
nengo.simulator.analytics ├── Direct │ └── test_ensemble.npz ├── LIF │ └── test_ensemble.npz ├── LIFRate │ └── test_ensemble.npz ├── RectifiedLinear │ └── test_ensemble.npz └── Sigmoid └── test_ensemble.npz 5 directories, 5 files
import nengo; import numpy as np from nengo.tests.conftest import (Simulator, analytics, plt, logger, seed, pytest_generate_tests) def test_ensemble(Simulator, nl, seed, analytics, logger, plt): with nengo.Network(seed=seed) as model: model.config[nengo.Ensemble].neuron_type = nl() stim = nengo.Node([0.5]) ens = nengo.Ensemble(40, dimensions=1) nengo.Connection(stim, ens) probe = nengo.Probe(ens, synapse=0.05) sim = Simulator(model) sim.run(0.5) plt.plot(sim.trange(), sim.data[probe]) analytics.add_data('out', sim.data[probe], "decoded out") logger.info('RMSE=%f', nengo.utils.numpy.rmse( sim.data[probe][sim.trange() > 0.4], 0.5)) assert np.allclose( sim.data[probe][sim.trange() > 0.4], 0.5, atol=0.1)
..... 5 passed in 1.86 seconds
nengo.simulator.logs ├── Direct │ └── test_ensemble.txt ├── LIF │ └── test_ensemble.txt ├── LIFRate │ └── test_ensemble.txt ├── RectifiedLinear │ └── test_ensemble.txt └── Sigmoid └── test_ensemble.txt 5 directories, 5 files
[INFO] === Test run at 2015-06-15 13:44:12 === [INFO] RMSE=0.000094
[INFO] === Test run at 2015-06-15 13:44:12 === [INFO] Cache hit [557ba1f3a5c815f201a71c859e8b41376f2a9885]: Loaded stored decoders. [INFO] RMSE=0.004409