|
| 1 | +# What to return for non-differentiable points |
| 2 | + |
| 3 | +In calculus one learns that if the derivative as computed by approaching from the left, |
| 4 | +and the derivative one computes as approaching from the right are not equal then the derivative is not defined, |
| 5 | +and we say the function is not differentiable at that point. |
| 6 | +This is distinct from the notion captured by [`NoTangent`](@ref), which is that the tangent space itself is not defined: because in some sense the primal value can not be perturbed e.g. is is a discrete type. |
| 7 | + |
| 8 | +However, contrary to what calculus says most autodiff systems will return an answer for such functions. |
| 9 | +For example for: `abs_left(x) = (x <= 0) ? -x : x`, AD will say the derivative at `x=0` is `-1`. |
| 10 | +Alternatively for: `abs_right(x) = (x < 0) ? -x : x`, AD will say the derivative at `x=0` is `1`. |
| 11 | +Those two examples are weird since they are equal at all points, but AD claims different derivatives at `x=0`. |
| 12 | +The way to fix autodiff systems being weird is to write custom rules. |
| 13 | +So what rule should we write for this case? |
| 14 | + |
| 15 | +The obvious answer, would be to write a rule that throws an error if input at a point where calculus says the derivative is not defined. |
| 16 | +Another option is to return some error signally value like `NaN`. |
| 17 | +Which you *can* do. |
| 18 | +However, this is not useful. |
| 19 | +Instead we introduce what we call the **sub/super-differential convention**: |
| 20 | + |
| 21 | +> It is always permissable to return any element of the sub/super-differential. |
| 22 | +> You should return the most useful. |
| 23 | +
|
| 24 | +Or equivalently but considering the trivial singleton sub/super-differential seperately: |
| 25 | + |
| 26 | +> At any point where the derivative is not defined, it is permissable to return any element of the sub/super-differential. |
| 27 | +> You should return the most useful. |
| 28 | +
|
| 29 | +We will justify this further below, but first let us discuss what it means. |
| 30 | + |
| 31 | +## What is the sub/super-differential? |
| 32 | + |
| 33 | +The subderivative is defined only for locally convex functions, where-as the super-deriviative is fined only for locally concave functions. |
| 34 | +For our purpose we, basically never care which we are working with and so write sub/super-derivative. |
| 35 | + |
| 36 | +For a function $f$ at some point $x_0$ a sub/super-derivative is a real number $c$ such that there exists a open ball $\mathcal{B} \subset \mathrm{dom}(f)$ containing $x_0$, |
| 37 | +and for all points $z \in \mathcal{B}$ the following holds: |
| 38 | + |
| 39 | +$$\mathrm{sub -derivative:}\qquad f(z) - f(x_0) \ge c\,(z-x_0)$$ |
| 40 | + |
| 41 | +$$\mathrm{super-derivative:}\qquad f(z) - f(x_0) \le c\,(z-x_0)$$ |
| 42 | + |
| 43 | +We call the the set of all values $c$ the sub/super-differential at $x_0$. |
| 44 | + |
| 45 | +More informally: consider a plot of the function. |
| 46 | +The sub/super-differential at a point is the set of slopes of all lines you could draw touching that point, but with the lines either entirely above, or entirely below the curve. |
| 47 | + |
| 48 | +It is best illustrated with a figure: |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | +In this figure a plot of a function is shown in blue. |
| 53 | +Two subtangent lines are plotted in red. |
| 54 | +Their slopes are sub/super-derivatives at $x_0$, and they are two elements of the subdifferential. |
| 55 | +If you flip it upside down, it would apply for the super-differential, with the lines being above the curve. |
| 56 | + |
| 57 | +### Some key things to note. |
| 58 | + |
| 59 | +For a function where the derivative is defined on both sides of the point: |
| 60 | + - the derivative on each side is a sub/super-derivative at the point |
| 61 | + - as is the mean of the derivative of each side |
| 62 | + - in-fact the mean of any subset (including the whole sub/super-differential) of sub/super-derivatives is also a sub/super-derivative. |
| 63 | + - if the derivative one one side is negative and the other positive then zero is a sub/super-derivative. |
| 64 | + |
| 65 | +For a function that is only defined on one side of the point, the sub/super-differential is the full set of real numbers. |
| 66 | +This by the subgradient convention leaves you free to chose *any* useful value. |
| 67 | + |
| 68 | +!!! info "Does AD always return a sub/super-derivative? No" |
| 69 | + On consideration of this, one might be tempted to think that AD always returns a sub/super-derivative. |
| 70 | + And that in normal cases it return the only sub/super-derivative i.e. the actual derivative; and in other case it picks one of the branches. |
| 71 | + Thus all weirdness of AD disagreeing with calculus could be explained away in this way. |
| 72 | + **This is not the case.** |
| 73 | + As it is not necessarily true that all branches derivatives are correct sub/super-differentials for the function. |
| 74 | + Consider the function from [Abadi and Plotkin, 2019](https://dl.acm.org/doi/10.1145/3371106): |
| 75 | + `f(x::Float64) = x == 0.0 ? 0.0 : x`. |
| 76 | + The correct derivative of this function is `1` at all points, but most ADs will say that at `x=0` the derivative is zero. |
| 77 | + The fix for this, is to define a rule which *does* in fact return a sub/super-derivative. |
| 78 | + So one could say a correctly functioning AD with all needed rules does always return a sub/super-differential. |
| 79 | + |
| 80 | + |
| 81 | +## What is useful ? |
| 82 | + |
| 83 | +The sub/super-differential convention had two parts: |
| 84 | +"It is always permissable to return any element of the sub/super-differential. |
| 85 | +**You should return the most useful.**". |
| 86 | +What is the most useful? |
| 87 | +This is a value judgement you as a rule author will have to make. |
| 88 | + |
| 89 | + |
| 90 | +### It is often zero |
| 91 | + |
| 92 | +If zero is a sub/super-derivative, then it is often the most useful one. |
| 93 | +Especially if the point is a local minima/maxima |
| 94 | +For a function like `abs` or `x -> x<0 ? x : -2x` setting the non-differentiable point to either side would result in it leaving that maxima. |
| 95 | + |
| 96 | +Further, a nice (albeit generally intractable) algorithm for finding the global optima is to take the set of all stationary points (i.e. points where the derivative is zero), combine that with the boundary points and evaluate the primal function at all of them. |
| 97 | +The extrema of this set are the global optima. |
| 98 | +This algorithm is only guaranteed correct for functions that are differentiable everywhere *or* that apply the sub/super-derivative convention and make all non-differentiable local optima claim to have a zero derivative. |
| 99 | +It is also correct if you make other non-differentiable points have zero derivative, just slower. |
| 100 | + |
| 101 | +### It is sometimes the non-zero, especially if it boarders a flat section |
| 102 | + |
| 103 | +If a function has derivative zero in some large section of it's domain, like `relu` or `x->clamp(x, -1, 1)`, |
| 104 | +a case can be made for choosing the non-zero derivative branch. |
| 105 | +Depending exactly on the larger function being optimized, it is often the case that a zero gradient for this function means a total zero gradient (e.g. if the greater function is a chain of composed calls). |
| 106 | +So once things move into the flat-region they stay there. |
| 107 | +If we chose the other branch we move them into (just barely) the nonflat region. |
| 108 | +If moving into the non-flat region was good they will move further there later. |
| 109 | +If it is not good then they well be rapidly cast deeper into the flat region and we will not be at this boundary case. |
| 110 | + |
| 111 | +### It is sometimes the mean |
| 112 | +Either the mean of the branches, or the overall mean of the sub/super-differential (which may be equal). |
| 113 | + |
| 114 | +A nice advantage of it is that it will agree with the result you will get from central finite differencing. |
| 115 | +Which is what [ChainRulesTestUtils.jl](https://github.com/JuliaDiff/ChainRulesTestUtils.jl) defaults to. |
| 116 | + |
| 117 | +### All else being equal it is just one of the branches |
| 118 | +Pick one. |
| 119 | +It will be fast. |
| 120 | +It will agree with either the forwards or reverse finite differencing results. |
| 121 | + |
| 122 | +### It is almost never `Inf`, `NaN` or an error |
| 123 | +Practically speaking, people are generally using AD to perform some gradient descent like optimization procedure. |
| 124 | +`NaN` and `Inf` do not generally take us to nice places. |
| 125 | +Erroring can be worse, especially if it is a local minima -- the optimization fully converges to that minima and then throws an error rather than reporting the result. |
| 126 | +If the primal function takes a non-finite value or errors on one side, then we are in the case that we are at a boundry of the domain. |
| 127 | +Which means we are free to chose *any* value. |
| 128 | +In particular we often want to chose value of the derivative from **the other side where the primal is defined.** |
| 129 | + |
| 130 | + |
| 131 | +## Why is the sub/super-differential convention permissible? |
| 132 | + |
| 133 | +Math isn't real, and AD doesn't do calculus. |
| 134 | +We are trying to accomplish some goal, and this is approach works well. |
| 135 | +More specifically, consider our initial examples: |
| 136 | +`abs_left(x) = (x <= 0) ? -x : x`, and `abs_right(x) = (x < 0) ? -x : x`. |
| 137 | +These are a a primal level indistinguishable to the user. |
| 138 | +It is impossible to tell which `Base.abs` uses without looking at the source. |
| 139 | +Thus the rule author must be free to chose between assuming it is either. |
| 140 | +Which is equivalent to saying they are free to chose to return the derivative or either branch. |
| 141 | +We can then take the continuous relaxation of that choice: to chose any value between them. |
| 142 | +Which for that case is choosing any sub-differential. |
| 143 | +We then generalize from that chose into the sub/super-differential convention. |
| 144 | + |
| 145 | +## How does this generalize to n-D |
| 146 | +Carefully, but consistently. |
0 commit comments