Open jogama opened 4 years ago
We changed the behaviour of the nengo.Sigmoid
neurons in Nengo v2.4.0 to more accurately reflect the Sigmoid function.
To make this example work with the latest Nengo release:
Change the way the learning rule is created (I think you have already done this):
conn.learning_rule_type={'my_pes': nengo.PES()}
conn.learning_rule_type['my_pes'].learning_rate = 1e-4
to
conn.learning_rule_type={'my_pes': nengo.PES(learning_rate = 1e-4)}
Change the tau_ref
of the Sigmoid neuron from 0.002
to 0.0025
.
neuron_mode = nengo.Sigmoid(tau_ref=0.002)
to
neuron_mode = nengo.Sigmoid(tau_ref=0.0025)
For both the input
and error
ensembles, set custom intercepts
and max_rates
values. The values below have been tested to perform reasonably well. Change
input = nengo.Ensemble(N*D_inp, dimensions=D_inp, neuron_type=neuron_mode, label="input")
...
error = nengo.Ensemble(N*D_out, dimensions=D_out, neuron_type=neuron_mode, label="error")
to
input = nengo.Ensemble(N*D_inp, dimensions=D_inp, neuron_type=neuron_mode,
intercepts=Uniform(0.25, 1), max_rates=Uniform(350, 400), label="input")
...
error = nengo.Ensemble(N*D_out, dimensions=D_out, neuron_type=neuron_mode,
intercepts=Uniform(0.25, 1), max_rates=Uniform(350, 400), label="error")
For the inhibitory connection to the error
ensemble, increase the inhibitory weight on the transform. This is to ensure that the error
ensemble is fully inhibited. Change
nengo.Connection(inhib, error.neurons, transform=[[-1]] * error.n_neurons)
to
nengo.Connection(inhib, error.neurons, transform=[[-10]] * error.n_neurons)
Now, a deeper dive as to why the change to the Sigmoid neuron is required. From Nengo v2.4.0 onwards, the inflection point of the Sigmoid neuron (i.e., where the neuron's intercept is on the x-axis) also corresponds to having a firing rate half that of it's maximum firing rate (i.e., 1/tau_ref
).
What does this mean in terms of its effect on the notebook? First, for ensembles using the Nengo defaults, this means that for a Sigmoid neuron ensemble, there are a few constraints:
x = 1
is the max_rate
value provided to the ensemble (note: this is different from the maximum firing rate of the neuron, which is 1/tau_ref
). The maximum firing rate of the neuron must be equal to or exceed this value.x = intercept
.0.5/tau_ref
.The default for Nengo ensembles is to have neurons with max_rates
of 200-400 Hz. From constraint 1, 1/tau_ref >= 400
. Combining this with constraint 3, the firing rate at the inflection point 0.5/tau_ref >= 400
. However constraint 4 sets the effective minimum max_rate
value for that neuron to 0.5/tau_ref <= 200
. Solving all of these constraints leads to the result that tau_ref = 1/400
. This is why tau_ref
is changed from 0.002
to 0.0025
.
Constraint 2 and 3, also mean that with the current Sigmoid neurons, the firing rate of the neurons at x = -1
may be quite high. Since we want neuron response curves that have a decent range of firing rates, the input
and error
populations have their max_rates
and intercepts
shifted in order to accomplish this. You can use the response curve plotting code (i.e., p0.plot(*response_curves(input, sim))
) to investigate the effect changing the max_rates
and intercepts
values have on the response curves of the neurons. This change can also be applied to the other neural populations (answer
, actual_error
), however the input
and error
populations are the most crucial as they are the ones directly involved in the learning.
Thank you so much for the detailed response! This is a great starting point and will keep me busy for some time. Everything works on my computer with the above mentioned python2 environment. Some of the graphs are somewhat different, but XOR is learned.
Hello,
I came here via the standard neural nets in https://www.nengo.ai/examples/
I first saw
Fixing that, I saw
I'll probably either continue fixing this, or (more likely) try to figure out what version of nengo works with this code and install under a pyenv. In either case, would you want a pull request? Could you provide some advice for either case?
In any case, thank you for providing these examples.
This is my current environment: