-
Notifications
You must be signed in to change notification settings - Fork 147
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
Allowing additional arguments to function being differentiated #32
Comments
In which cases is it not possible to achieve this behavior by using a closure? |
I am using it inside an optimization problem (through MathProgBase), The I could construct Giuseppe Ragusa On Wed, Aug 5, 2015 at 4:05 PM, Miles Lubin [email protected]
|
I might be misunderstanding, but does it help that the new API allows one to easily take derivatives/gradients/etc. at the provided point without having to build a closure first? For example, using the old API, you have to construct julia> using ForwardDiff
julia> f(x) = sin(x[1]) + cos(x[2])^2 + tan(x[3])^3
f (generic function with 1 method)
julia> g = forwarddiff_gradient(f, Float64)
gradf (generic function with 2 methods)
julia> g([1.0,2.0,3.0])
3-element Array{Float64,1}:
0.540302
0.756802
0.0621972 Using the new API, you can simply perform the evaluation julia> using ForwardDiff
julia> f(x) = sin(x[1]) + cos(x[2])^2 + tan(x[3])^3
f (generic function with 1 method)
julia> gradient(f, [1.0, 2.0, 3.0])
3-element Array{Float64,1}:
0.540302
0.756802
0.0621972 Similar methods exist for Jacobians/Hessians/etc. The tentative documentation for the new API can be found in the README of #27's branch. |
The new API is great. But it is still not up to the task for the sort of problems I am dealing with. To be more concrete, I tried to make a simple example where passing down argument is necessary. I have a function,
The Jacobian with respect to With the new API I can use
which gives
where the 3x6 block is
In this case, The things get worse since I am also interested to the hessian of the following function
This is sparse as the second derivtives wrt to If I do
Since in my use case Both |
Not necessarily, and why not create the closure once instead of at each iteration? |
Because, for instance, Probably I my resolve the issue by looking at advanced closures alternatives #102. |
Do you have any benchmarks showing the performance difference here? |
Not off-hand --- I changed completely the interface to avoid globals --- but I remember getting a ~5x speedup plus a reduction in memory allocation using my hacked ForwardDiff API (that allows extra argument). |
Were you using globals or closures? |
Globals. I thought that the closure performance hit is (or used to be?) large. |
Not nearly as bad as using globals. If you can put together a realistic but small benchmark, I think that would help sort out the issues here. |
I just pushed a branch that extends the API to allow for targeting specific arguments. It was quite a fun little problem to try to solve generically. Scroll down to the bottom of the README for the new stuff. I didn't want to add this to #27 yet, because I haven't developed good tests for it. I believe that the strategy I'm using can be implemented such that there is no (or very little) loss of performance due to the generalization. It's very possible that what I just pushed will be that fast, but I need to do to some more rigorous performance comparisons before I make any claims. My guess is that the main performance hit for the Finally, |
@jrevels this looks outstanding. I will try it soon. I will contribute with extensive performance testing. |
@gragusa Awesome, thanks! Also, remember - since I don't have automated tests for it yet, there are probably bugs that may or may not actually throw errors. Silent bugs could corrupt your results without any warning, so be wary of results you get from that branch for the time being. |
I can help with testing. Do you have anything in mind? Adjusting the old
|
Pretty much. Like I mentioned, The things that immediately come to mind that need to be tested for
TBH, properly building the fuzzer mentioned in 1) would be a task that might even be worthy of its own package. 3) is something that could be done basically immediately, however, and I'd love to see the results. |
I made a package for the fuzzer here. It may take a while before I can start work on it, but at least now there's a centralized place to make contributions to. |
@jrevels I was starting on helping with test and performing with benchmark of the wrt-feature branch, but the branch does not merge nicely anymore --- you have done way to much work in the last week. I looked at the code and it seems that your changes are still compatible with your work on the wrt feature. Are they? |
This feature is still possible given the new underlying structure, but a lot has changed so it wouldn't just be a straight port (the strategy would essentially be the same, though). The Currently, fleshing out our benchmarks and resolving #37 are higher priority than this, since those may change how we implement the |
Now that #37 is resolved, I've revisited this idea, and I think that telling users to make closures is the way to go here. It's a much simpler solution than trying to incorporate this feature into ForwardDiff's API. Feel free to continue to discuss this, but for now, I'm going to close the issue. To give an explicit example, here's a potential way in which a user should accomplish this: # I have some function f(x, y, z)
# I want to take the gradient of f with respect to y
const my_cache = ForwardDiffCache()
g_y(x, y, z) = ForwardDiff.gradient(n -> f(x, n, z), y, cache=my_cache) Obviously, there may be more performant ways of doing the above if you're looping over different If there are still performance concerns with anonymous closures, then this issue could be reopened is depending on what we see from benchmarks/profiling examples. In general, however, I feel like effort to fix closure concerns should be focused on improving Base rather than hacking around the problem in ForwardDiff. |
I am re-opening this issue, with a justification and explanation found at the bottom of #77. |
I have being using ForwardDiff.jl for a while. My use case is a little bit different as I need to differentiate
f(x, args...)
only with respect tox
. Of source, in typical usage this can be accomplished by closure. By in some instances it is not possible.I locally extended the api to allow
args...
to be passed down down (see, e.g., here).I have been following the work on #27 (which is great by the way) and I was wondering whether either such extension would be possible or whether the new API will allow additional arguments.
The text was updated successfully, but these errors were encountered: