And
I hear this a lot but it doesn't make sense to me. How do you differentiate an conditional or a loop? It doesn't make sense mathematically, so I'm not sure what sense it makes programmatically.
Going beyond AD there is a "differential lambda calculus" [1]. I don't really understand this work. It requires more background in programming languages, logic, and analysis than I have time to learn. My understanding is it allows you to compute more derivatives (e.g. for higher-order functions) and place conditions so only sensible derivatives are computed. There is also "differential linear logic" [2] which has some relation to the differential lambda calculus but it's unclear to me what that relationship is.
So in summary I believe:
1. automatic differentiation will compute the correct derivative when such a thing is available, and some nonsense answer otherwise
2. to increase the space of programs for which derivatives can be computed and to rule out other programs you need to look at differential lambda calculus / linear logic.
[1]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.471... [2]: https://arxiv.org/abs/1606.01642
The problem is this is false too. Just modify my example a bit:
y = x if x > 0 else x if x < 0 else 0
Here we clearly have y'(0) = 1, yet autodiff would seem to give y'(0) = 0.If your loop is computing something like f(g(...h(x))) i.e. applying functions in sequence, starting with x, then there's no problem -- dual numbers will compute the correct derivative.
If the loop is an implementation detail, like I think the poisson distribution p(λ,k) is often computed with a loop up to k... then making λ a dual number still works. Clearly you can't differentiate on k, because it's an integer.
This talk from 27mins onwards discusses some of the issues if you're interested in diving in a bit deeper: https://www.youtube.com/watch?v=qhPBfysSYI8 I found it pretty heavy going. YMMV.
Or to say that another way, since the derivative by definition changes x infinitesimally, it never changes on which side of the conditional x is located.
y = x if x > 0 else -2 * x if x < 0 else 0In practice, from what I've read it seems to be fine to just take any value between these and most commonly they are just averaged. It helps that these regions are rarely encountered.
For more detail, check out Chapter 6 [1], Section 6.3 "Hidden Units" in The Deep Learning book.
y = x if x > 0 else x if x < 0 else 0
Zero is in no way a subderivative at x = 0.In calculus class this would be ill-defined / ambiguous, but the computer is simple-minded and picks one answer.
This doesn't seem like a major flaw to me. What are you using this for which would care? Maybe you have something like a rectification which produces exactly x=0 much more often than 1 in 2^32... in which case a function like your y amounts to a special case for this.
If you cared you could write a special case for the derivative too, here's one which will give y'(0)=42 but otherwise the automatic derivative:
julia> y(x) = x>0 ? x : -2x
julia> y(x::Dual) = x==0 ? dual(0, 42) : (x>0 ? x : -2x)Every function is constant at every point. For example, I could define the identity function as `y ( x ) = if ( x > 0 ) { x } elsif ( x < 0 ) { x } else { 0 }`, but that doesn't mean that its derivative at the origin is `0`.
The examples given in the article are merely derivatives of ordinary mathematical functions defined by ordinary mathematical expressions - in particular, there are no sequencing, no conditionals and no loops. So why call them “differentiable programs” when you are actually dealing with ordinary differentiable functions from good old 19th century analysis? We need urgent improvements in the intellectual honesty department.