Zygote.jl
Zygote.jl copied to clipboard
Error from second derivative with non-const global
Should I expect this to work?
julia> b = 5
5
julia> Zygote.refresh()
julia> f(x) = 4*x^2 + b*x + 10
julia> f'(25)
210.0
julia> g = f'
#59 (generic function with 1 method)
julia> g'(25)
ERROR: Can't differentiate foreigncall expression
Stacktrace:
[1] error(s::String)
@ Base .\error.jl:33
[2] Pullback
@ .\iddict.jl:102 [inlined]
[3] (::typeof(∂(get)))(Δ::Nothing)
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface2.jl:0
[4] Pullback
@ C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\lib\lib.jl:68 [inlined]
[5] (::typeof(∂(accum_global)))(Δ::Nothing)
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface2.jl:0
[6] Pullback
@ C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\lib\lib.jl:79 [inlined]
[7] (::typeof(∂(λ)))(Δ::Nothing)
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface2.jl:0
[8] Pullback
@ C:\Users\niklasg\.julia\packages\ZygoteRules\AIbCs\src\adjoint.jl:67 [inlined]
[9] (::typeof(∂(λ)))(Δ::Nothing)
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface2.jl:0
[10] Pullback
@ .\REPL[2]:1 [inlined]
[11] (::typeof(∂(λ)))(Δ::Tuple{Nothing, Float64})
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface2.jl:0
[12] Pullback
@ C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface.jl:41 [inlined]
[13] (::typeof(∂(λ)))(Δ::Tuple{Float64})
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface2.jl:0
[14] Pullback
@ C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface.jl:83 [inlined]
[15] (::typeof(∂(#59)))(Δ::Float64)
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface2.jl:0
[16] (::Zygote.var"#57#58"{typeof(∂(#59))})(Δ::Float64)
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface.jl:41
[17] (::Zygote.var"#59#60"{Zygote.var"#59#60"{typeof(f)}})(x::Int64)
@ Zygote C:\Users\niklasg\.julia\packages\Zygote\cCyLF\src\compiler\interface.jl:83
[18] top-level scope
@ REPL[7]:1
In principle, yes. In reality, less reliably than first derivatives.
Can you post the stack trace?
I edited the original post to include the stack trace.
For some reason it's tripping over the non-const global b. If you avoid that (which you probably should anyway -- which may be why nobody saw the bug) then it works:
julia> f2(x, b2=5) = 4*x^2 + b2*x + 10
f2 (generic function with 2 methods)
julia> g2 = f2'; g2'(25)
8.0
julia> const bc = 5; f3(x) = 4*x^2 + bc*x + 10
f3 (generic function with 1 method)
julia> g3 = f3'; g3'(25)
8.0
Notice that the gradient is (Δ::Nothing) in the stack trace. So it knows it doesn't need to go down this path, but somehow does? \src\lib\lib.jl:79 is https://github.com/FluxML/Zygote.jl/blob/master/src/lib/lib.jl#L79 accum_global(__context__, ref, x̄), which looks like it should call https://github.com/FluxML/Zygote.jl/blob/master/src/lib/lib.jl#L66 which tests x̄ === nothing. But doesn't?
@mcabbott: Yes, the non-const 'b' was actually why I asked whether it was expected to work.