nengo / nengo-loihi

Run Nengo models on Intel's Loihi chip
https://www.nengo.ai/nengo-loihi/
Other
35 stars 12 forks source link

Differing oscillator behaviour with `weights=True` vs `weights=False` #90

Open xchoo opened 6 years ago

xchoo commented 6 years ago

So, I was playing around with the oscillator example from the loihi documentation. I noticed that the bevahiour of the oscillator was different between using weights=True and weights=False when you specify the solver manually.

The code is as follows (note, there is no nengo_loihi.set_defaults() being used here).

import nengo
import nengo_loihi

with nengo.Network(seed=12314) as model:
    ens = nengo.Ensemble(200, dimensions=2)

    def kick_func(t):
        if t < 0.1:
            return [1, 0]
        else:
            return [0, 0]

    kick = nengo.Node(kick_func)
    nengo.Connection(kick, ens)

    speed = 1.5
    nengo.Connection(ens, ens, transform=[[1.0, speed],
                                          [-speed, 1.0]],
                     synapse=0.1,
                     solver=nengo.solvers.LstsqL2(weights=True))
    p1 = nengo.Probe(ens, synapse=0.01)

with nengo_loihi.Simulator(model, precompute=False) as sim:
    sim.run(10)

import matplotlib.pyplot as plt
plt.figure()
plt.plot(sim.data[p1][:, 0], sim.data[p1][:, 1])
plt.xlim([-1, 1])
plt.ylim([-1, 1])
plt.show()
xchoo commented 6 years ago

And the graphs for nengo_loihi (using the emulator). When weights=True, notice that the oscillator quickly collapses back to the (approx) 0,0 point. osc_1 osc_2

xchoo commented 6 years ago

And the corresponding cases with normal nengo: osc_4 osc_3

xchoo commented 6 years ago

And finally, the same plots on actual loihi hardward: osc_5 osc_6

hunse commented 6 years ago

Just a guess, but could be because the synaptic filter on the recurrent connection isn't being applied. This may be fixed by one of the PRs in the queue. I'll look more when I'm back at my machine.

On Wed, Sep 26, 2018, 10:51 xchoo notifications@github.com wrote:

And finally, the same plots on actual loihi hardward: [image: osc_5] https://user-images.githubusercontent.com/1971583/46088159-d1364b00-c179-11e8-95cd-2e701f8e9841.png [image: osc_6] https://user-images.githubusercontent.com/1971583/46088160-d3000e80-c179-11e8-97c5-ddd1575448dd.png

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/nengo/nengo-loihi/issues/90#issuecomment-424744580, or mute the thread https://github.com/notifications/unsubscribe-auth/AB3J-iLBwnKLlPLZt3tN7Bj7c084t4Ebks5ue5R5gaJpZM4W60ET .

hunse commented 6 years ago

It turns out the synaptic filter isn't the problem. It could be that using both weights and encoders causes one or the other to not get scaled well, but I haven't been able to work around that (I tried changing max rates/intercepts, and having an ensemble input the kick using weights so that the recurrent ensemble only has weights in).

Anyway, I agree that this is a good reason to hold off making weights=True the default.

tcstewar commented 6 years ago

Anyway, I agree that this is a good reason to hold off making weights=True the default.

I definitely agree. :)

Any ideas about other ways of improving this oscillator? In particular, it's a lot more square than expected.... I don't know if adjusting inter_n and inter_rate might help, but that's the only thing that's coming to mind for me....

arvoelke commented 6 years ago

Note that the example at the top no longer works on the current master branch (0.4.0-dev, fe611a1e484cda1b667d5283e7b488f6fe9547b4), with the error BuildError: Cannot change tau_s on already configured neurons (also see #94).

I ran a git bisect and it gave me:

3b6311d82cf4e78a6220ba1c03bba0c1039022eb is the first bad commit
commit 3b6311d82cf4e78a6220ba1c03bba0c1039022eb
Author: Eric Hunsberger <erichuns@gmail.com>
Date:   Tue Sep 4 15:54:04 2018 -0400

    Connections to ensembles have proper synapse

    This fixes (for example) neuron->ensemble connections
    (of which we currently have no test cases).

    This commit also includes some fixes for tests affected
    by this change.

which is from PR #45 (not PR #95), merged 5 days ago.

To circument this error, modify the first connection to nengo.Connection(kick, ens, synapse=0.1).

hunse commented 6 years ago

This is mostly fixed by #124. Now, you get something like this when running the script at the top. (I did make two changes to the script. One is to use nengo_loihi.set_defaults(). Basically, you always have to call this function, or at least set the intercepts so they don't go too close to 1. The exact value depends on the network, but intercepts close to 1 means high gains which means large weights which means we scale our weight range to accommodate those outliers and miss the important stuff. The other change was minor, just increasing the probe filter to 0.03.) oscillator_defaults

Interestingly, I can get even better accuracy by not calling nengo_loihi.set_defaults(), but only setting the intercepts to Uniform(-1, 0.5) instead. oscillator_05

EDIT: I figured out the reason the second one looks better is just that the oscillator speed is quite high in the original script, so the lower-firing-rate neurons can't handle it. Decreasing the speed allows the model to work fine with nengo_loihi.set_defaults().

arvoelke commented 6 years ago

Interestingly, I can get even better accuracy by not calling nengo_loihi.set_defaults(), but only setting the intercepts to Uniform(-1, 0.5) instead.

Is there any reason this is not the default range for set_defaults rather than (-0.5, 0.5)? Anecdotally, I've found that having neurons with broad coverage (intercepts closer to -1) improves the quality of linear function approximation, which is needed for dynamical systems such as the integrator / oscillator.

Edit: Nevermind, just noticed this is addressed by #126. :)

Both results here and in #124 are looking really good by the way!

tcstewar commented 6 years ago

Is there any reason this is not the default range for set_defaults rather than (-0.5, 0.5)?

Not really. I did some exploration of this in #69 but only for the feed-forward case, and ended up arguing for (-1, 0.95) as a good range.

Also, in that PR I specifically did not want to go the set_defaults route, because that doesn't help for any model that sets the intercepts value itself (for example, any WTA circuit, or the basal ganglia model -- so a large proportion of the nengo_benchmarks). Instead, since this is about hardware-specific discretization issues, I believe this sort of thing should get handled in the builder, and the builder is free to not give exactly the same intercepts range that the user has asked for, if that would help with the discretization process.