Esempio n. 1
0
def test_stateful(Simulator, sim_stateful, func_stateful, func):
    with Network() as net:
        config.configure_settings(stateful=sim_stateful)

        Ensemble(30, 1)

    with Simulator(net) as sim:
        kwargs = dict(n_steps=5, stateful=func_stateful)

        with pytest.warns(None) as recwarns:
            getattr(sim, func)(**kwargs)
        assert sim.n_steps == (5 if func_stateful and sim_stateful else 0)

        if func == "predict" and func_stateful and not sim_stateful:
            # note: we do not get warnings for predict_on_batch/run_steps because
            # they automatically set func_stateful=sim_stateful
            assert (len([
                w
                for w in recwarns if "Ignoring stateful=True" in str(w.message)
            ]) > 0)
        else:
            assert len(recwarns) == 0

        getattr(sim, func)(**kwargs)
        assert sim.n_steps == (10 if func_stateful and sim_stateful else 0)
Esempio n. 2
0
def tensor_layer(input, layer_func, shape_in=None, synapse=None,
                 transform=1, **layer_args):
    """A utility function to construct TensorNodes that apply some function
    to their input (analogous to the ``tf.layers`` syntax).

    Parameters
    ----------
    input : :class:`~nengo:nengo.base.NengoObject`
        object providing input to the layer
    layer_func : callable or :class:`~nengo:nengo.neurons.NeuronType`
        a function that takes the value from ``input`` (represented as a
        ``tf.Tensor``) and maps it to some output value. or a Nengo neuron
        type, defining a nonlinearity that will be applied to ``input``
    shape_in : tuple of int, optional
        if not None, reshape the input to the given shape
    synapse : float or :class:`~nengo:nengo.synapses.Synapse`, optional
        synapse to apply on connection from ``input`` to this layer
    transform : :class:`~numpy:numpy.ndarray`, optional
        transform matrix to apply on connection from ``input`` to this layer
    layer_args : dict, optional
        these arguments will be passed to ``layer_func`` if it is callable, or
        :class:`~nengo:nengo.Ensemble` if ``layer_func`` is a
        :class:`~nengo:nengo.neurons.NeuronType`

    Returns
    -------
    :class:`.TensorNode` or :class:`~nengo:nengo.ensemble.Neurons`
        a TensorNode that implements the given layer function (if
        ``layer_func`` was a callable), or a Neuron object with the given
        neuron type, connected to ``input``
    """

    if isinstance(layer_func, NeuronType):
        node = Ensemble(input.size_out, 1, neuron_type=layer_func,
                        **layer_args).neurons
    else:
        # add (ignored) time input and pass kwargs
        def node_func(_, x):
            return layer_func(x, **layer_args)

        # reshape input if necessary
        if shape_in is not None:
            node_func = reshaped(shape_in)(node_func)

        node = TensorNode(node_func, size_in=input.size_out)

    Connection(input, node, synapse=synapse, transform=transform)

    return node
Esempio n. 3
0
def test_keep_history(Simulator, seed):
    with Network(seed=seed) as net:
        config.configure_settings(keep_history=True)
        a = Ensemble(30, 1)
        p = Probe(a.neurons, synapse=0.1)

    with Simulator(net) as sim:
        sim.run_steps(10)

    with net:
        net.config[p].keep_history = False

    with Simulator(net) as sim2:
        sim2.run_steps(10)

    assert sim.data[p].shape == (10, 30)
    assert sim2.data[p].shape == (1, 30)
    assert np.allclose(sim.data[p][[-1]], sim2.data[p])
Esempio n. 4
0
def test_keep_history(Simulator, use_loop, seed):
    with Network(seed=seed) as net:
        config.configure_settings(keep_history=True, use_loop=use_loop)
        a = Ensemble(30, 1)
        p = Probe(a.neurons, synapse=0.1)

    kwargs = dict() if use_loop else dict(unroll_simulation=10)
    with Simulator(net, **kwargs) as sim:
        sim.run_steps(10)

    with net:
        net.config[p].keep_history = False

    with Simulator(net, **kwargs) as sim2:
        sim2.run_steps(10)

    assert sim.data[p].shape == (10, 30)
    assert sim2.data[p].shape == (1, 30)
    assert np.allclose(sim.data[p][[-1]], sim2.data[p])
Esempio n. 5
0
    def get_ensemble(self, dim, add_to_container=True):
        if self.is_input and self.pairs_per_dim != 1:
            # To support this, we need to figure out how to deal with the
            # `post_inds` that map neurons to axons. Either we can do this
            # on the host, in which case we'd have inputs going to the chip
            # where we can have multiple spikes per axon per timestep, or we
            # need to do it on the chip with one input axon per neuron.
            raise NotImplementedError(
                "Input neurons with more than one neuron per dimension")

        n_neurons = 2 * dim * self.pairs_per_dim
        encoders = np.vstack([np.eye(dim), -np.eye(dim)] * self.pairs_per_dim)
        return Ensemble(
            n_neurons,
            dim,
            neuron_type=SpikingRectifiedLinear(),
            encoders=encoders,
            gain=self.gain.repeat(dim),
            bias=self.bias.repeat(dim),
            add_to_container=add_to_container,
        )
