ForwardDiff gradient with additional parameters

I am trying to use ForwardDiff.gradient on a function that takes arguments at which the gradient should be taken, as well as data. For example

using Distributions, ForwardDiff
srand(1)
D = rand(Normal(5.0, 1.0), 10)

f(x, D) = loglikelihood(Normal(x[1], x[2]), D)

I would like to take the gradient of f wrt x, using data D. I can “hack” this by setting D as a global parameter e.g.

using Distributions, ForwardDiff
srand(1)
D = rand(Normal(5.0, 1.0), 10)

f(x) = loglikelihood(Normal(x[1], x[2]), D)
ForwardDiff.gradient(f, [5.0, 1.0])

But I don’t like this code for more general usage. What I’d like to do is something along the lines of

g(x, D) = loglikelihood(Normal(x[1], x[2]), D)
ForwardDiff.gradient(g, [5.0, 1.0], D=D)

But I’m not sure what the correct syntax is. Any advice on the correct usage of ForwardDiff in this setting?

An anonymous function would solve your problem nicely:

julia> f(x, D) = loglikelihood(Normal(x[1], x[2]), D)
f (generic function with 1 method)

julia> ForwardDiff.gradient(x -> f(x, D), [5.0, 1.0])
2-element Array{Float64,1}:
 0.533077
 2.26674 

Note that this is basically the same as your global D “hack” (which is actually a perfectly fine way to solve the problem as well):

julia> function my_function()
       D = rand(Normal(5.0, 1.0), 10)
       f(x) = loglikelihood(Normal(x[1], x[2]), D)
       ForwardDiff.gradient(f, [5.0, 1.0])
   end
my_function (generic function with 1 method)

julia> my_function()
2-element Array{Float64,1}:
 -1.26298
 -3.8625 
4 Likes

Also, the general term for what I’m suggesting is a closure.

4 Likes

Thanks @rdeits ! That works.