Wrong Jacobian
ChenZhao44 opened this issue · comments
using Yao
include("chainrules_patch.jl")
using Zygote
circ = put(1, 1=> Rx(0))
function loss(circ, θ)
circ = dispatch!(circ, [θ])
ψ = zero_state(1)
ψ = apply!(ψ, circ)
return abs2.(state(ψ))
end
function loss2(circ, θ)
circ = dispatch!(circ, [θ]) # this works
ψ = zero_state(1)
ψ = apply!(ψ, circ)
return abs2.(state(ψ))[2]
end
The gradient at pi
should be zero.
julia> gradient(x -> loss2(circ, x), pi)
(6.123233995736766e-17,)
However, the Jacobian is wrong. Here, the second element should be approximate to zero.
julia> jacobian(x -> loss(circ, x), pi)
([-6.123233995736766e-17, 1.0],)
julia> using Yao
julia> include("chainrules_patch.jl")
julia> using Zygote
julia> circ = put(1, 1=> Rx(0))
nqubits: 1
put on (1)
└─ rot(X, 0.0)
julia> function loss(circ, θ)
circ = dispatch!(circ, [θ])
ψ = zero_state(1)
ψ = apply!(ψ, circ)
return abs2.(state(ψ))
end
loss (generic function with 1 method)
julia> function loss2(circ, θ)
circ = dispatch!(circ, [θ]) # this works
ψ = zero_state(1)
ψ = apply!(ψ, circ)
return abs2.(state(ψ))[2]
end
loss2 (generic function with 1 method)
julia> gradient(x -> loss2(circ, x), pi)
(6.123233995736766e-17,)
julia> jacobian(x -> loss2(circ, x), pi)
([6.123233995736766e-17],)
Hmm, please definitely check your zygote version!
I checked my Zygote ver. which is 0.6.12.
The error is in Jacobian of loss
not loss2
.
julia> jacobian(x -> loss(circ, x), pi)
([-6.123233995736766e-17, 1.0],)
It should be approximate to ([0, 0], )
.
I updated Zygote to 0.6.19. And this issue is still there.
I just confirmed your issue. But I think it is probably an issue of Zygote's withjacobian
function.
function withjacobian(f, args...)
y, back = pullback(_jvec∘f, args...)
out = map(args) do x
T = promote_type(eltype(x), eltype(y))
dx = x isa AbstractArray ? similar(x, T, length(y), length(x)) :
x isa Number ? similar(y, T, length(y)) :
nothing
end
delta = _eyelike(y)
@show delta
@show back(delta[:,2])
@show back(delta[:,1])
@show back(delta[:,2])
for k in LinearIndices(y)
grads = back(delta[:,k])
for (dx, grad) in zip(out, grads)
dx isa AbstractArray || continue
_gradcopy!(view(dx,k,:), grad)
end
end
(val=y, grad=out)
end
I tried the following order of computing gradients,
julia> jacobian(x -> loss(circ, x), pi)
delta = [1.0 0.0; 0.0 1.0]
back(delta[:, 2]) = (6.123233995736766e-17,)
back(delta[:, 1]) = (-0.0,)
([6.123233995736766e-17, -1.0],)
julia> jacobian(x -> loss(circ, x), pi)
delta = [1.0 0.0; 0.0 1.0]
back(delta[:, 2]) = (6.123233995736766e-17,)
back(delta[:, 1]) = (-0.0,)
back(delta[:, 2]) = (6.123233995736766e-17,)
([7.498798913309288e-33, -1.8369701987210297e-16],)
julia> jacobian(x -> loss(circ, x), pi)
delta = [1.0 0.0; 0.0 1.0]
back(delta[:, 1]) = (-6.123233995736766e-17,)
back(delta[:, 2]) = (1.0,)
([6.123233995736766e-17, -1.0],)
My theory is, during computing the first gradient, the cached data is destroyed. The quick fix for you is just compute column by column, each time re-compute cached states. We really need an expert to look into this.
BTW, do you have such issue when using the previous patch for zygote?
You can also try the following approach to fix your issue
- implement non-inplace version
dispatch
andapply
, - rewrite rules for these functions,
- submit a PR to QuAlgorithmZoo if you have time. :P
then it should works
Just pushed a fix to this patch. Now the Jacobian should work. You need to update YaoBlocks to v0.11.5. to make it work. Now, the patch is implemented on apply
and dispatch
functions.
@GiggleLiu Thanks! It has been fixed.