# Second order derivatives with ChainRules

**URL:** <https://discourse.julialang.org/t/second-order-derivatives-with-chainrules/103606>\
**Category:** Machine Learning\
**Tags:** chainrulescore, hessian, chainrules\
**Created:** [September 7, 2023, 9:49am UTC](https://discourse.julialang.org/t/second-order-derivatives-with-chainrules/103606 "2023-09-07T09:49:06Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![mariusd](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mariusd/32/23231_2.png) [@mariusd](https://discourse.julialang.org/u/mariusd)\
**Post date:** [September 7, 2023, 9:49am UTC](https://discourse.julialang.org/t/second-order-derivatives-with-chainrules/103606/1 "2023-09-07T09:49:06Z")

</div>

How can I get the second order derivarive of a function using ChainRules? Bellow is my approach for the `sin` function.

See the following code:

```julia
using ChainRules
using ChainRulesCore

# from the docs, first derivative of sin
x = 1.0
sinx, sin_pullback = rrule(sin, x)
sin_pullback(x) == (NoTangent(), cos(x)) # true

```

Let’s try to make it more general:

```julia
using ChainRules
using ChainRulesCore

sin_pullback(u) = rrule(sin, u)[2]
sin_pullback(pi/4)(1) == (NoTangent(), cos(pi/4)) # true
dsin(u) = sin_pullback(u)(1)[2] # get the cos(u) value
dsin(pi/4) == cos(pi/4) # true

# does not work:
rrule(dsin, pi/4) # returns nothing, we want (cos(pi/4), -sin(pi/4)

```

This happens because `dsin != cos` and there is no rrule defined for `dsin`.

So how can we achieve this?

---

<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:** [September 7, 2023, 1:48pm UTC](https://discourse.julialang.org/t/second-order-derivatives-with-chainrules/103606/2 "2023-09-07T13:48:54Z")

</div>

In short you need an AD engine.

The difference between `rrule(f, x)` and (say) `Zygote.pullback(f, x)` is that the first only exists when someone has written a rule by hand for this exact `f`.

Whereas Zygote will will look inside an arbitrary function, and see what other functions it calls. Here, `dsin(u)` calls some `sin_back` function, which (at very least) calls `cos` and `Tuple`, and then calls `getindex` the result. These individually have rules, but it needs to splice them together.
