-
Notifications
You must be signed in to change notification settings - Fork 50
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
Documentation on Running Simple Program using AD #24
Comments
As I see it the immediate reason why this fails is that d needs to be inlined for the plugin to be able to work its magic. However a function can only be inlined if it's (syntactically) fully applied. In its current form, d when fully applied returns a value in the codomain of a differentiable function, but not in general a differentiable function. I suspect the real reason why this isn't easy to fix is that the category of differentiable functions is not equal to the category of twice-differentiable functions. |
I remember thinking that the issue here was GHC applying rewrite rules and other optimizations in an unfortunate order. Although one can probably define a category of infinitely differentiable functions (lazily generating as many derivatives as you might want), another option (used above, IIRC) is to differentiate, extract a regular function, and differentiate again. The plugin would then perform two translations from GHC Core to categorical form. I do such cascading translations often, for instance to differentiate and then generate a circuit. Now I'm wondering if @TimPut is onto a simpler explanation and solution. GHC inlining, however, does not require syntactic full application. Rather there have to be as many explicit arguments as there were parameters on the LHS of a definition. The important difference here is that we can encourage d :: (Double -> a) -> Double -> a
d f = \ x -> derF f x 1
{-# INLINE d #-} |
That's funny. (Logically speaking, the information on the number of parameters that must be supplied in order to trigger inlining belongs in the I was trying to test whether nesting can be expressed, and if so whether it works correctly. For the case here, that pretty much comes down to handing variable scoping correctly. But if differentiation of higher-order functions is supported, there's a trickier case of nesting described in https://arxiv.org/abs/1211.4892 |
All variables are eliminated during the translation to categorical form (described here), and that translation is independent of AD. I don't think the perturbation confusion issue arises with the categorical approach. The extended essence-of-ad paper contains correctness proofs, which fortunately are fairly simple, since differentiation (really local affine approximation) is compositional over the categorical vocabulary in very simple ways, unlike with the lambda calculus. I'd be interested in exploring the question together, hopefully resolving it to our mutual satisfaction.
Thanks for the warning. Which example in the paper? Differentiation and higher-order functions seems to be a tricky combination for the categorical approach as well. |
Let me explain the simple meat of arXiv:1211.4892. Start with a derivative-taking operator d (f :: R -> a) (x :: R) = (derivative of f at x) :: (tangent space of a at f(x))
s (u :: R) (f :: R -> a) (x :: R) = f (x + u)
dHat = d s 0 The functions Note that |
Yes, that is a very nice property. One issue is that even if a defined function is first-order, it may internally use higher-order constructs. f ys y = foldl (+) 0 (map (^2) (map (y -) ys)) If we have a compositional formulation, and we push it into code like this, we're forced to define derivatives of higher-order functions in a fashion consonant with our first-order derivatives. I'd very much welcome the chance to work through some of these issues with you. I feel like we each have a good handle on one appendage of the elephant, and if we pull together we might be able to really take it apart. Should we take the discussion to email? |
@barak |
@TimPut I'm fine with that, until I start embarrassing myself! |
none of these examples work, presently.
with
|
I'm trying to play with the AD facilities, so decided to start with a minimal example.
Placing this as
nest.hs
in the top-levelconcat
directory and runningstack ghc nest.hs
generatesnest
butI tried to turn on options etc, see below, to get this migrated to compile-time, but must not have tickled the right ones. This is a beautiful system, and I'd like to play with it using the nice exported API without delving down into the internals. A few tiny examples of how to do this would really help.
The text was updated successfully, but these errors were encountered: