NengoDL Simulator

This is the class that allows users to access the nengo_dl backend. This can be used as a drop-in replacement for nengo.Simulator (i.e., simply replace any instance of nengo.Simulator with nengo_dl.Simulator and everything will continue to function as normal).

In addition, the Simulator exposes features unique to the nengo_dl backend, such as Simulator.train().

class nengo_dl.simulator.Simulator(network, dt=0.001, seed=None, model=None, tensorboard=False, dtype=tf.float32, step_blocks=50, device=None, unroll_simulation=True, minibatch_size=None)[source]

Simulate network using the nengo_dl backend.

Parameters:
network : Network or None

a network object to be built and then simulated. If None, then a built model must be passed to model instead

dt : float, optional

length of a simulator timestep, in seconds

seed : int, optional

seed for all stochastic operators used in this simulator

model : Model, optional

pre-built model object

tensorboard : bool, optional

if True, save network output in the Tensorflow summary format, which can be loaded into Tensorboard

dtype : tf.DType, optional

floating point precision to use for simulation

step_blocks : int, optional

controls how many simulation steps run each time the graph is executed (affects memory usage and graph construction time)

device : None or "/cpu:0" or "/gpu:[0-n]", optional

device on which to execute computations (if None then uses the default device as determined by Tensorflow)

unroll_simulation : bool, optional

if True, unroll simulation loop by explicitly building each iteration (up to step_blocks) into the computation graph. if False, use a symbolic loop, which is more general and produces a simpler graph, but is likely to be slower to simulate

minibatch_size : int, optional

the number of simultaneous inputs that will be passed through the network

reset(seed=None)[source]

Resets the simulator to initial conditions.

Parameters:
seed : int, optional

if not None, overwrite the default simulator seed with this value (note: this becomes the new default simulator seed)

step(**kwargs)[source]

Run the simulation for one time step.

Parameters:
kwargs : dict

see _run_steps()

run(time_in_seconds, **kwargs)[source]

Simulate for the given length of time.

Parameters:
time_in_seconds : float

amount of time to run the simulation for

kwargs : dict

see _run_steps()

run_steps(n_steps, **kwargs)[source]

Simulate for the given number of steps.

Parameters:
n_steps : int

the number of simulation steps to be executed

kwargs : dict

see _run_steps()

Notes

If step_blocks is specified, and n_steps > step_blocks, this will repeatedly execute step_blocks timesteps until the the number of steps executed is >= n_steps.

_run_steps(n_steps, profile=False, input_feeds=None)[source]

Execute step_blocks sized segments of the simulation.

Parameters:
n_steps : int

the number of simulation steps to be executed

profile : bool, optional

if True, collect Tensorflow profiling information while the simulation is running (this will slow down the simulation)

input_feeds : dict of {Node: ndarray}

override the values of input Nodes with the given data. arrays should have shape (sim.minibatch_size, n_steps, node.size_out).

Notes

  • This function should not be called directly; run the simulator through Simulator.step(), Simulator.run_steps(), or Simulator.run().
  • The input_feeds argument allows the user to pass several simultaneous input sequences through the model. That is, instead of running the model n times with 1 input at a time, the model can be run once with n inputs at a time. Only the values of input nodes (nodes with no incoming Connections) can be overwritten in this way.
train(inputs, targets, optimizer, n_epochs=1, objective='mse', shuffle=True)[source]

Optimize the trainable parameters of the network using the given optimization method, minimizing the objective value over the given inputs and targets.

Parameters:
inputs : dict of {Node: ndarray}

input values for Nodes in the network; arrays should have shape (batch_size, sim.step_blocks, node.size_out)

targets : dict of {Probe: ndarray}

desired output value at Probes, corresponding to each value in inputs; arrays should have shape (batch_size, sim.step_blocks, probe.size_in)

optimizer : tf.train.Optimizer

