Need some help in understanding zygote gradient

Hi, I met some troubles in understanding zygote gradient.

for example: I plan to get the gradient for f(x) = x^2 at x = 5, and also sum the result of f(x) for each time

let
  result = 0 
  f(x) = begin
      a = x^2
      result += a
      a
  end
  @info gradient(x -> f(x), 5)
  @info result
end

#it works, I got 
#[ Info: (10.0,)
#[ Info: 25

but if I run the code directly, an Error araised:

result = 0 
f(x) = begin
    a = x^2
    result += a
    a
end

gradient(x -> f(x), 5) 

ERROR: MethodError: no method matching +(::IRTools.Inner.Undefined, ::Int64)

what is the meaning of this error info while it works in a let block

Thanks for any suggestion, have a good day.

The problem is that you are modifying variable outside of the scope of the gradient, which is something AD is not happy with. If possible, I would rewrite the code as

f(x) = x^2
r, gs = Flux.withgradient(f, 5)
result +=r

1 Like

Specifically, you are modifying a global variable. This should work, but because it is a global you need you qualify it with global before modifying it in f. You can see this if you try to run f directly: it doesn’t work!

julia> f(1)
ERROR: UndefVarError: result not defined
Stacktrace:
 [1] f(x::Int64)
   @ Main ./REPL[3]:3
 [2] top-level scope
   @ REPL[4]:1

julia> f(x) = begin # you have to add the global keyword like this:
           a = x^2
           global result += a
           a
       end
f (generic function with 1 method)

julia> f(1)
1

julia> f(x) = begin # or this
           a = x^2
           global result
           result += a
           a
       end
f (generic function with 1 method)

julia> f(1)
1

All this to say that Zygote can’t make functions with errors suddenly work :wink:

1 Like