Skip to content

Perturbation Confusion (Nested Differentiation Bug) #83

Closed
@jrevels

Description

@jrevels

Nested differentiation should not be trusted until this issue is resolved. Not all nested calculations will be affected, but I think it's better to play it safe. Non-nested differentiation should be unaffected.

EDIT:

This bug is restricted to cases where the inner function closes over the argument at which an outer function is being differentiated.

Here are some examples:

const D = ForwardDiff.derivative

# inner function is a closure over x -> WILL GIVE WRONG RESULT
D(x -> x * D(y -> x + y, 1), 1) 

# inner function is a closure over v -> WILL GIVE WRONG RESULT
ForwardDiff.gradient(v -> sum(v) * D(y -> y * norm(v), 1), [1])

# inner function doesn't use x at all -> WILL GIVE CORRECT RESULT
D(x -> x * D(y -> y^2, 1), 1)

# inner function is a closure, but over z, not x -> WILL GIVE CORRECT RESULT
z = 3
D(x -> x / D(y -> y^z, 1), 1)

I discovered today that ForwardDiff suffers from perturbation confusion.

I noticed this when I was looking at the test suite earlier today and realized we had a test missing. The missing test should've been verifying that the following bug didn't occur:

julia> const D = ForwardDiff.derivative
derivative (generic function with 7 methods)

julia> D(x -> x * D(y -> x + y, 1), 1)
2 # this should obviously be 1

I thought I had committed this test a while ago (at the same time that I wrote the other nested differentiation tests), but apparently I screwed up somewhere, because I can't find it in the commit history.

I won't have time to really dig into this for a week or two, and a fix might require significant changes to the package (likely implementing a tagging system). I won't be sure of the best path forward until I do some thorough testing/code review. I'll go ahead and update the docs/README to make it clear that this issue exists.

@mlubin I bet this is also an issue for a lot of nested differentiation that people do using DualNumbers.jl, unless they were wise enough to code around it. I don't think DualNumbers.jl has a responsibility to provide a tagging system or anything, but it might be worth mentioning in that package's README.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions