-
Notifications
You must be signed in to change notification settings - Fork 3
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
Table look-up #1
Comments
An inevitable problem with your approach is that there is currently no way to implement your table into the C code created by JiTC*DE. At first glance, addressing this seems like a major difficulty (compared to which your symbolic issues are peanuts). Moreover, I consider applications of this very limited (see below), so I am strongly leaning towards not implementing something like this. To somewhat expand on the latter: One of the main reasons for existence of JiTC*DE is to avoid the look-ups of coupling matrices, since those are usually comparably expensive, in particular if the coupling matrices are sparse. More generally, the JiTC*DE way of dealing with tables is to hard-code them. In a related manner, JiTC*DE exist to make computing the derivative (right-hand side of the differential equation) as fast as possible, because that’s very often the bottle-neck. If the derivative includes some complex table look-up, which is the actual main bottle-neck, we are entering a different category of problem for which JiTC*DE wasn’t designed. Now, I am aware that this argument doesn’t fully translate to your application, but it may illustrate why what you want to do does not fit well into the general architecture of JiTC*DE. Another problem with implementing your table as it is, is that the outcome depends on your system’s state in a non-continuous manner – which integrators don’t like at all. With all that being said, here are some general approaches to solving your problem that I can think of:
|
Thanks for the response @Wrzlprmft, you are the MVP! Just if interested, this is how the "table look-up" looks like. The inputs mu_I and std_I are computed in each timestep as a result of continuous dynamics (DDE) and from these the firing rate is approximated using the table (again, instead of solving Fokker-Planck equation for mean-field approximation). As for the proposed solutions:
That's nice of you, but I would lose the speed I am getting from using
Of this I thought, maybe I'd resort for it. I have some experience with Gaussian Processes, but even if I would train one "off-line" (i.e. before jitting the integration), then the prediction (i.e. getting the actual value of firing rate during the integration) using the trained hyperparameters rely on complicated algebra like Cholesky decomposition and solving matrix equations. Symbolic regression might be the way to go, albeit I never used it and have no experience with it.
Unfortunately, not the case. Table lookups are done in each time-step and as you can see from the plot, they might jump.
Unfortunately, they are DDE (with noise, but I can precompute it -- I am using Ornstein-Uhlenbeck process as noisy input)
This I used (and actually asked about it in the |
Well, if you have your table look-up in an efficient Python function, the proposed change would allow you to call this function from a JiTC*DE derivative. Python would only act as an interface here. This would of course cause a little overhead, but it should not be too bad. If this is truly relevant to speed, one could also intercept the C code created by JiTC*DE and plug your table look-up into it. It’s a bit messy (but I can help you with it), but certainly easier than to provide a general-purpose solution that is more efficient than the proposed Python function calls.
From your diagram, I would strongly recommend it. This does not look utterly complicated and if it works, the result is probably considerably faster than your table look-up. The main annoyance will be the periodic discontinuity (so I wouldn’t make this part of the symbolic regression at first), but that will be a problem either way. Symbolic regression is capable of reconstructing the Bethe–Weizsäcker formula from data; I am quite confident that it can handle your problem.
I think you got the idea. Anyway, looking at your data, this probably cannot be applied here. |
@jajcayn: Have you made any progress with this? I am mainly asking because calling Python functions in the derivative is on my to-do list anyway, but if you have a use for it, it is no problem to prioritise it. |
Hey sorry, for the delayed response. So in the end, I must say, I will be really glad for evaluating python function within the symbolic derivatives :) for the time being, I am still using old All-in-all, if you plan on working on python function within jited derivatives, I'd be grateful and I definitely try them out! Thanks! |
Callbacks from the derivative are now implemented. Please read the respective documentation (search for callback), get the latest version of JiTC*DE from GitHub, and tell me whether everything works for you. |
Hey @Wrzlprmft, wonderful! Thank you very much! τ = 15
n = 10
β = 0.25
γ = 0.1
f = [β * y(0, t - τ) / (1 + y(0, t - τ) ** n) - γ * y(0) / 2.0 * y(0)]
DDE = jitcdde(f, callback_functions=())
DDE.constant_past([1.0])
DDE.step_on_discontinuities()
data = []
for time in numpy.arange(DDE.t, DDE.t+500, 10):
data.append( DDE.integrate(time) )
plt.plot(data) then played the game that the last guy in the equation ( def func(y, factor, gamma):
return y[0] * factor * gamma
callback = se.Function("callback")
# when calling callback in derivatives definition, I omit the state vector as the mandatory first argument, is that correct?
f = [β * y(0, t - τ) / (1 + y(0, t - τ) ** n) - callback(y(0) / 2.0, γ)]
DDE = jitcdde(f, callback_functions=[(callback, func, 2)], verbose=True)
DDE.constant_past([1.0])
DDE.step_on_discontinuities()
data = []
for time in numpy.arange(DDE.t, DDE.t + 500, 10):
data.append(DDE.integrate(time))
plt.plot(data) and it works nicely. I tried to imitate my use case when each neural mass within the network will have three callback functions: each callback will be a table lookup (with different tables, that's why three) taking two arguments: I'll try to implement the full network of neural masses using the callbacks in the evening. Thanks again, I'll let you know whether I succeed with full network implementation. |
Just checking: You added that
Yes.
Apart from not being Mackey–Glass anymore, yes. The two scripts should be equivalent. (I suppose you already checked that they produce the same output, so I will not double-check.)
That should be enough – unless you want to do something that requires the derivative of the f, e.g. computing Lyapunov exponents. Then things get a bit more tricky. |
Yes, I added division by the scripts are indeed equivalent, both yield the same integrated time-series. I also successfully implement table lookup in my neural models, everything works as expected:) thanks again, I think you can close the issue. |
Hey again :)
Not sure whether this should come here or to specific jitc*de I am using, but I feel it is a general question / problem.
So, I would need to make a table look-up as part of my dynamics. The thing is I am using a model (mean-field approximation of spiking neuron model) which uses pre-computed quantities in order to avoid solving Fokker-Planck equation each time step. So this table "converts" mean and standard deviation of membrane potential into firing rate. You can imagine it as
The problem is, of course, that the indices
x_idx
andy_idx
are symbolic. Just to make a pointx_idx
isSo what I tried:
symengine.Lambdify
the code is roughly as this:
so I need to define Matrix as a symbol and lambdify it in order to get correct indices for a table lookup. However, this is not working as
Then I found out that
MatrxSymbol
is not implemented insymengine
and nobody knows if and when they'd implement it (I've spent an afternoon searching their github issues)Use sympy's fallback symbols
y
andt
so the other option was to use "slow"
sympy
(still faster I guess than pure python) and instead ofI did
unfortunately, this is not working as this time I am getting
unrelated to the table lookup and this is an earlier error, which means that
sympy
is not really fully compatible withsymenigne
sincesymengine
has no problems in determining the truth value ofRelational
...However, the problem is that in order to work this with
sympy
I would need to rewrite almost all integration logic which then would become unusable withsymengine
... Since this is the only model I am having problem implementing injitc*de
I really do not want to rewrite the core logic to be compatible withsympy
, I am more than happy withsymengine
.I guess you're not an expert on
symengine
but the main question is whether you have some idea how you would do symbolic table lookup, given thatsymengine
does not implement 2D symbolic arrays? Should I somehow approximate the table with a function?Thanks a lot!
N.
The text was updated successfully, but these errors were encountered: