# Second derivative in Zygote returns nothing

**URL:** <https://discourse.julialang.org/t/second-derivative-in-zygote-returns-nothing/99624>\
**Category:** Machine Learning\
**Tags:** zygote, neural-network\
**Created:** [May 30, 2023, 6:23pm UTC](https://discourse.julialang.org/t/second-derivative-in-zygote-returns-nothing/99624 "2023-05-30T18:23:31Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![jarroyoe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jarroyoe/32/42482_2.png) [@jarroyoe](https://discourse.julialang.org/u/jarroyoe)\
**Post date:** [May 30, 2023, 6:23pm UTC](https://discourse.julialang.org/t/second-derivative-in-zygote-returns-nothing/99624/1 "2023-05-30T18:23:32Z")

</div>

I need to optimize a function that depends on the gradient of another function. When I run the following code:

```julia
using Zygote

data = rand(1,10)
f(p,x) = [x*p[1];x*p[2].+p[3]]
truef(x) = [x.+1;2*x]

function loss(p)
        dndts = [truef(x[1]) for x in data]
        dfdt(x) = Zygote.forwarddiff(x->f(p,x),x)

        ℓ = sum(abs2,reduce(hcat,[dfdt(data[i]).-dndts[i] for i in 1:10]))
        return ℓ
end

println(Zygote.gradient(loss,rand(3)))

```

I get `(nothing,)`. If I take the gradient inside the function out, something like this:

```julia
using Zygote

data = rand(1,10)
f(p,x) = [x*p[1];x*p[2].+p[3]]
truef(x) = [x.+1;2*x]

function loss(p)
        dndts = [truef(x[1]) for x in data]
        dfdt(x) = f(p,x)

        ℓ = sum(abs2,reduce(hcat,[dfdt(data[i]).-dndts[i] for i in 1:10]))
        return ℓ
end

println(Zygote.gradient(loss,rand(3)))

```

it works correctly. I know second derivatives are complicated, so I was wondering what would be an appropriate solution for this. If it’s of any use:

- I’m trying to do this where my function `f` is a neural network, using either the `Lux` or `Flux` environment
- My function, just like in this MWE, is a single input function that returns several outputs.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [May 31, 2023, 3:59am UTC](https://discourse.julialang.org/t/second-derivative-in-zygote-returns-nothing/99624/2 "2023-05-31T03:59:13Z")

</div>

Note that `Zygote.forwarddiff` doesn’t take a derivative. And further, it is explicitly blind to anything closed over by the function, i.e. to your `p`:

```julia
help?> Zygote.forwarddiff
  forwarddiff(f, x; chunk_threshold = ForwardDiff.DEFAULT_CHUNK_THRESHOLD) -> f(x)

  Runs f(x) as usual, but instructs Zygote to differentiate f using forward mode, rather than the
  usual reverse mode. 
[...]

  Note that the function f will drop gradients for any closed-over values.

  julia> gradient(2, 3) do a, b
           forwarddiff(a) do a
             a*b
           end
         end
  (3, nothing)

```

If you want a second derivative, using ForwardDiff outside, and Zygote inside, would probably work here.
