Scaling up simularity

I have been experimenting with modeling the core/belt/parabelt in Nengo but each time I expand the size of the dimensions I seem to have to retune the transforms to keep the data in range. Plus, some suggested options in the combined Ensemble do not scale well such as:


Which requires encoders be tuned for each dimension added

Any suggestions?

Hello and welcome Graeme!

What is the “core/belt/parabelt”? Are you referring to the auditory core, lateral belt, and parabelt cortices in the human superior temporal gyrus? How are you trying to model them? Specifically, what data are you trying to keep in range? It would be helpful if you could post some code showing what you are trying to accomplish.

Thank you Sean

The core/belt/parabelt is a repetitive theme found in all sensory
modalities, the Auditory core, Lateral Belt, and parabelt cortices are
at least one of the versions found in the brain. There is also a version
for vision, etc. The core has direct thalamic input to cortex laminae IV
my theory is that the belt then acts as an early Novelty Detector that
prioritizes the outputs of the core, to direct further processing to the
most novel inputs for hierarchical expansion, in essence gating data in
the parabelt and from the core in a manner that allocates learning

I use similarity as a detection mechanism for detection of Entropy, then
use Negative Activation as a way of biasing for Minimum Entropy. The
idea is to detect Novelty. Which is the Minimum Entropy state, and use
that to allocate learning resources to areas that are not learning
saturated yet. The idea is that this is a inversion of the Maximum
Entropy Principle, I call the theory Mepla for Minimum Entropy Principle
of Learning Allocation.

As an example of how it might work, I am including My
current example. and Figure 1.png the graph for it This is a two input
version, without any clustering etc.

Thanks for your interest

Graeme (2.51 KB)

Understanding your model

I’m going to try and explain what you said back to you to make sure I understand.

There are three cortical sections that seem important. They are the Core, Lateral Belt and Parabelt. You want to model the Lateral Belt as a Novelty Detector of data coming from the Core. You’ve defined Novelty as being the similarity between the Core and the Parabelt, which you’ve modeled as the product between two signals.

What behaviour do you want to initiate once you have this similarity measure? Alternatively, is it the ability to calculate the similarity that you are currently stuck on?

Understanding your code

Looking at your code, there’s a few problems and a few quality of life improvements that could be made. I’ve posted your code below for ease of reference:

import numpy as np
import matplotlib.pyplot as plt
import nengo
from nengo.processes import Piecewise

model = nengo.Network()

with model:

    stim_a = nengo.Node(7.5)
    stim_b = nengo.Node(Piecewise({0: .5, .1: 7.5, .2: .2}))

    # set up the input neurons
    a = nengo.Ensemble(n_neurons=100, dimensions=1, radius=1)
    b = nengo.Ensemble(n_neurons=100, dimensions=1, radius=1)
    c = nengo.Ensemble(n_neurons=100, dimensions=1, radius=1)

    d = nengo.Ensemble(n_neurons=100, dimensions=1, radius=1)
    e = nengo.Ensemble(n_neurons=100, dimensions=1, radius=1)

    # set up the alternate path
    combined = nengo.Ensemble(n_neurons=200, dimensions=2, radius=1.5)
    prod = nengo.Ensemble(n_neurons=100, dimensions=1, radius=1)
    combined.encoders = nengo.dists.Choice([[1, 1], [-1, 1], [1, -1], [-1, -1]])

    nengo.Connection(stim_a, a)
    nengo.Connection(stim_b, b)
    nengo.Connection(stim_a, c)

    # connect the alternate path
    nengo.Connection(a, combined[0])
    nengo.Connection(b, combined[1])

    # connect the input neurons to the 2D neuron
    #  nengo.Connection(c, d[0])
    nengo.Connection(d, e, transform=2.5)

    # connect the Input Node to the alternate pathway
    def product(x):
        return x[0] * x[1]

    # define the product function
    nengo.Connection(combined, prod, transform=-2.5, function=product)
    # connect up the product transform
    threshold = -0.8

    def thresh(x):
        return x[0] - threshold

    # define cross dimensional addition
    # nengo.Connection(prod, d[1])

    nengo.Connection(prod, d, transform=1.5, function=thresh)

    nengo.Connection(c, e, transform=-.14)  # , function=additn)
    # connect up the addition transform
    product_probe = nengo.Probe(prod, synapse=0.01)
    d_probe = nengo.Probe(d, synapse=0.01)
    e_probe = nengo.Probe(e, synapse=0.01)

# set up the probes to gather data
with nengo.Simulator(model) as sim:
    # set up the simulator run

# save the probes as txt type data files
plt.plot(sim.trange(),[product_probe], label='product')
plt.plot(sim.trange(),[d_probe], label='d output')
plt.plot(sim.trange(),[e_probe], label='e output')

What exactly are the inputs and outputs that you’re expecting from this network and how are they differing from what you’re currently getting?

Even without totally understanding what’s happening in the code, there’s a few quirks worth noting. In the code, you’re using a custom product ensemble, but may I suggest using nengo.networks.Product instead? Additionally, you seem to want a to have a similarity threshold for some decision to be made. Your current implementation won’t work as you expect and I recommend instead using the configuration shown in this example. Finally, your inputs 7.5 and 7.5 greatly exceed the radius of the ensemble they are feeding into and might be the source of some of your confusion. These inputs are going to saturate the neural ensembles and are instead going to represent something around 1.2 instead of 7.5.

Bonus tips

One last thing. I’m a bit surprised you’re doing manual plotting. Have you tried using the Nengo GUI for exploring your model?

I must admit that I don’t understand everything about the models I am
trying to use, I just barely managed to get the graphics running on this
machine, the version that I have is without the NEF front-end menu to
load the gui. I can probably rig it, but it is flakey on loading the
simulator for me, something about having two different browsers both
trying to interface with it, the default is evolution on my machine and
it took me a while to find a copy of firefox that would load. When I
load the gui, It automatically tries to load evolution, and I have to
interfere with that by loading firefox right afterwords or it gives me a
dummy simulator and won’t compile my code, it is much more reasonable to
do my work with python which works every time.


Ok, I have had time to review and experiment with your advice, for instance the problem with nengo.networks.Product() is that it demands a single vector when I want to compare vectors. I did away with the nengo.dists.Choice() line with no noticeable negative effects which goes a long way towards making the algorithm scalable, and I have already scaled it up to three dimensions, and tuned it with smaller transforms etc.

On the inputs, once I had them in range, the results became much tighter to tune. But it still requires custom tuning each time I scale the system larger. On the outputs: I want a negative value that is thresholdable, for gating purposes on d, and a fairly representative version of a after gating. I could probably use some help on implementing threshold if only because I was guessing how to implement it and this is the best mechanism I could find. None of the core mechanisms allow a threshold variable to be set, and I am not yet familiar with all the other functions, and I can still not load the library.

Actually I noted an error in your assumption of what I was trying to do, I am not comparing the core and parabelt, I am comparing core values, and gating them in the parabelt

Rats, I made a mistake in the last posting, I want e to be a mirror image of A (with a negative value)

I have to admit, that I missed your threshold example. However when I tried it, I found it wasn’t tuned for Negative Logic it assumes that the high value is the one I want to threshold for not the negative value. In a tonic inhibition mechanism you want to threshold for the negative value that is largest, not the values that are above the threshold.


FYI, you can edit your posts in this forum by clicking the three dots beside “reply” and then clicking the pencil icon.

I’m still not clear on what you’re trying to achieve. Would it be possible to draw a block diagram showing the various inputs and outputs? Alternatively, would you want to hop onto a video call to discuss this more quickly?

Ok, I will try to send you a graphic I made up that describes the basic network. I’d go on a video call, if I could, but my system is very buggy and lags excessively. What I want to do first is expand the input range to at least 30 inputs and still manage to compare the vectors for each input using something like a dot product that will detect similarity. This then will go through an additive inversion to change the similarity detector into a Novelty detector, then I want to use the output from that calculation to gate a copy of the A input so that detection of novelty releases a copy of the A input. It’s a simple circuit just complicated by scaling up to 30 inputs and a problem I am now having trying to get the gating mechanism to propagate. I am embarrassed that it is so simple.

Seanny123 Reviewer
May 14

I’m still not clear on what you’re trying to achieve. Would it be
possible to draw a block diagram showing the various inputs and
outputs? Alternatively, would you want to hop onto a video call to
discuss this more quickly?

Thanks for drawing the diagram. It really helped me understand what you’re working towards!

What do you mean by inputs ? From what I can tell there’s two inputs in your current network. Are input A and input B gating each other in the full network? If you added an input C, would it be added to the combination of A and B? Would it just be gated by the product of A and B?

Actually no, it adds it’s own product so I am comparing multiple entries at once I am uploading a new version of with 3 inputs to illustrate (I have commented out the hand plotting lines so that it will load in the nengo_gui version of the program. I am not sure I have the best version of this, but it outputs a mirror image of A once it is in the right sector of the graph. I will also output the latest version of figure1 which tracks the outputs of the neurons output of the whole circuit is in E[dot_product scaled up to 3 inputs (2.5 KB)

The diagram appears to have disappeared. Would you mind re-uploading it?

As you will notice, the drawing is of the old non-scaled version of the program scaling it up to three inputs still works, but I have yet to make six inputs work. I am also trying to scale it up to six outputs but the simulation takes time between updates.

I think I have been simulating simularity wrongly, I was confused because I knew that there were only two laminae in the belt cortex that I absolutely needed to implement. Nengo doesn’t separate out laminae so I assumed that I needed to implement it in two ensembles, but now I think I need to implement it in three different types of ensembles. The spare type of ensemble is needed because there are two functions of the combined ensemble that don’t fit together in a single ensemble as far as I know. It’s a limitation of the model, and natural neurons can probably mix functions easier. Instead of trying to make it all into a single simularity detector, I have to string multiple simularity detectors of only 2 dimensions together using an additive function.

Ok, I heard about cosine similarity, and tried it because the dot product was too quick to get out of range, It seems better and the transforms do not need to be as large. I can’t do it now, but I will update the three input version in a bit. (3.4 KB)