def mnist(use_tensor_layer=True): """ A network designed to stress-test tensor layers (based on mnist net). Parameters ---------- use_tensor_layer : bool If True, use individual tensor_layers to build the network, as opposed to a single TensorNode containing all layers. Returns ------- :class:`nengo:nengo.Network` benchmark network """ with nengo.Network() as net: nengo_dl.configure_settings(trainable=False) # create node to feed in images net.inp = nengo.Node(np.ones(28 * 28)) if use_tensor_layer: nengo_nl = nengo.RectifiedLinear() ensemble_params = dict(max_rates=nengo.dists.Choice([100]), intercepts=nengo.dists.Choice([0])) amplitude = 1 synapse = None x = nengo_dl.tensor_layer(net.inp, tf.layers.conv2d, shape_in=(28, 28, 1), filters=32, kernel_size=3) x = nengo_dl.tensor_layer(x, nengo_nl, **ensemble_params) x = nengo_dl.tensor_layer(x, tf.layers.conv2d, shape_in=(26, 26, 32), transform=amplitude, filters=32, kernel_size=3) x = nengo_dl.tensor_layer(x, nengo_nl, **ensemble_params) x = nengo_dl.tensor_layer(x, tf.layers.average_pooling2d, shape_in=(24, 24, 32), synapse=synapse, transform=amplitude, pool_size=2, strides=2) x = nengo_dl.tensor_layer(x, tf.layers.dense, units=128) x = nengo_dl.tensor_layer(x, nengo_nl, **ensemble_params) x = nengo_dl.tensor_layer(x, tf.layers.dropout, rate=0.4, transform=amplitude) x = nengo_dl.tensor_layer(x, tf.layers.dense, units=10) else: nl = tf.nn.relu # def softlif_layer(x, sigma=1, tau_ref=0.002, tau_rc=0.02, # amplitude=1): # # x -= 1 # z = tf.nn.softplus(x / sigma) * sigma # z += 1e-10 # rates = amplitude / (tau_ref + tau_rc * tf.log1p(1 / z)) # return rates @nengo_dl.reshaped((28, 28, 1)) def mnist_node(_, x): x = tf.layers.conv2d(x, filters=32, kernel_size=3, activation=nl) x = tf.layers.conv2d(x, filters=32, kernel_size=3, activation=nl) x = tf.layers.average_pooling2d(x, pool_size=2, strides=2) x = tf.contrib.layers.flatten(x) x = tf.layers.dense(x, 128, activation=nl) x = tf.layers.dropout(x, rate=0.4) x = tf.layers.dense(x, 10) return x node = nengo_dl.TensorNode(mnist_node, size_in=28 * 28, size_out=10) x = node nengo.Connection(net.inp, node, synapse=None) net.p = nengo.Probe(x) return net
# In[ ]: # Connect the input with integrator: nengo.Connection(input, integrator.input, synapse=tau) # ## Step 4: Probe outputs # # Anything that is probed will collect the data it produces over time, allowing us to analyze and visualize it later. # In[ ]: with integrator: input_probe = nengo.Probe(input) integrator_probe = nengo.Probe(integrator.ensemble, synapse=0.01) # 10ms filter # ## Step 5: Run the model # In[ ]: # Create our simulator with nengo.Simulator(integrator) as sim: # Run it for 6 seconds sim.run(6) # ## Step 6: Plot the results
def test_slicing(Simulator, nl, plt, seed): N = 300 x = np.array([-1, -0.25, 1]) s1a = slice(1, None, -1) s1b = [2, 0] T1 = [[-1, 0.5], [2, 0.25]] y1 = np.zeros(3) y1[s1b] = np.dot(T1, x[s1a]) s2a = [0, 2] s2b = slice(0, 2) T2 = [[-0.5, 0.25], [0.5, 0.75]] y2 = np.zeros(3) y2[s2b] = np.dot(T2, x[s2a]) s3a = [2, 0] s3b = np.asarray([0, 2]) # test slicing with numpy array T3 = [0.5, 0.75] y3 = np.zeros(3) y3[s3b] = np.dot(np.diag(T3), x[s3a]) sas = [s1a, s2a, s3a] sbs = [s1b, s2b, s3b] Ts = [T1, T2, T3] ys = [y1, y2, y3] weight_solver = nengo.solvers.LstsqL2(weights=True) with nengo.Network(seed=seed) as m: m.config[nengo.Ensemble].neuron_type = nl() u = nengo.Node(output=x) a = nengo.Ensemble(N, dimensions=3, radius=1.7) nengo.Connection(u, a) probes = [] weight_probes = [] for sa, sb, T in zip(sas, sbs, Ts): b = nengo.Ensemble(N, dimensions=3, radius=1.7) nengo.Connection(a[sa], b[sb], transform=T) probes.append(nengo.Probe(b, synapse=0.03)) # also test on weight solver b = nengo.Ensemble(N, dimensions=3, radius=1.7) nengo.Connection(a[sa], b[sb], transform=T, solver=weight_solver) weight_probes.append(nengo.Probe(b, synapse=0.03)) with Simulator(m) as sim: sim.run(0.2) t = sim.trange() for i, [y, p] in enumerate(zip(ys, probes)): plt.subplot(len(ys), 1, i + 1) plt.plot(t, np.tile(y, (len(t), 1)), '--') plt.plot(t, sim.data[p]) atol = 0.01 if nl is nengo.Direct else 0.1 for i, [y, p, wp] in enumerate(zip(ys, probes, weight_probes)): assert np.allclose(y, sim.data[p][-20:], atol=atol), "Failed %d" % i assert np.allclose(y, sim.data[wp][-20:], atol=atol), "Weights %d" % i
def test_conv_preslice(on_chip, Simulator, plt): conv2d = pytest.importorskip("nengo._vendor.npconv2d.conv2d") kernel = np.array([[-1, 2, -1], [-1, 2, -1], [-1, 2, -1]], dtype=float) kernel /= kernel.max() image = np.array( [ [1, 2, 1, 2, 0], [2, 3, 2, 1, 1], [1, 2, 1, 2, 3], [2, 3, 2, 1, 1], [1, 2, 1, 2, 0], ], dtype=float, ) image /= image.max() image2 = np.column_stack([c * x for c in image.T for x in (1, -1)]) input_gain = 149.0 neuron_type = nengo.SpikingRectifiedLinear() loihi_neuron = LoihiSpikingRectifiedLinear() layer0_neuron = loihi_neuron if on_chip else neuron_type y_ref = layer0_neuron.rates(image.ravel(), input_gain, 0) y_ref = conv2d.conv2d(y_ref.reshape((1, 5, 5, 1)), kernel.reshape((3, 3, 1, 1)), pad="VALID") y_ref = loihi_neuron.rates(y_ref.ravel(), 1.0, 0.0).reshape((3, 3)) with nengo.Network() as net: nengo_loihi.add_params(net) u = nengo.Node(image2.ravel()) a = nengo.Ensemble( 50, 1, neuron_type=neuron_type, gain=nengo.dists.Choice([input_gain]), bias=nengo.dists.Choice([0]), ) net.config[a].on_chip = on_chip transform = nengo_transforms.Convolution(n_filters=1, input_shape=(5, 5, 1), init=kernel.reshape( (3, 3, 1, 1))) b = nengo.Ensemble( transform.output_shape.size, 1, neuron_type=neuron_type, gain=nengo.dists.Choice([1]), bias=nengo.dists.Choice([0]), ) nengo.Connection(u, a.neurons, synapse=None) nengo.Connection(a.neurons[::2], b.neurons, transform=transform) bp = nengo.Probe(b.neurons, synapse=nengo.Alpha(0.02)) with Simulator(net) as sim: assert sim.precompute is True sim.run(0.3) y_ref = y_ref / input_gain y = sim.data[bp][-1].reshape((3, -1)) / input_gain plt.subplot(121) plt.imshow(y_ref) plt.colorbar() plt.subplot(122) plt.imshow(y) plt.colorbar() assert np.allclose(y, y_ref, atol=0.02, rtol=0.1)
neuron_type = nengo.LIF(amplitude=0.01) # this is an optimization to improve the training speed, # since we won't require stateful behaviour in this example nengo_dl.configure_settings(stateful=False) # the input node that will be used to feed in (context, location, goal) inp = nengo.Node(np.zeros((36*4 + args.maze_id_dim,))) x = nengo_dl.Layer(tf.keras.layers.Dense(units=args.hidden_size))(inp) x = nengo_dl.Layer(neuron_type)(x) out = nengo_dl.Layer(tf.keras.layers.Dense(units=args.dim))(x) out_p = nengo.Probe(out, label="out_p") out_p_filt = nengo.Probe(out, synapse=0.1, label="out_p_filt") # minibatch_size = 200 minibatch_size = 256 sim = nengo_dl.Simulator(net, minibatch_size=minibatch_size) print("\nSimulator Built\n") # number of timesteps to repeat the input/output for n_steps = 30 def mse_loss(y_true, y_pred):
def test_conv_connection(channels, channels_last, Simulator, seed, rng, plt, allclose): # load data with open(os.path.join(test_dir, "mnist10.pkl"), "rb") as f: test10 = pickle.load(f) test_x = test10[0][0].reshape((28, 28)) test_x = 1.999 * test_x - 0.999 # range (-1, 1) input_shape = make_channel_shape(test_x.shape, channels, channels_last) filters = Gabor(freq=Uniform(0.5, 1)).generate(8, (7, 7), rng=rng) filters = filters[None, :, :, :] # single channel filters = np.transpose(filters, (2, 3, 0, 1)) strides = (2, 2) tau_rc = 0.02 tau_ref = 0.002 tau_s = 0.005 neuron_type = LoihiLIF(tau_rc=tau_rc, tau_ref=tau_ref) pres_time = 0.1 with nengo.Network(seed=seed) as model: nengo_loihi.add_params(model) u = nengo.Node(test_x.ravel(), label="u") a = nengo.Ensemble( input_shape.size, 1, neuron_type=LoihiSpikingRectifiedLinear(), max_rates=nengo.dists.Choice([40 / channels]), intercepts=nengo.dists.Choice([0]), label="a", ) model.config[a].on_chip = False if channels == 1: nengo.Connection(u, a.neurons, transform=1, synapse=None) elif channels == 2: # encode image into spikes using two channels (on/off) if input_shape.channels_last: nengo.Connection(u, a.neurons[0::2], transform=1, synapse=None) nengo.Connection(u, a.neurons[1::2], transform=-1, synapse=None) else: k = input_shape.spatial_shape[0] * input_shape.spatial_shape[1] nengo.Connection(u, a.neurons[:k], transform=1, synapse=None) nengo.Connection(u, a.neurons[k:], transform=-1, synapse=None) filters = np.concatenate([filters, -filters], axis=2) else: raise ValueError("Test not configured for more than two channels") conv2d_transform = nengo_transforms.Convolution( 8, input_shape, strides=strides, kernel_size=(7, 7), channels_last=channels_last, init=filters, ) output_shape = conv2d_transform.output_shape gain, bias = neuron_type.gain_bias(max_rates=100, intercepts=0) gain = gain * 0.01 # account for `a` max_rates b = nengo.Ensemble( output_shape.size, 1, neuron_type=neuron_type, gain=nengo.dists.Choice([gain[0]]), bias=nengo.dists.Choice([bias[0]]), label="b", ) nengo.Connection(a.neurons, b.neurons, synapse=tau_s, transform=conv2d_transform) bp = nengo.Probe(b.neurons) with nengo.Simulator(model, optimize=False) as sim_nengo: sim_nengo.run(pres_time) ref_out = sim_nengo.data[bp].mean(axis=0).reshape(output_shape.shape) with Simulator(model, target="simreal") as sim_emu: sim_emu.run(pres_time) emu_out = sim_emu.data[bp].mean(axis=0).reshape(output_shape.shape) with Simulator(model, hardware_options={"snip_max_spikes_per_step": 800}) as sim_loihi: sim_loihi.run(pres_time) sim_out = sim_loihi.data[bp].mean(axis=0).reshape(output_shape.shape) if not output_shape.channels_last: ref_out = np.transpose(ref_out, (1, 2, 0)) emu_out = np.transpose(emu_out, (1, 2, 0)) sim_out = np.transpose(sim_out, (1, 2, 0)) out_max = max(ref_out.max(), emu_out.max(), sim_out.max()) # --- plot results rows = 2 cols = 3 ax = plt.subplot(rows, cols, 1) imshow(test_x, vmin=0, vmax=1, ax=ax) ax = plt.subplot(rows, cols, 2) tile(np.transpose(filters[0], (2, 0, 1)), cols=8, ax=ax) ax = plt.subplot(rows, cols, 3) plt.hist(ref_out.ravel(), bins=31) plt.hist(sim_out.ravel(), bins=31) ax = plt.subplot(rows, cols, 4) tile(np.transpose(ref_out, (2, 0, 1)), vmin=0, vmax=out_max, cols=8, ax=ax) ax = plt.subplot(rows, cols, 5) tile(np.transpose(emu_out, (2, 0, 1)), vmin=0, vmax=out_max, cols=8, ax=ax) ax = plt.subplot(rows, cols, 6) tile(np.transpose(sim_out, (2, 0, 1)), vmin=0, vmax=out_max, cols=8, ax=ax) assert allclose(emu_out, ref_out, atol=10, rtol=1e-3) assert allclose(sim_out, ref_out, atol=10, rtol=1e-3)
def test_conv_deepnet( channels_last, pop_type, precompute, Simulator, request, rng, seed, plt, allclose, ): """Run a convolutional network with two layers on the chip. Checks that network with block splitting on the target matches one without on the emulator. """ # TODO: This case fails in NxSDK 0.9.0 but will be fixed in the next version. # Remove this check once the next version is released. if pop_type == 32: pytest.skip("Pop32 multichip test requires latest NxSDK") def set_partition(partition): os.environ["PARTITION"] = partition request.addfinalizer(lambda: set_partition("")) # multichip pop_type = 16 works only on nahuku32 board currently if pop_type == 16: set_partition("nahuku32") def conv_layer(x, input_shape, array_init=None, label=None, conn_args=None, **conv_args): conn_args = {} if conn_args is None else conn_args if array_init is not None: assert all(a not in conv_args for a in ("init", "kernel_size", "n_filters")) assert array_init.ndim == 4 conv_args["init"] = array_init conv_args["kernel_size"] = array_init.shape[:2] assert array_init.shape[2] == input_shape.n_channels conv_args["n_filters"] = array_init.shape[3] conv = nengo.Convolution(input_shape=input_shape, **conv_args) # add an ensemble to implement the activation function layer = nengo.Ensemble(conv.output_shape.size, 1, label=label) # connect up the input object to the new layer conn = nengo.Connection(x, layer.neurons, transform=conv) return layer, conv, conn channels = 1 n_filters0 = 1 n_filters1 = 4 n_filters2 = 4 # load data with open(os.path.join(test_dir, "mnist10.pkl"), "rb") as f: test10 = pickle.load(f) test_x = test10[0][0].reshape(28, 28) # range (0, 1) input_shape = make_channel_shape(test_x.shape, channels, channels_last) filters0 = np.ones((1, 1, channels, n_filters0)) # use Gabor filters for first layer filters1 = Gabor(freq=Uniform(0.5, 1), sigma_x=Choice([0.9]), sigma_y=Choice([0.9])).generate(n_filters1, (7, 7), rng=rng) assert n_filters0 == 1 filters1 = filters1[None, :, :, :] # single channel filters1 = np.transpose(filters1, (2, 3, 0, 1)) # rows, cols, in_chan, out_chan # use random combinations of first-layer channels in 1x1 convolution filters2 = rng.uniform(-0.2, 1, size=(n_filters1, n_filters2)).clip(0, None) filters2 *= 2 / filters2.sum(axis=0, keepdims=True) # each filter sums to 2 filters2 = filters2[None, None, :, :] # rows, cols, in_chan, out_chan tau_s = 0.001 max_rate = 100 amp = 1 / max_rate f_split = 2 if pop_type == 32 else 4 # use Loihi neuron type so Nengo sim mimics Loihi neuron effects neuron_type = LoihiSpikingRectifiedLinear(amplitude=amp) pres_time = 0.2 with nengo.Network(seed=seed) as net: nengo_loihi.add_params(net) net.config[nengo.Ensemble].neuron_type = neuron_type net.config[nengo.Ensemble].max_rates = Choice([max_rate]) net.config[nengo.Ensemble].intercepts = Choice([0]) net.config[nengo.Connection].synapse = tau_s u = nengo.Node(test_x.ravel(), label="u") layer0, conv0, conn0 = conv_layer( u, input_shape=input_shape, array_init=filters0, strides=(1, 1), channels_last=channels_last, label="layer0", conn_args=dict(synapse=None), ) net.config[layer0].on_chip = False layer1, conv1, conn1 = conv_layer( layer0.neurons, input_shape=conv0.output_shape, array_init=filters1, strides=(2, 2), channels_last=channels_last, label="layer1", ) net.config[layer1].block_shape = nengo_loihi.BlockShape( make_shape((4, 4), f_split, channels_last), conv1) net.config[conn1].pop_type = pop_type layer2, conv2, conn2 = conv_layer( layer1.neurons, input_shape=conv1.output_shape, array_init=filters2, strides=(1, 1), channels_last=channels_last, label="layer2", ) net.config[layer2].block_shape = nengo_loihi.BlockShape( make_shape((4, 4), f_split, channels_last), conv2) net.config[conn2].pop_type = pop_type output_p = nengo.Probe(layer2.neurons) output_shape = conv2.output_shape with nengo.Simulator(net, optimize=False) as sim_nengo: sim_nengo.run(pres_time) ref_out = (sim_nengo.data[output_p] > 0).sum(axis=0).reshape( output_shape.shape) with Simulator(net, target="sim") as sim_emu: sim_emu.run(pres_time) emu_out = (sim_emu.data[output_p] > 0).sum(axis=0).reshape( output_shape.shape) # TODO: Remove the if condition when configurable timeout parameter # is available in nxsdk if (pop_type == 32 or os.popen("sinfo -h --partition=nahuku32").read().find("idle") > 0): with Simulator( net, precompute=precompute, hardware_options={ "allocator": RoundRobin(), "snip_max_spikes_per_step": 800, }, ) as sim_loihi: sim_loihi.run(pres_time) sim_out = ((sim_loihi.data[output_p] > 0).sum(axis=0).reshape( output_shape.shape)) elif nengo_loihi.version.dev is None: pytest.fail( "Pop16 multichip test failed since Nahuku32 is unavailable") else: pytest.skip( "Pop16 multichip test skipped since Nahuku32 is unavailable") out_max = ref_out.max() ref_out = ref_out / out_max emu_out = emu_out / out_max sim_out = sim_out / out_max if channels_last: # channels first, to display channels in separate plots ref_out = np.transpose(ref_out, (2, 0, 1)) emu_out = np.transpose(emu_out, (2, 0, 1)) sim_out = np.transpose(sim_out, (2, 0, 1)) # --- plot results rows = 2 cols = 3 ax = plt.subplot(rows, cols, 1) imshow(test_x, vmin=0, vmax=1, ax=ax) ax = plt.subplot(rows, cols, 2) tile(np.transpose(filters1, (2, 3, 0, 1))[0], rows=2, cols=2, grid=True, ax=ax) ax = plt.subplot(rows, cols, 3) plt.hist((ref_out.ravel(), emu_out.ravel(), sim_out.ravel()), bins=21) ax = plt.subplot(rows, cols, 4) tile(ref_out, rows=2, cols=2, grid=True, ax=ax) ax = plt.subplot(rows, cols, 5) tile(emu_out, rows=2, cols=2, grid=True, ax=ax) ax = plt.subplot(rows, cols, 6) tile(sim_out, rows=2, cols=2, grid=True, ax=ax) assert allclose(sim_out, ref_out, atol=0.15, rtol=1e-3) assert allclose(sim_out, emu_out, atol=1e-3, rtol=1e-3)
# build model model = nengo.Network(label="Many neurons.") with model: A = nengo.Ensemble( 100, dimensions=1) with model: sin = nengo.Node(lambda t: np.sin(8*t)) nengo.Connection(sin, A, synapse=0.01) with model: sin_probe = nengo.Probe(sin) A_probe = nengo.Probe(A, synapse=0.1) A_spikes = nengo.Probe(A.neurons) with nengo.Simulator(model) as sim: sim.run(10) plt.figure() plt.plot(sim.trange(), sim.data[A_probe], label="A output") plt.plot(sim.trange(), sim.data[sin_probe], "r", label="Input") plt.legend() plt.show() plt.figure()
# # Introduction # The Neural Engineering Framework (NEF) is the set of theoretical methods that are used in Nengo for constructing neural models. The NEF is based on <a href="http://www.amazon.com/gp/product/0262550601">Eliasmith & Anderson's (2003) book</a> from MIT Press. This notebook introduces the three main principles discussed in that book and implemented in Nengo. # # Principle 1: Representation # # ## Encoding # # Neural populations represent time-varying signals through their spiking responses. A signal is a vector of real numbers of arbitrary length. This example is a 1D signal going from -1 to 1 in 1 second. # In[ ]: model = nengo.Network(label="NEF summary") with model: input = nengo.Node(lambda t: t * 2 - 1) input_probe = nengo.Probe(input) # In[ ]: with nengo.Simulator(model) as sim: sim.run(1.0) plt.plot(sim.trange(), sim.data[input_probe], lw=2) plt.title("Input signal") plt.xlabel("Time (s)") plt.xlim(0, 1) hide_input() # These signals drive neural populations based on each neuron's *tuning curve* (which is similar to the I-F (current-frequency) curve, if you're familiar with that). # # The tuning curve describes how much a particular neuron will fire as a function of the input signal.
def split_passthrough(model, max_dim=16): replaced = {} inputs = {} outputs = {} parents = {} gather_info(model, inputs, outputs, parents) changed = True while changed: changed = False for node in model.all_nodes[:]: if node.output is None: if node.size_in > max_dim: changed = True nodes = [] slices = [] index = 0 while index < node.size_in: label = node.label if label is not None: label += ' (%d)' % len(nodes) size = min(node.size_in - index, max_dim) with parents[node]: new_node = nengo.Node(None, size_in=size, label=label) parents[new_node] = parents[node] inputs[new_node] = [] outputs[new_node] = [] slices.append(slice(index, index + size)) nodes.append(new_node) index += size for c in inputs.get(node, [])[:]: base_transform = c.transform if len(base_transform.shape) == 0: base_transform = np.eye( c.size_mid) * base_transform transform = np.zeros((node.size_in, c.size_in)) transform[c.post_slice] = base_transform for i, n in enumerate(nodes): t = transform[slices[i]] if np.count_nonzero(t) > 0: with parents[c]: new_c = nengo.Connection( c.pre, n, transform=t, function=c.function, synapse=c.synapse) inputs[n].append(new_c) outputs[c.pre_obj].append(new_c) parents[new_c] = parents[c] outputs[c.pre_obj].remove(c) inputs[node].remove(c) parents[c].connections.remove(c) for c in outputs.get(node, [])[:]: base_transform = c.transform if len(base_transform.shape) == 0: base_transform = np.eye( c.size_mid) * base_transform transform = np.zeros((c.size_out, node.size_out)) transform[:, c.pre_slice] = base_transform for i, n in enumerate(nodes): t = transform[:, slices[i]] if np.count_nonzero(t) > 0: with parents[c]: new_c = nengo.Connection(n, c.post, transform=t, synapse=c.synapse) outputs[n].append(new_c) inputs[c.post_obj].append(new_c) parents[new_c] = parents[c] inputs[c.post_obj].remove(c) outputs[node].remove(c) parents[c].connections.remove(c) parents[node].nodes.remove(node) replaced[node] = nodes for p in model.probes[:]: if p.target in replaced: model.probes.remove(p) probes = [] for n in replaced[p.target]: with model: probe = nengo.Probe(n, synapse=p.synapse) probes.append(probe) replaced[p] = probes return replaced
def model(self, p): model = nengo.Network() if p.direct: model.config[nengo.Ensemble].neuron_type = nengo.Direct() if p.task == 'compare': self.exp = NumberExperiment(p=p) elif p.task == 'fingers': self.exp = FingerTouchExperiment(p=p) with model: input0 = nengo.Node(self.exp.input0) input1 = nengo.Node(self.exp.input1) pointer_source = nengo.Node(self.exp.pointer_source) pointer_target = nengo.Node(self.exp.pointer_target) report_finger = nengo.Node(self.exp.report_finger) report_compare = nengo.Node(self.exp.report_compare) memory_clear = nengo.Node(self.exp.memory_clear) # create neural models for the two input areas # (fingers and magnitude) #area0 = nengo.Ensemble(p.N_input*p.pointer_count, p.pointer_count, # radius=np.sqrt(p.pointer_count)) area0 = nengo.networks.EnsembleArray(p.N_input, n_ensembles=p.pointer_count) area1 = nengo.Ensemble(p.N_input, 1) nengo.Connection(input0, area0.input) nengo.Connection(input1, area1) # define the connections to create the pointers def matrix(n, m, pre=None, post=None, value=1): m = [[0] * n for i in range(m)] if pre is None: pre = range(n) if post is None: post = range(m) for i in range(max(len(pre), len(post))): m[post[i % len(post)]][pre[i % len(pre)]] = value return m pointers = nengo.Network() with pointers: for i in range(p.pointer_count): nengo.Ensemble(p.N_pointer, dimensions=p.input_count * 2 + 1, neuron_type=nengo.LIF(), radius=np.sqrt(p.input_count * 2 + 1), label='%d' % i) for i in range(p.pointer_count): pointer = pointers.ensembles[i] nengo.Connection( pointer_source, pointer, transform=matrix( p.input_count, p.input_count * 2 + 1, post=[k * 2 for k in range(p.input_count)])) nengo.Connection(pointer_target, pointer, transform=matrix(p.pointer_count, p.input_count * 2 + 1, pre=[i], post=[p.input_count * 2])) nengo.Connection(area0.output, pointer, transform=matrix(p.pointer_count, p.input_count * 2 + 1, pre=[i], post=[1])) nengo.Connection(area1, pointer, transform=matrix(1, p.input_count * 2 + 1, pre=[0], post=[3])) # define the connections to extract the current value # from the pointers def ref_func(x): if x[-1] < 0.5: return 0 sum = 0 for i in range(p.input_count): if x[2 * i] > 0.5: sum += x[2 * i + 1] return sum basis = [] for i in range(p.pointer_count): b = [0] * p.pointer_count b[i] = 1 basis.append(b) b = [0] * p.pointer_count b[i] = -1 basis.append(b) #reference=nengo.Ensemble(p.N_reference,p.pointer_count, # radius=np.sqrt(p.pointer_count)*p.ref_radius, # neuron_type=nengo.LIF(), # encoders=nengo.dists.Choice(basis), # intercepts=nengo.dists.Uniform(0.1,0.9)) reference = nengo.networks.EnsembleArray( p.N_reference, n_ensembles=p.pointer_count, radius=p.ref_radius, neuron_type=nengo.LIF(), encoders=nengo.dists.Choice([[1]]), intercepts=nengo.dists.Uniform(0.1, 0.9)) for i in range(p.pointer_count): matrix = [p.crosstalk] * p.pointer_count matrix[i] = 1.0 - p.crosstalk for j in range(p.pointer_count): delta = np.abs(i - j) if delta > 1: matrix[j] = max( 0, p.crosstalk - p.crosstalk_decay * (delta - 1)) pointer = pointers.ensembles[i] nengo.Connection(pointer, reference.input, function=ref_func, transform=[[x] for x in matrix]) # add a memory to integrate the value referenced by the pointers memory = nengo.networks.EnsembleArray(p.N_memory, p.pointer_count, neuron_type=nengo.LIF(), radius=1) nengo.Connection(reference.output, memory.input, transform=p.memory_input_scale, synapse=p.memory_synapse) nengo.Connection(memory.output, memory.input, transform=1, synapse=p.memory_synapse) # create a system to report which fingers were pressed report = nengo.networks.EnsembleArray( p.N_report, p.pointer_count, encoders=nengo.dists.Choice([[1]]), intercepts=nengo.dists.Uniform(0.3, 0.9), neuron_type=nengo.LIF(), radius=0.3) nengo.Connection(memory.output, report.input, transform=1) m = [[-10] * p.pointer_count for i in range(p.pointer_count)] for i in range(p.pointer_count): m[i][i] = 0 nengo.Connection(report.output, report.input, transform=m, synapse=0.01) reported = nengo.networks.EnsembleArray( p.N_report, p.pointer_count, radius=1, encoders=nengo.dists.Choice([[1]]), neuron_type=nengo.LIF(), intercepts=nengo.dists.Uniform(0.05, 0.9)) nengo.Connection(report.output, reported.input, transform=1, synapse=0.2) nengo.Connection(reported.output, report.input, transform=-1) nengo.Connection(reported.output, reported.input, transform=1.2) # create a system to report whether the first # or second number is bigger compare = nengo.Ensemble(p.N_compare, 1, neuron_type=nengo.LIF()) nengo.Connection(memory.ensembles[0], compare, transform=p.compare_scale) nengo.Connection(memory.ensembles[1], compare, transform=-p.compare_scale) # create inhibitory gates to control the two reporting systems report_gate_f = nengo.Ensemble(50, 1, encoders=nengo.dists.Choice([[1]]), intercepts=nengo.dists.Uniform( 0.1, 0.9)) report_gate_c = nengo.Ensemble(50, 1, encoders=nengo.dists.Choice([[1]]), intercepts=nengo.dists.Uniform( 0.1, 0.9)) nengo.Connection(report_finger, report_gate_f, transform=-1) nengo.Connection(report_compare, report_gate_c, transform=-1) report_bias = nengo.Node([1]) nengo.Connection(report_bias, report_gate_f) nengo.Connection(report_bias, report_gate_c) nengo.Connection(report_gate_c, compare.neurons, transform=[[-100.0]] * p.N_compare, synapse=0.01) for i in range(p.pointer_count): nengo.Connection(report_gate_f, report.ensembles[i].neurons, transform=[[-100.0]] * p.N_report, synapse=0.01) nengo.Connection(report_gate_f, reported.ensembles[i].neurons, transform=[[-100.0]] * p.N_report, synapse=0.01) for ens in memory.all_ensembles: nengo.Connection(memory_clear, ens.neurons, transform=[[-10]] * ens.n_neurons, synapse=0.01) self.p_report = nengo.Probe(report.output, synapse=p.probe_synapse) self.p_compare = nengo.Probe(compare, synapse=p.probe_synapse) self.p_memory = nengo.Probe(memory.output, synapse=p.probe_synapse) self.locals = locals() return model
def go(NPre=100, N=100, t=10, m=Uniform(30, 30), i=Uniform(-0.8, 0.8), neuron_type=LIF(), seed=0, dt=0.001, fPre=None, fEns=None, fS=DoubleExp(2e-2, 2e-1), dPreA=None, dPreB=None, dEns=None, ePreA=None, ePreB=None, eBio=None, stage=None, alpha=1e-6, eMax=1e0, stimA=lambda t: np.sin(t), stimB=lambda t: 0): with nengo.Network(seed=seed) as model: inptA = nengo.Node(stimA) inptB = nengo.Node(stimB) preInptA = nengo.Ensemble(NPre, 1, radius=3, max_rates=m, seed=seed) preInptB = nengo.Ensemble(NPre, 1, max_rates=m, seed=seed) ens = nengo.Ensemble(N, 1, max_rates=m, intercepts=i, neuron_type=neuron_type, seed=seed) tarEns = nengo.Ensemble(N, 1, max_rates=m, intercepts=i, neuron_type=nengo.LIF(), seed=seed) cpa = nengo.Connection(inptA, preInptA, synapse=None, seed=seed) cpb = nengo.Connection(inptB, preInptB, synapse=None, seed=seed) pInptA = nengo.Probe(inptA, synapse=None) pInptB = nengo.Probe(inptB, synapse=None) pPreInptA = nengo.Probe(preInptA.neurons, synapse=None) pPreInptB = nengo.Probe(preInptB.neurons, synapse=None) pEns = nengo.Probe(ens.neurons, synapse=None) pTarEns = nengo.Probe(tarEns.neurons, synapse=None) if stage == 1: c0b = nengo.Connection(preInptB, tarEns, synapse=fPre, solver=NoSolver(dPreB), seed=seed + 1) c1b = nengo.Connection(preInptB, ens, synapse=fPre, solver=NoSolver(dPreB), seed=seed + 1) learnEncoders(c1b, tarEns, fS, alpha=alpha, eMax=eMax) if stage == 2: c0a = nengo.Connection(preInptA, tarEns, synapse=fPre, solver=NoSolver(dPreA), seed=seed) c0b = nengo.Connection(preInptB, tarEns, synapse=fPre, solver=NoSolver(dPreB), seed=seed + 1) c1a = nengo.Connection(preInptA, ens, synapse=fPre, solver=NoSolver(dPreA), seed=seed) c1b = nengo.Connection(preInptB, ens, synapse=fPre, solver=NoSolver(dPreB), seed=seed + 1) learnEncoders(c1a, tarEns, fS, alpha=alpha, eMax=eMax) if stage == 3: c1a = nengo.Connection(preInptA, ens, synapse=fPre, solver=NoSolver(dPreA), seed=seed) c1b = nengo.Connection(preInptB, ens, synapse=fPre, solver=NoSolver(dPreB), seed=seed + 1) if stage == 4: preInptC = nengo.Ensemble(NPre, 1, max_rates=m, seed=seed) ens2 = nengo.Ensemble(N, 1, max_rates=m, intercepts=i, neuron_type=neuron_type, seed=seed) ens3 = nengo.Ensemble(N, 1, max_rates=m, intercepts=i, neuron_type=neuron_type, seed=seed) nengo.Connection(inptB, preInptC, synapse=fEns, seed=seed) c1a = nengo.Connection(preInptA, ens, synapse=fPre, solver=NoSolver(dPreA), seed=seed) c2b = nengo.Connection(preInptB, ens2, synapse=fPre, solver=NoSolver(dPreB), seed=seed + 1) c3 = nengo.Connection(ens2, ens, synapse=fEns, solver=NoSolver(dEns), seed=seed) c4a = nengo.Connection(preInptA, ens3, synapse=fPre, solver=NoSolver(dPreA), seed=seed) c4b = nengo.Connection(preInptC, ens3, synapse=fPre, solver=NoSolver(dPreB), seed=seed) learnEncoders(c3, ens3, fS, alpha=alpha / 10, eMax=eMax) pTarEns = nengo.Probe(ens3.neurons, synapse=None) if stage == 5: c1a = nengo.Connection(preInptA, ens, synapse=fPre, solver=NoSolver(dPreA), seed=seed) c5 = nengo.Connection(ens, ens, synapse=fEns, solver=NoSolver(dEns), seed=seed) with nengo.Simulator(model, seed=seed, dt=dt, progress_bar=False) as sim: if isinstance(neuron_type, Bio): if stage == 1: setWeights(c1b, dPreB, ePreB) if stage == 2: setWeights(c1a, dPreA, ePreA) setWeights(c1b, dPreB, ePreB) if stage == 3: setWeights(c1a, dPreA, ePreA) setWeights(c1b, dPreB, ePreB) if stage == 4: setWeights(c1a, dPreA, ePreA) setWeights(c2b, dPreB, ePreB) setWeights(c4a, dPreA, ePreA) setWeights(c4b, dPreB, ePreB) setWeights(c3, dEns, eBio) if stage == 5: setWeights(c1a, dPreA, ePreA) setWeights(c5, dEns, eBio) neuron.h.init() sim.run(t, progress_bar=True) reset_neuron(sim, model) else: sim.run(t, progress_bar=True) ePreB = c1b.e if stage == 1 else ePreB ePreA = c1a.e if stage == 2 else ePreA eBio = c3.e if stage == 4 else eBio return dict( times=sim.trange(), inptA=sim.data[pInptA], inptB=sim.data[pInptB], preInptA=sim.data[pPreInptA], preInptB=sim.data[pPreInptB], ens=sim.data[pEns], tarEns=sim.data[pTarEns], ePreA=ePreA, ePreB=ePreB, eBio=eBio, )
def run(self): n_neurons = 40 subdim = 16 direct = False output = self.stimuli.output # vector output from coherence score threshold = self.stimuli.threshold # for correct answer on inf task g_transform = np.transpose(np.ones((1, self.dimensions))) # mem gate model = spa.SPA(label='ConceptModel', seed=self.seed) with model: # Vision Component model.vision = spa.Buffer(dimensions=self.dimensions, subdimensions=subdim, neurons_per_dimension=n_neurons, vocab=self.main_voc, direct=direct) # Memory Component model.sp_mem = spa.Buffer(dimensions=self.dimensions, subdimensions=subdim, neurons_per_dimension=n_neurons, vocab=self.main_voc, direct=direct) model.context_mem = spa.Memory(dimensions=self.dimensions, subdimensions=subdim, neurons_per_dimension=n_neurons, vocab=self.main_voc, tau=0.01 / 0.3, direct=direct) # Inferential Evaluation Subsystem model.inference = spa.Buffer(dimensions=self.dimensions, subdimensions=subdim, neurons_per_dimension=n_neurons, vocab=self.feat_voc, direct=direct) model.score = spa.Memory(dimensions=1, neurons_per_dimension=3000, synapse=0.05, direct=direct) model.gatesignal = spa.Memory(dimensions=1, neurons_per_dimension=500, synapse=0.05, direct=direct) model.cleanup1 = spa.AssociativeMemory( input_vocab=self.feat_voc, output_vocab=self.weight_voc, n_neurons_per_ensemble=250, threshold=0.25) # Perceptual Evaluation Subsystem model.cleanup2 = spa.AssociativeMemory(input_vocab=self.label_voc, output_vocab=self.label_voc, n_neurons_per_ensemble=1000, threshold=threshold) # Shared Component model.decision = spa.Memory(dimensions=self.dimensions, subdimensions=subdim, neurons_per_dimension=n_neurons, vocab=self.label_voc, tau=0.01 / 0.3, synapse=0.05, direct=direct) # Motor Component model.motor = spa.Memory(dimensions=self.dimensions, subdimensions=subdim, neurons_per_dimension=n_neurons, vocab=self.label_voc, synapse=0.1, direct=direct) # Convenient probing of rule applications if self.raster: model.apps = spa.Buffer(dimensions=self.dimensions, subdimensions=subdim, neurons_per_dimension=n_neurons, vocab=self.feat_voc, direct=direct) self.pApps = nengo.Probe(model.apps.state.output, synapse=0.03) self.appSpikes = nengo.Probe(model.apps.state.ea_ensembles[3], 'spikes') nengo.Connection(model.cleanup1.output, model.apps.state.input) # Action definitions actions = spa.Actions( 'dot(vision, POSNER) --> context_mem=VIS', 'dot(vision, BROOKS) --> context_mem=VIS', 'dot(vision, MURPHY) --> context_mem=INFER', 'dot(context_mem, VIS) --> gatesignal=2, context_mem=R5', 'dot(context_mem, INFER) --> context_mem=R1', 'dot(context_mem, R1) --> inference=sp_mem*~R1, context_mem=R2', 'dot(context_mem, R2) --> inference=sp_mem*~R2, context_mem=R3', 'dot(context_mem, R3) --> inference=sp_mem*~R3, context_mem=R4', 'dot(context_mem, R4) --> inference=sp_mem*~R4, context_mem=R5', 'dot(context_mem, R5) --> motor=decision') # Basal ganglia and thalamus model.bg = spa.BasalGanglia(actions) model.thal = spa.Thalamus(model.bg) # Subnetworks defined outside of SPA model.product = Product(600, self.dimensions) model.vis_gate = Product(300, self.dimensions) model.mem_gate = Product(300, self.dimensions) model.conv = CircularConvolution(250, self.dimensions, invert_a=True) # Connections for gate with memory for perceptual evaluation tasks nengo.Connection(model.vision.state.output, model.vis_gate.B) nengo.Connection(model.gatesignal.state.output, model.vis_gate.A, transform=g_transform) nengo.Connection(model.vis_gate.output, model.conv.A) nengo.Connection(model.sp_mem.state.output, model.mem_gate.B) nengo.Connection(model.gatesignal.state.output, model.mem_gate.A, transform=g_transform) nengo.Connection(model.mem_gate.output, model.conv.B) nengo.Connection(model.conv.output, model.decision.state.input) # Connections for inferential evaluation tasks nengo.Connection(model.inference.state.output, model.cleanup1.input) nengo.Connection(model.cleanup1.output, model.product.A) nengo.Connection(model.vision.state.output, model.product.B) nengo.Connection(model.cleanup2.output, model.decision.state.input) nengo.Connection(model.product.output, model.score.state.input, transform=model.product.dot_product_transform()) nengo.Connection(model.score.state.output, model.cleanup2.input, transform=np.transpose(output)) # Input to visual buffer def vision(t): if t < 0.08: return self.stimuli.task if 0.0801 <= t < 1: return self.probe else: return '0' model.input = spa.Input(vision=vision, sp_mem=self.stimuli.memory) # Inhibit the gate with inference actions actions = [2, 4, 5, 6, 7, 8] target = model.gatesignal for action in actions: for e in target.all_ensembles: nengo.Connection(model.thal.actions.ensembles[action], e.neurons, transform=[[-2]] * e.n_neurons) # Set radius for ensemble computing scalar coherence score. for ens in model.score.state.ensembles: ens.radius = 2 # Define probes for semantic pointer plots self.pVision = nengo.Probe(model.vision.state.output, synapse=0.03) self.pMotor = nengo.Probe(model.motor.state.output, synapse=0.03) self.pMemory = nengo.Probe(model.sp_mem.state.output, synapse=0.03) self.pContext = nengo.Probe(model.context_mem.state.output, synapse=0.03) self.pScore = nengo.Probe(model.score.state.output, synapse=0.03) self.pDecision = nengo.Probe(model.decision.state.output, synapse=0.03) self.pActions = nengo.Probe(model.thal.actions.output, synapse=0.01) self.pUtility = nengo.Probe(model.bg.input, synapse=0.01) # Define probes for spike rasters self.visSpikes = nengo.Probe(model.vision.state.ea_ensembles[3], 'spikes') self.conSpikes = nengo.Probe( model.context_mem.state.ea_ensembles[5], 'spikes') self.memSpikes = nengo.Probe(model.sp_mem.state.ea_ensembles[7], 'spikes') self.motSpikes = nengo.Probe(model.motor.state.ea_ensembles[1], 'spikes') self.scoSpikes = nengo.Probe(model.score.state.ea_ensembles[0], 'spikes') # Run the model sim = nengo.Simulator(model) sim.run(0.45) # Save graph if plotting chosen if self.raster: graph = Plotter(self, sim) if self.stimuli.task == 'MURPHY': graph.plot_spikes_inf() else: graph.plot_spikes_vis() # Assess correctness of output self.measure_output(sim)
def __init__(self, mapping, threshold=0.2, learning_rate=1e-4, DimVocab=256, subdimensions=32, learned_function_scale=2.0): model = spa.SPA() self.model = model self.mapping = mapping #self.vocab_category = spa.Vocabulary(D_category) #self.vocab_items = spa.Vocabulary(D_items) self.VocabUnified = spa.Vocabulary(DimVocab) for k in sorted( mapping.keys()): #allocating verctors for categories name self.VocabUnified.parse(k) for v in mapping[k]: # allocating vectors to the items self.VocabUnified.parse(v) with model: model.cue = spa.State(DimVocab, vocab=self.VocabUnified, subdimensions=subdimensions) model.target = spa.State(DimVocab, vocab=self.VocabUnified, subdimensions=subdimensions) c = [] n_sub = len(model.cue.state_ensembles.ea_ensembles) for i in range(n_sub): cues = [] targets = [] for cue, vals in mapping.items(): for val in vals: cues.append( self.VocabUnified.parse(cue).v[i * subdimensions:(i + 1) * subdimensions]) targets.append( self.VocabUnified.parse(val).v / n_sub * learned_function_scale) cues.append( self.VocabUnified.parse(val).v[i * subdimensions:(i + 1) * subdimensions]) targets.append( self.VocabUnified.parse(cue).v / n_sub * learned_function_scale) cc = nengo.Connection( model.cue.all_ensembles[i], model.target.input, learning_rule_type=nengo.PES(learning_rate=learning_rate), **nengo.utils.connection.target_function(cues, targets)) cc.eval_points = cues cc.function = targets c.append(cc) print i #model.error = spa.State(D_items, vocab=self.vocab_items) #nengo.Connection(model.items.output, model.error.input) #nengo.Connection(model.error.output, c.learning_rule) #I am not sure how this implements the learning model.error = spa.State(DimVocab, vocab=self.VocabUnified, subdimensions=subdimensions) nengo.Connection(model.target.output, model.error.input) print 'the loop ended, right?' for cc in c: nengo.Connection(model.error.output, cc.learning_rule) self.stim_cue_value = np.zeros(DimVocab) #? self.stim_cue = nengo.Node(self.stim_cue_fun) #? nengo.Connection(self.stim_cue, model.cue.input, synapse=None) self.stim_correct_value = np.zeros(DimVocab) self.stim_correct = nengo.Node(self.stim_correct) nengo.Connection(self.stim_correct, model.error.input, synapse=None, transform=-1) self.stim_stoplearn_value = np.zeros(1) self.stim_stoplearn = nengo.Node(self.stim_stoplearn) for ens in model.error.all_ensembles: nengo.Connection(self.stim_stoplearn, ens.neurons, synapse=None, transform=-10 * np.ones((ens.n_neurons, 1))) self.stim_justmemorize_value = np.zeros(1) self.stim_justmemorize = nengo.Node(self.stim_justmemorize) for ens in model.target.all_ensembles: #? nengo.Connection(self.stim_justmemorize, ens.neurons, synapse=None, transform=-10 * np.ones((ens.n_neurons, 1))) self.probe_target = nengo.Probe(model.target.output, synapse=0.01) if __name__ != '__builtin__': self.sim = nengo.Simulator(self.model)
def test_conv_overlap_input(Simulator, plt): """Tests a fully on-chip conv connection. """ conv2d = pytest.importorskip("nengo._vendor.npconv2d.conv2d") kernel = np.array([[-1, 2, -1], [-1, 2, -1], [-1, 2, -1]], dtype=float) kernel /= kernel.max() image = np.array( [ [1, 2, 1, 2, 0], [2, 3, 2, 1, 1], [1, 2, 1, 2, 3], [2, 3, 2, 1, 1], [1, 2, 1, 2, 0], ], dtype=float, ) image /= image.max() input_scale = 119.0 bias = input_scale * image.ravel() neuron_type = nengo.SpikingRectifiedLinear() y_ref = LoihiSpikingRectifiedLinear().rates(image.ravel(), input_scale, 0) y_ref = conv2d.conv2d(y_ref.reshape((1, 5, 5, 1)), kernel.reshape((3, 3, 1, 1)), pad="VALID") y_ref = LoihiSpikingRectifiedLinear().rates(y_ref.ravel(), 1.0, 0.0).reshape((3, 3)) with nengo.Network() as net: a = nengo.Ensemble( bias.size, 1, neuron_type=neuron_type, gain=nengo.dists.Choice([0]), bias=bias, ) transform = nengo_transforms.Convolution(n_filters=1, input_shape=(4, 5, 1), init=kernel.reshape( (3, 3, 1, 1))) b0 = nengo.Ensemble( transform.output_shape.size, 1, neuron_type=neuron_type, gain=nengo.dists.Choice([1]), bias=nengo.dists.Choice([0]), ) b1 = nengo.Ensemble( transform.output_shape.size, 1, neuron_type=neuron_type, gain=nengo.dists.Choice([1]), bias=nengo.dists.Choice([0]), ) nengo.Connection(a.neurons[:20], b0.neurons, transform=transform) nengo.Connection(a.neurons[5:], b1.neurons, transform=transform) b0p = nengo.Probe(b0.neurons, synapse=nengo.Alpha(0.02)) b1p = nengo.Probe(b1.neurons, synapse=nengo.Alpha(0.02)) with Simulator(net) as sim: sim.run(0.3) y_ref = y_ref / input_scale y0 = sim.data[b0p][-1].reshape((2, -1)) / input_scale y1 = sim.data[b1p][-1].reshape((2, -1)) / input_scale plt.subplot(131) plt.imshow(y_ref) plt.colorbar() plt.subplot(132) plt.imshow(b0) plt.colorbar() plt.subplot(133) plt.imshow(b1) plt.colorbar() assert np.allclose(y0, y_ref[:2], atol=0.02, rtol=0.1) assert np.allclose(y1, y_ref[1:], atol=0.02, rtol=0.1)
model = nengo.Network(label='Matrix Multiplication', seed=123) # Values should stay within the range (-radius,radius) radius = 1 with model: # Make 2 EnsembleArrays to store the input A = nengo.networks.EnsembleArray(N, Amat.size, radius=radius, label="A") B = nengo.networks.EnsembleArray(N, Bmat.size, radius=radius, label="B") # connect inputs to them so we can set their value inputA = nengo.Node(Amat.ravel(), label="input A") inputB = nengo.Node(Bmat.ravel(), label="input B") nengo.Connection(inputA, A.input) nengo.Connection(inputB, B.input) A_probe = nengo.Probe(A.output, sample_every=0.01, synapse=0.01) B_probe = nengo.Probe(B.output, sample_every=0.01, synapse=0.01) with model: # The C matix is composed of populations that each contain # one element of A and one element of B. # These elements will be multiplied together in the next step. C = nengo.networks.EnsembleArray(N, n_ensembles=Amat.size * Bmat.shape[1], ens_dimensions=2, radius=1.5 * radius, label="C") # The appropriate encoders make the multiplication more accurate for ens in C.ensembles: ens.encoders = np.tile([[1, 1], [-1, 1], [1, -1], [-1, -1]],
def test_chip_population_axons(on_chip, precompute, pop_type, channels_last, Simulator, rng): """Check that all types of population axons work as inputs or between cores. Also, on the chip, dummy axons were still having an effect. Check this is fixed. """ def conv_layer(input=None, label=None, **kwargs): conv = nengo.Convolution(**kwargs) layer = nengo.Ensemble(conv.output_shape.size, 1, label=label) conn = (nengo.Connection(input, layer.neurons, transform=conv) if input is not None else None) return layer, conv, conn if pop_type == 16 and not channels_last: pytest.skip( "pop16 axons not compatible with single-compartment shifts") max_rate = 100 amp = 1 / max_rate n_filters0 = 4 n_filters1 = 4 # 6 x 6 input will have one unused pixel at edge with 3 x 3 kernel and stride 2 input_shape = (6, 6, 1) if channels_last else (1, 6, 6) input_shape = nengo_transforms.ChannelShape(input_shape, channels_last=channels_last) X = rng.uniform(0.2, 1, size=input_shape.shape) kernel0 = rng.uniform(0.2, 1, size=(1, 1, 1, n_filters0)) kernel1 = rng.uniform(0.1, 0.5, size=(3, 3, n_filters0, n_filters1)) with nengo.Network(seed=0) as net: nengo_loihi.add_params(net) net.config[nengo.Ensemble].neuron_type = nengo.SpikingRectifiedLinear( amplitude=amp) net.config[nengo.Ensemble].max_rates = nengo.dists.Choice([max_rate]) net.config[nengo.Ensemble].intercepts = nengo.dists.Choice([0]) net.config[nengo.Connection].synapse = 0.005 inp = nengo.Node(X.ravel()) if not on_chip else None # first layer is off-chip to translate the inputs into spikes layer0, conv0, _ = conv_layer( input=inp, n_filters=n_filters0, input_shape=input_shape, channels_last=channels_last, kernel_size=(1, 1), init=kernel0, label="layer0", ) net.config[layer0].on_chip = on_chip if on_chip: assert kernel0.shape[:2] == (1, 1) w = kernel0[0, 0] Y = X.dot(w) if channels_last else np.tensordot(w.T, X, axes=1) layer0.gain = nengo.dists.Choice([0.0]) layer0.bias = Y.ravel() * max_rate layer1, conv1, conn1 = conv_layer( input=layer0.neurons, n_filters=n_filters1, input_shape=conv0.output_shape, channels_last=channels_last, kernel_size=(3, 3), strides=(2, 2), init=kernel1, label="layer1", ) net.config[conn1].pop_type = pop_type probe = nengo.Probe(layer1.neurons) sim_time = 0.1 with Simulator(net, target="sim") as emulator: emulator.run(sim_time) with Simulator(net, target="loihi", precompute=precompute) as loihi: loihi.run(sim_time) assert np.all(emulator.data[probe].sum(axis=0) > 0) assert np.array_equal(loihi.data[probe], emulator.data[probe])
def generate( target_xyz, net=None, # define q2xyz, euc, error_combined, mse inside net probes_on=True, # set True to record data use_intrcepts=False, direct_mode=False, n_scale=100): """ Connect up the q2xyz, euc, error_combined and mse sub-networks up for the Inverse Kinematics model. """ config = nengo.Config(nengo.Connection, nengo.Ensemble) with net, config: current_q = [0.0, 0.0, 0.0, 0.0, 0.0] dim = net.dim # the number of DOF of the arm axis = net.axis # the number axis net.probes_on = probes_on net.xyz_in = nengo.Node(target_xyz, label='xyz_in') net.xyz_t = nengo.Node(size_in=axis, label='xyz_t') net.xyz_diff = nengo.Node(size_in=2 * axis, label='xyz_diff') net.error_q = nengo.Node(size_in=dim + axis, label='error_q') net.q_fixed = nengo.Node(size_in=dim, label='q_fixed') if use_intrcepts: net.xyz_t = nengo.Ensemble( n_neurons=2000, dimensions=axis, radius=np.sqrt(axis), intercepts=get_intercepts(2000, axis), ) else: if direct_mode: net.xyz_t = nengo.Ensemble( n_neurons=2000, dimensions=axis, radius=np.sqrt(axis), neuron_type=nengo.Direct(), ) else: net.xyz_t = nengo.Ensemble( n_neurons=2000, dimensions=axis, radius=np.sqrt(axis), ) nengo.Connection(net.xyz_in, net.xyz_t, transform=-1) nengo.Connection(net.xyz_in, net.xyz_diff[0:3]) nengo.Connection(net.xyz_t, net.xyz_diff[3:]) nengo.Connection(net.xyz_t, net.error_q[5:]) nengo.Connection(net.q_fixed, net.error_q[0:5]) ''' q2xyz ''' nengo.Connection(net.q_fixed, net.q2xyz.input) nengo.Connection(net.q2xyz.output, net.xyz_t) ''' error_combined ''' nengo.Connection(net.error_q, net.error_combined.input) nengo.Connection(net.error_combined.output, net.q_fixed) ''' euc ''' nengo.Connection(net.xyz_t, net.euc.input) ''' mse ''' nengo.Connection(net.xyz_diff, net.mse.input) if probes_on: net.probe_euc = nengo.Probe(net.euc.output, synapse=0.1) net.probe_mse = nengo.Probe(net.mse.output, synapse=0.05) net.probe_xyz_in = nengo.Probe(net.xyz_in, synapse=0.05) net.probe_xyz_pred = nengo.Probe(net.q2xyz.output, synapse=0.05) net.probe_q_fixed = nengo.Probe(net.q_fixed, synapse=0.05) net.probe_q_c = nengo.Probe(net.error_combined.q_c, synapse=0.05) net.probe_q_in = nengo.Probe(net.error_combined.q_in, synapse=0.05) net.probe_error_combined = nengo.Probe( net.error_combined.error_combined, synapse=0.05) return net
def test_conv_input(channels_last, Simulator, plt, allclose): input_shape = make_channel_shape((4, 4), 1, channels_last=channels_last) seed = 3 # fix seed to do the same computation for both channel positions rng = np.random.RandomState(seed + 1) with nengo.Network(seed=seed) as net: nengo_loihi.add_params(net) a = nengo.Node(rng.uniform(0, 1, size=input_shape.size)) nc = 2 kernel = np.array([1.0, -1.0]).reshape((1, 1, 1, nc)) transform = nengo_transforms.Convolution( nc, input_shape, channels_last=channels_last, init=kernel, kernel_size=(1, 1), ) b = nengo.Ensemble( transform.output_shape.size, 1, neuron_type=nengo.SpikingRectifiedLinear(), max_rates=nengo.dists.Choice([50]), intercepts=nengo.dists.Choice([0]), ) net.config[b].on_chip = False nengo.Connection(a, b.neurons, transform=transform) output_shape = transform.output_shape nf = 4 kernel = rng.uniform(-0.005, 0.005, size=(3, 3, nc, nf)) transform = nengo_transforms.Convolution( nf, output_shape, channels_last=channels_last, init=-kernel, kernel_size=(3, 3), ) c = nengo.Ensemble( transform.output_shape.size, 1, neuron_type=nengo.LIF(), max_rates=nengo.dists.Choice([100]), intercepts=nengo.dists.Choice([0]), ) nengo.Connection(b.neurons, c.neurons, transform=transform) output_shape = transform.output_shape p = nengo.Probe(c.neurons) with nengo.Simulator(net, optimize=False) as sim: sim.run(1.0) with Simulator(net, seed=seed) as sim_loihi: sim_loihi.run(1.0) p0 = np.sum(sim.data[p] > 0, axis=0).reshape(output_shape.shape) p1 = np.sum(sim_loihi.data[p] > 0, axis=0).reshape(output_shape.shape) if not channels_last: p0 = np.transpose(p0, (1, 2, 0)) p1 = np.transpose(p1, (1, 2, 0)) plt.plot(p0.ravel(), "k") plt.plot(p1.ravel(), "b--") # loihi spikes are not exactly the same, but should be close-ish assert allclose(p0, p1, rtol=0.15, atol=1)
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_conv_split(Simulator, rng, plt, allclose): channels_last = False # load data with open(os.path.join(test_dir, "mnist10.pkl"), "rb") as f: test10 = pickle.load(f) input_shape = make_channel_shape((28, 28), 1, channels_last) n_filters = 8 kernel_size = (7, 7) kernel = Gabor(freq=Uniform(0.5, 1)).generate(n_filters, kernel_size, rng=rng) kernel = kernel[None, :, :, :] # single channel kernel = np.transpose(kernel, (2, 3, 0, 1)) strides = (2, 2) seed = 3 # fix seed to do the same computation for both channel positions with nengo.Network(seed=seed) as net: nengo_loihi.add_params(net) a = nengo.Node(test10[0][0].ravel()) # --- make population to turn image into spikes nc = 1 in_kernel = np.array([1.0]).reshape((1, 1, 1, nc)) transform = nengo_transforms.Convolution( 1, input_shape, kernel_size=(1, 1), init=in_kernel, channels_last=channels_last, ) b = nengo.Ensemble( transform.output_shape.size, 1, neuron_type=nengo.SpikingRectifiedLinear(), max_rates=nengo.dists.Choice([50]), intercepts=nengo.dists.Choice([0]), ) net.config[b].on_chip = False nengo.Connection(a, b.neurons, transform=transform) in_shape = transform.output_shape transform = nengo_transforms.Convolution( n_filters, in_shape, kernel_size=kernel_size, strides=strides, init=kernel, channels_last=channels_last, ) out_shape = transform.output_shape split_slices = conv.split_channels(out_shape, max_size=1024, max_channels=4) # --- make convolution population, split across ensembles cc = [] cp = [] out_shapes = [] xslice = conv.ImageSlice(in_shape) for yslice in split_slices: transform_xy = conv.split_transform(transform, xslice, yslice) out_shapes.append(transform_xy.output_shape) c = nengo.Ensemble( transform_xy.output_shape.size, 1, neuron_type=nengo.LIF(), max_rates=nengo.dists.Choice([15]), intercepts=nengo.dists.Choice([0]), ) nengo.Connection(b.neurons, c.neurons, transform=transform_xy) cc.append(c) cp.append(nengo.Probe(c.neurons)) simtime = 0.3 with nengo.Simulator(net, optimize=False) as sim_nengo: sim_nengo.run(simtime) hw_opts = dict(snip_max_spikes_per_step=100) with Simulator(net, seed=seed, hardware_options=hw_opts) as sim_loihi: sim_loihi.run(simtime) nengo_out = [] loihi_out = [] for p, out_shape_i in zip(cp, out_shapes): nengo_out.append( (sim_nengo.data[p] > 0).sum(axis=0).reshape(out_shape_i.shape)) loihi_out.append( (sim_loihi.data[p] > 0).sum(axis=0).reshape(out_shape_i.shape)) if channels_last: nengo_out = np.concatenate(nengo_out, axis=2) loihi_out = np.concatenate(loihi_out, axis=2) # put channels first to display them separately nengo_out = np.transpose(nengo_out, (2, 0, 1)) loihi_out = np.transpose(loihi_out, (2, 0, 1)) else: nengo_out = np.concatenate(nengo_out, axis=0) loihi_out = np.concatenate(loihi_out, axis=0) out_max = np.maximum(nengo_out.max(), loihi_out.max()) # --- plot results rows = 2 cols = 3 ax = plt.subplot(rows, cols, 1) imshow(test10[0][0].reshape((28, 28)), vmin=0, vmax=1, ax=ax) ax = plt.subplot(rows, cols, 2) tile(np.transpose(kernel[0], (2, 0, 1)), cols=8, ax=ax) ax = plt.subplot(rows, cols, 3) plt.hist(nengo_out.ravel(), bins=31) plt.hist(loihi_out.ravel(), bins=31) ax = plt.subplot(rows, cols, 4) tile(nengo_out, vmin=0, vmax=out_max, cols=8, ax=ax) ax = plt.subplot(rows, cols, 6) tile(loihi_out, vmin=0, vmax=out_max, cols=8, ax=ax) assert allclose(loihi_out, nengo_out, atol=0.15 * out_max, rtol=0.15)
def rate_nengo_dl_net(neuron_type, discretize=True, dt=0.001, nx=256, gain=1., bias=0.): """Create a network for determining rate curves with Nengo DL. Arguments --------- neuron_type : NeuronType The neuron type used in the network's ensemble. discretize : bool, optional (Default: True) Whether the tau_ref and tau_rc values should be discretized before generating rate curves. dt : float, optional (Default: 0.001) Simulator timestep. nx : int, optional (Default: 256) Number of x points in the rate curve. gain : float, optional (Default: 1.) Gain of all neurons. bias : float, optional (Default: 0.) Bias of all neurons. """ net = nengo.Network() net.dt = dt net.bias = bias net.gain = gain lif_kw = dict(amplitude=neuron_type.amplitude) if isinstance(neuron_type, LoihiLIF): net.x = np.linspace(-1, 30, nx) net.sigma = 0.02 lif_kw['tau_rc'] = neuron_type.tau_rc lif_kw['tau_ref'] = neuron_type.tau_ref if discretize: lif_kw['tau_ref'] = discretize_tau_ref(lif_kw['tau_ref'], dt) lif_kw['tau_rc'] = discretize_tau_rc(lif_kw['tau_rc'], dt) lif_kw['tau_ref'] += 0.5 * dt elif isinstance(neuron_type, LoihiSpikingRectifiedLinear): net.x = np.linspace(-1, 999, nx) net.tau_ref1 = 0.5 * dt net.j = neuron_type.current(net.x[:, np.newaxis], gain, bias).squeeze(axis=1) - 1 with net: if isinstance(neuron_type, LoihiLIF) and discretize: nengo_dl.configure_settings(lif_smoothing=net.sigma) net.stim = nengo.Node(np.zeros(nx)) net.ens = nengo.Ensemble(nx, 1, neuron_type=neuron_type, gain=nengo.dists.Choice([gain]), bias=nengo.dists.Choice([bias])) nengo.Connection(net.stim, net.ens.neurons, synapse=None) net.probe = nengo.Probe(net.ens.neurons) rates = dict( ref=loihi_rates(neuron_type, net.x, gain, bias, dt=dt).squeeze(axis=1)) # rates['med'] is an approximation of the smoothed Loihi tuning curve if isinstance(neuron_type, LoihiLIF): rates['med'] = nengo_rates(nengo.LIF(**lif_kw), net.x, gain, bias).squeeze(axis=1) elif isinstance(neuron_type, LoihiSpikingRectifiedLinear): rates['med'] = np.zeros_like(net.j) rates['med'][net.j > 0] = (neuron_type.amplitude / (net.tau_ref1 + 1. / net.j[net.j > 0])) return net, rates, lif_kw
# another pooling layer x = nengo_dl.tensor_layer(x, tf.layers.average_pooling2d, shape_in=(28, 28, 128), pool_size=2, strides=2) # linear readout x = nengo_dl.tensor_layer(x, tf.layers.dense, units=26) final_x = nengo_dl.tensor_layer(x, neuron_type) # we'll create two different output probes, one with a filter # (for when we're simulating the network over time and # accumulating spikes), and one without (for when we're # training the network using a rate-based approximation) out_p = nengo.Probe(x) out_p_filt = nengo.Probe(x, synapse=0.1) final_probe = nengo.Probe(final_x, 'spikes', synapse=0.1) # Adding time steps minibatch_size = 200 sim = nengo_dl.Simulator(net, minibatch_size=minibatch_size) train_data = { inp: np.asarray(train_data[0])[:, None, :], out_p: np.asarray(train_data[1])[:, None, :] } n_steps = 30 test_data = {
model = nengo.Network("Probing") with model: ens = nengo.Ensemble(n_neurons=50, dimensions=1) #node_number = nengo.Node(output=0.5) node_function = nengo.Node(output=np.sin) nengo.Connection(node_function, ens) print(ens.probeable) with model: # Connect the input signal to the neuron nengo.Connection(node_function, ens) with model: # The original input function_probe = nengo.Probe(node_function) # The raw spikes from the neuron spikes = nengo.Probe(ens.neurons) # Subthreshold soma voltage of the neuron voltage = nengo.Probe(ens.neurons, 'voltage') # Spikes filtered by a 10ms post-synaptic filter filtered = nengo.Probe(ens, synapse=0.01) with nengo.Simulator(model) as sim: # Create the simulator sim.run(5) print("Decoded output of the ensemble") print(sim.trange(), sim.data[filtered]) print("Spikes") print(sim.trange(), sim.data[spikes])
# first layer is off-chip to translate the images into spikes net.config[layer.ensemble].on_chip = False # build parallel copies of the network for _ in range(n_parallel): layer2, conv2 = conv_layer(layer, 1, conv.output_shape, kernel_size=(3, 3), strides=(2, 2)) nengo.Connection(layer2, out, transform=nengo_dl.dists.Glorot()) print("LAYER") print(out.size_in, "->", out.size_out) out_p = nengo.Probe(out) out_p_filt = nengo.Probe(out, synapse=nengo.Alpha(0.016)) # set up training data minibatch_size = 100 # for the test data evaluation we'll be running the network over time # using spiking neurons, so we need to repeat the input/target data # for a number of timesteps (based on the presentation_time) test_data = { inp: np.tile(test_data[0][:100, None, :], (1, int(presentation_time / dt), 1)), out_p_filt: np.tile(test_data[1][:100, None, :], (1, int(presentation_time / dt), 1)) }
synapse=tau_sensory) lin_control_func = partial(sense_to_lin_vel, n_sensors=n_sensors) nengo.Connection(environment[3:n_sensors + 3], linear_velocity, function=lin_control_func, synapse=tau_sensory) ang_exc_const = nengo.Node([0.15]) ang_exc = nengo.Ensemble(n_neurons=n_neurons, dimensions=1) nengo.Connection(ang_exc_const, ang_exc, synapse=tau_sensory) nengo.Connection(ang_exc, angular_velocity, transform=[[1.], [1.]]) if __name__ == '__main__': runtime = 5.0 with model: tau_probe = 0.05 p_xy = nengo.Probe(environment, synapse=tau_probe) with nengo.Simulator(model, progress_bar=True, dt=dt) as sim: sim.run(runtime) plt.figure(figsize=(16, 6)) plt.title("X-Y Position") plt.plot(sim.trange(), sim.data[p_xy], alpha=0.8, label="Vel error") plt.xlabel("Time (s)") plt.ylabel("Position") plt.legend() plt.show()
net.config[x].trainable = True net.config[conn].trainable = True # add a dropout layer x = nengo_dl.tensor_layer(x, tf.layers.dropout, rate=0.3) # the final 10 dimensional class output x = nengo_dl.tensor_layer(x, tf.layers.dense, units=10) return net, inp, x # construct the network net, inp, out = build_network(softlif_neurons) with net: out_p = nengo.Probe(out) # construct the simulator minibatch_size = 50 sim = nengo_dl.Simulator(net, minibatch_size=minibatch_size) # note that we need to add the time dimension (axis 1), which has length 1 # in this case. we're also going to reduce the number of test images, just to # speed up this example. train_inputs = {inp: mnist.train.images[:, None, :]} train_targets = {out_p: mnist.train.labels[:, None, :]} test_inputs = {inp: mnist.test.images[:minibatch_size * 2, None, :]} test_targets = {out_p: mnist.test.labels[:minibatch_size * 2, None, :]} def objective(x, y):
with Net_1: ipt = nengo.Node(list(MSvt[:, 4])) renderer = nengo.Ensemble(img_size**2, dimensions=n_bases, encoders=UW, label="renderer") #, neuron_type=nengo.Direct()) ibuffer = nengo.Ensemble( n_B, dimensions=img_size**2, encoders=numpy.array([encoder.flatten() for encoder in encoders_B]), label="ibuffer", ) #, neuron_type=nengo.Direct()) out = nengo.Node(size_in=img_size**2) nengo.Connection(ipt, renderer) nengo.Connection(renderer, ibuffer, function=render, synapse=0.01) nengo.Connection(ibuffer, ibuffer, function=lambda x: 0.01 * x, synapse=0.01) probeIbuffer_input = nengo.Probe(ibuffer, attr="input") probeIbuffer_output = nengo.Probe(ibuffer, attr="decoded_output") sim = nengo.Simulator(Net_1) sim.run(0.5) sim.run(0.5) ibuffer_inputData = sim.data[probeIbuffer_input] ibuffer_outputData = sim.data[probeIbuffer_output]
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, transform=1) probes.append(nengo.Probe(b)) names.append( f"{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, f"Solver '{name}' does not meet tolerances"
Any smooth function can be decoded. """ def aligned(n_neurons, radius=0.9): intercepts = np.linspace(-radius, radius, n_neurons) encoders = np.tile([[1], [-1]], (n_neurons // 2, 1)) intercepts *= encoders[:, 0] return intercepts, encoders model = nengo.Network(label="NEF summary") with model: input = nengo.Node(lambda t: t * 2 - 1) input_probe = nengo.Probe(input) intercepts, encoders = aligned(8) # Makes evenly spaced intercepts with model: A = nengo.Ensemble(8, dimensions=1, intercepts=intercepts, max_rates=Uniform(80, 100), encoders=encoders) with model: nengo.Connection(input, A) A_spikes = nengo.Probe(A.neurons) model = nengo.Network(label="NEF summary") with model: