-
Notifications
You must be signed in to change notification settings - Fork 174
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes to connection transform simulation #1330
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
I've been thinking about the first change a bit more (omitting identity transformations). It might be a bit too magicky, in that the API is suggesting there is a transform op happening (since the default So, a couple ideas:
I lean towards 3, because it is the most explicit. However, it is the least transparent, since it changes the |
I like option 3, having an explicit "don't apply a transform to this", but I'm not sure exactly what we should do about the Another question is whether we will handle the |
Yeah it's all kind of dependent on how people think about the connection weights. For decoded connections (
the new mental model would be
But in either case For the Node case, the previous mental model was
which in the new model would be
So under this new theoretical mental model you wouldn't expect there to be connection weights on a non-decoded connection if I think the new mental model makes slightly more sense, because it is conditional on the thing that the user sets/interacts with (
My inclination would be to keep the current behaviour, where it works for any N-d -> N-d signal. Perhaps that's another argument for changing the mental model, as previously if you probed the weights on a N-d -> N-d connection you'd get a scalar signal, which doesn't make a lot of sense if you're thinking of that signal as "connection weights".
Yeah that's kind of messy. In the current implementation this is implemented as To provide some further perspective on this, the reason I first started reconsidering this change is because in Sooo maybe the conclusion from all this is that we should just not do this optimization in the reference builder, and leave it up to backends (or a more downstream stage in the refactored builder)? Also, I know I've written a ton of words on this, but that's just because I think it's a kind of interesting/subtle design decision. I'm not actually that passionate about the outcome, whatever we decide. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Not sure what the best thing with regard to the transform is. It is indeed pretty subtle, there seem to be good arguments for all the options, and I haven't thought deeply about it.
I implemented this in the backend and I think it makes the most sense there. You can do more detailed optimizations when you have access to knowledge about the backend anyway, so I think we want the reference builder to focus more on just building a nice, simple, reliable representation, and leave the fancy stuff up to a more downstream system. So I reverted that change, just leaving the synapse/gain change. |
Sounds good, I'll merge shortly. We should move the discussion on transforms to a new issue perhaps? |
Hi, I have some comments regarding change 1 by @drasmuss , i.e. """nengo.Connection(x, ens.neurons) was applying the neural gains before the synapse (synapse(x*gains)), whereas nengo.Connection(x, ens) was applying the gains after the synapse (synapse(x)*gains). This changes it so that the implementation is consistent in both cases (I went with the latter formulation).""" The product and the filtering operations commute if synapse is a linear filter which it usually is being an exponentially decaying filter. So on the face of it, it shouldn't matter how you write this. But learning of weights get screwed up both for the test: nengo/tests/test_learning_rules.py as @drasmuss mentioned and in my simulations! Here I try to outline my understanding of this issue. Please correct me if I am wrong. I have Now the key difference between the two implementations: A) In old Nengo v 2.4.0 i.e. before this change 1, this is what would happen: B) In new Nengo v 2.5.0 i.e. after the change 1, this what happens now: For your ready reference, here's the commit that introduced this: I think the new implementation is the correct one if gains are to be properly taken into account during learning i.e. consistent with the NEF equations as advertized. However, I had already used the old Nengo for extensive simulation for my pre-print. So I had to re-write the equations for the neural current without using the gain \nu on the weights that are being learned. Everything in my pre-print is valid and consistent now, just caused me a low of searching for why learning rates and distributions of neural activity that were working fine before with v2.4.0, suddenly went for a toss with the new version 2.5.0! I've just uploaded the code for the pre-print and README to github https://github.com/adityagilra/FOLLOW. Cheers! |
@Seanny123 Tangentially related to some issues you had, might clear some things up? Especially this line? |
Motivation and context:
Two changes:
nengo.Connection(x, ens.neurons)
was applying the neural gains before the synapse (synapse(x*gains)
), whereasnengo.Connection(x, ens)
was applying the gains after the synapse (synapse(x)*gains
). This changes it so that the implementation is consistent in both cases (I went with the latter formulation).All Connections get created with a default
transform=1
, which has no effect. Forensemble->x
connections this gets rolled into the decoders, but fornode->x
connections we're just doing an unnecessary multiplication by 1 for all those connections. The second commit optimizes those identity multiplications out of the connection builder. (Note: we can't do a similar optimization for identity matrices, because those might be the target of learning rules).How has this been tested?
One of our unit tests failed after the neural gain change, because it was tuned to the previous implementation. I adjusted a parameter slightly to get it to pass again.
How long should this take to review?
Types of changes:
Checklist: