import weakref
from nengo.base import NengoObject, ObjView, ProcessParam
from nengo.dists import DistOrArrayParam, Uniform, UniformHypersphere
from nengo.exceptions import ReadonlyError
from nengo.neurons import LIF, NeuronTypeParam, Direct
from nengo.params import Default, IntParam, NumberParam
[docs]class Ensemble(NengoObject):
"""A group of neurons that collectively represent a vector.
Parameters
----------
n_neurons : int
The number of neurons.
dimensions : int
The number of representational dimensions.
radius : int, optional (Default: 1.0)
The representational radius of the ensemble.
encoders : Distribution or (n_neurons, dimensions) array_like, optional \
(Default: UniformHypersphere(surface=True))
The encoders used to transform from representational space
to neuron space. Each row is a neuron's encoder; each column is a
representational dimension.
intercepts : Distribution or (n_neurons,) array_like, optional \
(Default: ``nengo.dists.Uniform(-1.0, 1.0)``)
The point along each neuron's encoder where its activity is zero. If
``e`` is the neuron's encoder, then the activity will be zero when
``dot(x, e) <= c``, where ``c`` is the given intercept.
max_rates : Distribution or (n_neurons,) array_like, optional \
(Default: ``nengo.dists.Uniform(200, 400)``)
The activity of each neuron when the input signal ``x`` is magnitude 1
and aligned with that neuron's encoder ``e``;
i.e., when ``dot(x, e) = 1``.
eval_points : Distribution or (n_eval_points, dims) array_like, optional \
(Default: ``nengo.dists.UniformHypersphere(surface=True)``)
The evaluation points used for decoder solving, spanning the interval
(-radius, radius) in each dimension, or a distribution from which
to choose evaluation points.
n_eval_points : int, optional (Default: None)
The number of evaluation points to be drawn from the `eval_points`
distribution. If None, then a heuristic is used to determine
the number of evaluation points.
neuron_type : `~nengo.neurons.NeuronType`, optional \
(Default: ``nengo.LIF()``)
The model that simulates all neurons in the ensemble
(see `~nengo.neurons.NeuronType`).
gain : Distribution or (n_neurons,) array_like (Default: None)
The gains associated with each neuron in the ensemble. If None, then
the gain will be solved for using ``max_rates`` and ``intercepts``.
bias : Distribution or (n_neurons,) array_like (Default: None)
The biases associated with each neuron in the ensemble. If None, then
the gain will be solved for using ``max_rates`` and ``intercepts``.
noise : Process, optional (Default: None)
Random noise injected directly into each neuron in the ensemble
as current. A sample is drawn for each individual neuron on
every simulation step.
label : str, optional (Default: None)
A name for the ensemble. Used for debugging and visualization.
seed : int, optional (Default: None)
The seed used for random number generation.
Attributes
----------
bias : Distribution or (n_neurons,) array_like or None
The biases associated with each neuron in the ensemble.
dimensions : int
The number of representational dimensions.
encoders : Distribution or (n_neurons, dimensions) array_like
The encoders, used to transform from representational space
to neuron space. Each row is a neuron's encoder, each column is a
representational dimension.
eval_points : Distribution or (n_eval_points, dims) array_like
The evaluation points used for decoder solving, spanning the interval
(-radius, radius) in each dimension, or a distribution from which
to choose evaluation points.
gain : Distribution or (n_neurons,) array_like or None
The gains associated with each neuron in the ensemble.
intercepts : Distribution or (n_neurons) array_like or None
The point along each neuron's encoder where its activity is zero. If
``e`` is the neuron's encoder, then the activity will be zero when
``dot(x, e) <= c``, where ``c`` is the given intercept.
label : str or None
A name for the ensemble. Used for debugging and visualization.
max_rates : Distribution or (n_neurons,) array_like or None
The activity of each neuron when ``dot(x, e) = 1``,
where ``e`` is the neuron's encoder.
n_eval_points : int or None
The number of evaluation points to be drawn from the `eval_points`
distribution. If None, then a heuristic is used to determine
the number of evaluation points.
n_neurons : int or None
The number of neurons.
neuron_type : NeuronType
The model that simulates all neurons in the ensemble
(see ``nengo.neurons``).
noise : Process or None
Random noise injected directly into each neuron in the ensemble
as current. A sample is drawn for each individual neuron on
every simulation step.
radius : int
The representational radius of the ensemble.
seed : int or None
The seed used for random number generation.
"""
n_neurons = IntParam('n_neurons', default=None, low=1)
dimensions = IntParam('dimensions', default=None, low=1)
radius = NumberParam('radius', default=1.0, low=1e-10)
encoders = DistOrArrayParam('encoders',
default=UniformHypersphere(surface=True),
sample_shape=('n_neurons', 'dimensions'))
intercepts = DistOrArrayParam('intercepts',
default=Uniform(-1.0, 1.0),
optional=True,
sample_shape=('n_neurons',))
max_rates = DistOrArrayParam('max_rates',
default=Uniform(200, 400),
optional=True,
sample_shape=('n_neurons',))
eval_points = DistOrArrayParam('eval_points',
default=UniformHypersphere(),
sample_shape=('*', 'dimensions'))
n_eval_points = IntParam('n_eval_points', default=None, optional=True)
neuron_type = NeuronTypeParam('neuron_type', default=LIF())
gain = DistOrArrayParam('gain',
default=None,
optional=True,
sample_shape=('n_neurons',))
bias = DistOrArrayParam('bias',
default=None,
optional=True,
sample_shape=('n_neurons',))
noise = ProcessParam('noise', default=None, optional=True)
def __init__(self, n_neurons, dimensions, radius=Default, encoders=Default,
intercepts=Default, max_rates=Default, eval_points=Default,
n_eval_points=Default, neuron_type=Default, gain=Default,
bias=Default, noise=Default, label=Default, seed=Default):
super(Ensemble, self).__init__(label=label, seed=seed)
self.n_neurons = n_neurons
self.dimensions = dimensions
self.radius = radius
self.encoders = encoders
self.intercepts = intercepts
self.max_rates = max_rates
self.n_eval_points = n_eval_points
self.eval_points = eval_points
self.bias = bias
self.gain = gain
self.neuron_type = neuron_type
self.noise = noise
self._neurons = Neurons(self)
def __getitem__(self, key):
return ObjView(self, key)
def __len__(self):
return self.dimensions
@property
def neurons(self):
"""A direct interface to the neurons in the ensemble."""
return self._neurons
@neurons.setter
def neurons(self, dummy):
raise ReadonlyError(attr="neurons", obj=self)
@property
def probeable(self):
"""(tuple) Signals that can be probed on an ensemble."""
return ("decoded_output", "input")
@property
def size_in(self):
"""The dimensionality of the ensemble."""
return self.dimensions
@property
def size_out(self):
"""The dimensionality of the ensemble."""
return self.dimensions
[docs]class Neurons(object):
"""An interface for making connections directly to an ensemble's neurons.
This should only ever be accessed through the ``neurons`` attribute of an
ensemble, as a way to signal to `~nengo.Connection` that the connection
should be made directly to the neurons rather than to the ensemble's
decoded value.
"""
def __init__(self, ensemble):
self._ensemble = weakref.ref(ensemble)
def __getitem__(self, key):
return ObjView(self, key)
def __len__(self):
return self.ensemble.n_neurons
def __repr__(self):
return "<Neurons at 0x%x of %r>" % (id(self), self.ensemble)
def __str__(self):
return "<Neurons of %s>" % self.ensemble
@property
def ensemble(self):
"""(Ensemble) The ensemble these neurons are part of."""
return self._ensemble()
@property
def probeable(self):
"""(tuple) Signals that can be probed in the neuron population."""
return ('output', 'input') + self.ensemble.neuron_type.probeable
@property
def size_in(self):
"""(int) The number of neurons in the population."""
if isinstance(self.ensemble.neuron_type, Direct):
# This will prevent users from connecting/probing Direct neurons
# (since there aren't actually any neurons being simulated).
return 0
return self.ensemble.n_neurons
@property
def size_out(self):
"""(int) The number of neurons in the population."""
if isinstance(self.ensemble.neuron_type, Direct):
# This will prevent users from connecting/probing Direct neurons
# (since there aren't actually any neurons being simulated).
return 0
return self.ensemble.n_neurons