Esempio n. 6
0
    def __call__(
        self,
        input,
        transform=default_transform,
        shape_in=None,
        synapse=None,
        return_conn=False,
        **layer_args
    ):
        """
        Apply the TensorNode layer to the given input object.

        Parameters
        ----------
        input : ``NengoObject``
            Object providing input to the layer.
        transform : `~numpy.ndarray`
            Transform matrix to apply on connection from ``input`` to this layer.
        shape_in : tuple of int
            If not None, reshape the input to the given shape.
        synapse : float or `~nengo.synapses.Synapse`
            Synapse to apply on connection from ``input`` to this layer.
        return_conn : bool
            If True, also return the connection linking this layer to ``input``.
        layer_args : dict
            These arguments will be passed to `.TensorNode` if ``layer_func`` is a
            callable or Keras Layer, or `~nengo.Ensemble` if ``layer_func`` is a
            `~nengo.neurons.NeuronType`.

        Returns
        -------
        obj : `.TensorNode` or `~nengo.ensemble.Neurons`
            A TensorNode that implements the given layer function (if
            ``layer_func`` was a callable/Keras layer), or a Neuron object with the
            given neuron type, connected to ``input``.
        conn : `~nengo.Connection`
            If ``return_conn`` is True, also returns the connection object linking
            ``input`` and ``obj``.

        Notes
        -----
        The input connection created for the new TensorNode will be marked as
        non-trainable by default.
        """

        if shape_in is not None and all(x is not None for x in shape_in):
            size_in = np.prod(shape_in)
        elif isinstance(transform, np.ndarray) and transform.ndim == 2:
            size_in = transform.shape[0]
        else:
            size_in = input.size_out

        if isinstance(self.layer_func, NeuronType):
            obj = Ensemble(
                size_in, 1, neuron_type=self.layer_func, **layer_args
            ).neurons
        else:
            obj = TensorNode(
                self.layer_func,
                shape_in=(size_in,) if shape_in is None else shape_in,
                pass_time=False,
                **layer_args,
            )

        conn = Connection(input, obj, synapse=synapse, transform=transform)

        # set connection to non-trainable
        cfg = Config.context[0][conn]
        if not hasattr(cfg, "trainable"):
            configure_settings(trainable=None)
        cfg.trainable = False

        return (obj, conn) if return_conn else obj
Esempio n. 7
0
from matplotlib.pyplot import plot, show
from nengo import Connection, Ensemble, Network, Node, Probe
# from nengo.utils.simulator import operator_dependency_graph
from nengo_dl import Simulator
from numpy import sin

# define the model
with Network() as model:
    stim = Node(sin)
    a = Ensemble(100, 1)
    b = Ensemble(100, 1)
    Connection(stim, a)
    Connection(a, b, function=lambda x: x**2)

    probe_a = Probe(a, synapse=0.01)
    probe_b = Probe(b, synapse=0.01)

# build and run the model
with Simulator(model) as sim:
    sim.run(10)

# plot the results
plot(sim.trange(), sim.data[probe_a])
plot(sim.trange(), sim.data[probe_b])
show()
Esempio n. 8
0
def tensor_layer(input,
                 layer_func,
                 shape_in=None,
                 synapse=None,
                 transform=1,
                 return_conn=False,
                 **layer_args):
    """A utility function to construct TensorNodes that apply some function
    to their input (analogous to the ``tf.layers`` syntax).

    Parameters
    ----------
    input : ``NengoObject``
        Object providing input to the layer
    layer_func : callable or `~nengo.neurons.NeuronType`
        A function that takes the value from ``input`` (represented as a
        ``tf.Tensor``) and maps it to some output value, or a Nengo neuron
        type, defining a nonlinearity that will be applied to ``input``.
    shape_in : tuple of int
        If not None, reshape the input to the given shape
    synapse : float or `~nengo.synapses.Synapse`
        Synapse to apply on connection from ``input`` to this layer
    transform : `~numpy.ndarray`
        Transform matrix to apply on connection from ``input`` to this layer
    return_conn : bool
        If True, also return the connection linking this layer to ``input``
    layer_args : dict
        These arguments will be passed to ``layer_func`` if it is callable, or
        `~nengo.Ensemble` if ``layer_func`` is a `~nengo.neurons.NeuronType`

    Returns
    -------
    node : `.TensorNode` or `~nengo.ensemble.Neurons`
        A TensorNode that implements the given layer function (if
        ``layer_func`` was a callable), or a Neuron object with the given
        neuron type, connected to ``input``
    conn : `~nengo.Connection`
        If ``return_conn`` is True, also returns the connection object linking
        ``input`` and ``node``.
    """

    if isinstance(transform, np.ndarray) and transform.ndim == 2:
        size_in = transform.shape[0]
    elif shape_in is not None:
        size_in = np.prod(shape_in)
    else:
        size_in = input.size_out

    if isinstance(layer_func, NeuronType):
        node = Ensemble(size_in, 1, neuron_type=layer_func,
                        **layer_args).neurons
    else:
        # add (ignored) time input and pass kwargs
        def node_func(_, x):
            return layer_func(x, **layer_args)

        # reshape input if necessary
        if shape_in is not None:
            node_func = reshaped(shape_in)(node_func)

        node = TensorNode(node_func, size_in=size_in)

    conn = Connection(input, node, synapse=synapse, transform=transform)

    return (node, conn) if return_conn else node