FluxML / Zygote.jl

21st century AD
https://fluxml.ai/Zygote.jl/
Other
1.48k stars 211 forks source link

Autodiff bug? #1149

Open ilysym opened 4 years ago

ilysym commented 4 years ago
using Flux

function fn_good(t0, τ, duration)
    x = 1.0
    t = t0
    T = t0 + duration
    while t < T
        x += -τ*x
        t += 0.01
    end
    x
end

f_good(τ) = fn_good(0.0, τ, 0.1)

# prints "f_good'(0.01): -9.94820282509685"
println("f_good'(0.01): $(f_good'(0.01))")

function fn_broken(t0, τ, duration)
    x = 1.0
    t = t0
    while t < t0 + duration
        x += -τ*x
        t += 0.01
    end
    x
end

# expected to be equivalent to f_good()
f_broken(τ) = fn_broken(0.0, τ, 0.1)

# doesn't terminate
println("f_broken'(0.01): $(f_broken'(0.01))")
jeremiedb commented 4 years ago

There's something unexpected happening with variable assignment with Zygote. Using the copy(t0) results in expected behavior:

function fn_broken(t0, τ, duration)
    x = 1.0
    t = copy(t0)
    while t < t0 + duration
        x += -τ*x
        t += 0.01
        println("t: ", t, " | t0: ", t0)
    end
    x
end

If the copy is removed, the the printing shows that forward call still behaves appropriately (f_broken_fixed(0.01)), but the diff shows that t0 is tracking the value of t, resulting in an infinite loop.