The basal ganglia

The basal ganglia according to Stewart 2010 is an action selector that chooses whatever action has the best “salience” or “goodness”. Its really interesting behaviour manifests itself when it interacts with the thalamus and other components of the brain, but in this example we will only show the basal ganglia’s basic behaviour. It will choose between three actions that we’ll pretend are “eating”, “sleeping” and “playing”.

[1]:
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

import nengo

Step 1: Create the Network

Here we create the basal ganglia and the action input node.

[2]:
model = nengo.Network(label='Basal Ganglia')
with model:
    basal_ganglia = nengo.networks.BasalGanglia(dimensions=3)


class ActionIterator:
    def __init__(self, dimensions):
        self.actions = np.ones(dimensions) * 0.1

    def step(self, t):
        # one action at time dominates
        dominate = int(t % 3)
        self.actions[:] = 0.1
        self.actions[dominate] = 0.8
        return self.actions


action_iterator = ActionIterator(dimensions=3)

with model:
    actions = nengo.Node(action_iterator.step, label="actions")
/mnt/d/Documents/nengo-repos/nengo/nengo/networks/actionselection.py:182: UserWarning: SciPy is not installed, so BasalGanglia will use the default decoder solver. Installing SciPy may improve BasalGanglia performance.
  "SciPy is not installed, so BasalGanglia will "

Step 2: Connect the Network

Connect the input to the basal ganglia and connect the probes

[3]:
with model:
    nengo.Connection(actions, basal_ganglia.input, synapse=None)
    selected_action = nengo.Probe(basal_ganglia.output, synapse=0.01)
    input_actions = nengo.Probe(actions, synapse=0.01)

Step 3: Simulate the Network and Plot the Results

[4]:
with nengo.Simulator(model) as sim:
    # This will take a while
    sim.run(6)
/mnt/d/Documents/nengo-repos/nengo/nengo/builder/optimizer.py:639: UserWarning: Skipping some optimization steps because SciPy is not installed. Installing SciPy may result in faster simulations.
  "Skipping some optimization steps because SciPy is "
[5]:
plt.figure()
plt.subplot(2, 1, 1)
plt.plot(sim.trange(), sim.data[input_actions].argmax(axis=1))
plt.ylim(-0.1, 2.1)
plt.xlabel('time [s]')
plt.title("Index of actual max value")
plt.subplot(2, 1, 2)
plt.plot(sim.trange(), sim.data[selected_action].argmax(axis=1))
plt.ylim(-0.1, 2.1)
plt.xlabel('time [s]')
plt.title("Basal ganglia selected max value")
plt.tight_layout()
../../_images/examples_networks_basal-ganglia_8_0.png

As expected, the maximum index is found at 0, then 1, then 2 or “eating”, “sleeping”, then “playing”. Note that if you zoom in enough on the basal ganglia values, you’ll be able to see a bit of a delay between finding max values. If you read the aforementioned paper, you’ll see that this is expected and matches previous experiments.