Tensorflow optimizer, e.g. tf.train.GradientDescentOptimizer(learning_rate=0.1)

n_epochs : int, optional

run training for the given number of epochs (complete passes through inputs)

objective : "mse" or callable, optional

the objective to be minimized. passing "mse" will train with mean squared error. a custom function f(output, target) -> loss can be passed that consumes the actual output and target output for a probe in targets and returns a tf.Tensor representing the scalar loss value for that Probe (loss will be averaged across Probes).

shuffle : bool, optional

if True, randomize the data into different minibatches each epoch

Notes

  • Deep learning methods require the network to be differentiable, which means that trying to train a network with non-differentiable elements will result in an error. Examples of common non-differentiable elements include LIF, Direct, or processes/neurons that don’t have a custom Tensorflow implementation (see processes.SimProcessBuilder/ neurons.SimNeuronsBuilder)
  • Most Tensorflow optimizers do not have GPU support for networks with sparse reads, which are a common element in Nengo models. If your network contains sparse reads then training will have to be executed on the CPU (by creating the simulator via nengo_dl.Simulator(..., device="/cpu:0")), or is limited to optimizers with GPU support (currently this is only tf.train.GradientDescentOptimizer). Follow this issue for updates on Tensorflow GPU support.
loss(inputs, targets, objective=None)[source]

Compute the loss value for the given objective and inputs/targets.

Parameters:
inputs : dict of {Node: ndarray}

input values for Nodes in the network; arrays should have shape (batch_size, sim.step_blocks, node.size_out)

targets : dict of {Probe: ndarray}

desired output value at Probes, corresponding to each value in inputs; arrays should have shape (batch_size, sim.step_blocks, probe.size_in)

objective : "mse" or callable, optional

the objective used to compute loss. passing "mse" will use mean squared error. a custom function f(output, target) -> loss can be passed that consumes the actual output and target output for a probe in targets and returns a tf.Tensor representing the scalar loss value for that Probe (loss will be averaged across Probes). passing None will use the objective passed to the last call of Simulator.train().

_fill_feed(n_steps, inputs, targets=None, start=0)[source]

Create a feed dictionary containing values for all the placeholder inputs in the network, which will be passed to tf.Session.run.

Parameters:
n_steps : int

the number of execution steps

input_feeds : dict of {Node: ndarray}

override the values of input Nodes with the given data. arrays should have shape (sim.minibatch_size, n_steps, node.size_out).

targets : dict of {Probe: ndarray}, optional

values for target placeholders (only necessary if loss is being computed, e.g. when training the network)

start : int, optional

initial value of simulator timestep

Returns:
dict of {``tf.Tensor``: :class:`~numpy:numpy.ndarray`}

feed values for placeholder tensors in the network

save_params(path)[source]

Save trainable network parameters to the given path.

Parameters:
path : str

filepath of parameter output file

load_params(path)[source]

Load trainable network parameters from the given path.

Parameters:
path : str

filepath of parameter input file

print_params(msg=None)[source]

Print current values of trainable network parameters.

Parameters:
msg : str, optional

title for print output, useful to differentiate multiple print calls

close()[source]

Close the simulation, freeing resources.

Notes

The simulation cannot be restarted after it is closed. This is not a technical limitation, just a design decision made for all Nengo simulators.

trange(dt=None)[source]

Create a vector of times matching probed data.

Note that the range does not start at 0 as one might expect, but at the first timestep (i.e., dt).

Parameters:
dt : float, optional

the sampling period of the probe to create a range for; if None, the simulator’s dt will be used.

check_gradients(atol=0.0001, rtol=0.001)[source]

Perform gradient checks for the network (used to verify that the analytic gradients are correct).

Raises a simulation error if the difference between analytic and numeric gradient is greater than atol + rtol * numeric_grad (elementwise).

Parameters:
atol : float, optional

absolute error tolerance

rtol : float, optional

relative (to numeric grad) error tolerance