# Confused about how Zygote pullback handles tuple-valued loss functions

**URL:** <https://discourse.julialang.org/t/confused-about-how-zygote-pullback-handles-tuple-valued-loss-functions/91899>\
**Category:** Optimization (Mathematical)\
**Tags:** zygote\
**Created:** [December 20, 2022, 2:48pm UTC](https://discourse.julialang.org/t/confused-about-how-zygote-pullback-handles-tuple-valued-loss-functions/91899 "2022-12-20T14:48:56Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![bgroenks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bgroenks/32/21784_2.png) [@bgroenks](https://discourse.julialang.org/u/bgroenks)\
**Post date:** [December 20, 2022, 2:48pm UTC](https://discourse.julialang.org/t/confused-about-how-zygote-pullback-handles-tuple-valued-loss-functions/91899/1 "2022-12-20T14:48:56Z")

</div>

I noticed something odd (or at least that I don’t understand) with the `Zygote.pullback` method.

Let’s consider a very simple test case:

```julia
using Zygote

losses, back = Zygote.pullback(x -> (sum(x), sum(x)), [1.0,1.0])

```

Here we have a tuple-valued loss function, for which I would expect `back` to handle each entry separately, i.e. B\_1 = \frac{\partial y\_1}{\partial \ell\_1}\frac{\partial \ell\_1}{\partial p}, B\_2 = \frac{\partial y\_2}{\partial \ell\_2}\frac{\partial \ell\_2}{\partial p}.

However, that isn’t what happens. Instead, it seems like `back` treats the loss tuple as a vector and then sums over the results.

```julia
grads = back((1.0,1.0))
# output
(Fill(2.0, 2),)

```

and where does the `Fill` come from?

Am I missing something? Or is this a bug?

Thanks!

---

<div class="post-metadata">

**Author:** ![Tomas\_Pevny](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tomas_pevny/32/25466_2.png) [@Tomas\_Pevny](https://discourse.julialang.org/u/Tomas_Pevny)\
**Post date:** [December 20, 2022, 2:54pm UTC](https://discourse.julialang.org/t/confused-about-how-zygote-pullback-handles-tuple-valued-loss-functions/91899/2 "2022-12-20T14:54:58Z")

</div>

Zygote can handle only scalar loss function. Period. If you would like to take gradient of a function with two outputs, you are effectively computing Jacobian, which means that you need to take the gradient with respect to the first item, and then with the second.

---

<div class="post-metadata">

**Author:** ![bgroenks](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bgroenks/32/21784_2.png) [@bgroenks](https://discourse.julialang.org/u/bgroenks)\
**Post date:** [December 20, 2022, 3:05pm UTC](https://discourse.julialang.org/t/confused-about-how-zygote-pullback-handles-tuple-valued-loss-functions/91899/3 "2022-12-20T15:05:07Z")

</div>

I guess I was just thinking of it as taking the gradient with respect to two separate scalar losses (e.g. in a case where you have multiple additive loss terms), but yes, you’re right, it could also be a Jacobian. So then I guess `Zygote.jacobian` would be the appropriate function to use here.
