How to change input of a model depending on the state of the model

I’m trying to make a nengo_spa model that solves simple arithmetic tasts like 2+3 = ?

I have a randomly generated list of tasks that I would like to train/run the model on. So every time the model finishes one task (which is associated with a “Done” action) I want to give it the next task.

But each task takes a different amount of time to run (some may take 10x longer than others), and I don’t want to make the model wait for the same amount of time regardless of how long the task actually was because that would waste a lot of time running it.

Is there any way to change the input of the model while it’s running?

Hi,

I don’t have the time right now to give you a full example, but you probably want to take a look the Transcode module. It is similar to a nengo.Node, but aware of Semantic Pointers. You can feed you “Done” pointer/signal into it and define a function that, based on this signal, changes the output of the Transcode module. The output of the Transcode module would become what is currently your input to the model.

There is also an example of Transcode in the documentation, though it doesn’t explicitly cover your use case.

I hope that helps already a little bit.

Hmm fair enough, I haven’t thought of using transcode to store state like that.

Thanks for the suggestion! :slight_smile:

Ok, so this ended up working pretty well. But it’s a bit convoluted so I’ll post my implementation here in case anybody else ends up needing to do the same thing.

# A list of inputs to cycle through.
inputs = [
  'Input_1',
  'Input_2',
  # ... add as many as you need
]

# Set this to +1 when you want the next input, and to -1 when you don't.
next_input_switch = Scalar(n_neurons=4)

# Store some global data for every input to the model. This example has 1 model input per problem, but if you have more you need to have an array of these for every input.
previously_done = True
cursor = 0

# A function for Transcode. Again, if your model has more than 1 input, you probably need a separate function for each one.
def get_input(next_input_signal_value):
  if not previously_done and next_input_signal_value > 0.8:
    cursor = (cursor + 1) % len(inputs) # Wraparound. Maybe you wan't this, maybe not.
    previously_done = True
  elif next_input_signal_value < -0.8: # It's important to have a threshold both for setting and resetting previously_done.
    previously_done = False
  return problems[cursor]

# You can extract the current input from this Transcode.
problem_input = Transcode(get_input, size_in=1, vocab_out=YOUR_INPUT_VOCAB)
Connection(next_input_switch .output, problem_input.input)

# Later on..
with ActionSelection() as action_selection:
  ifmax('Done',
    dot(model_state, sym.Done),
      +1 >> next_input_switch)
  ifmax('Every other action',
    ...,
      -1 >> next_input_switch)