TensorFlow
gradients
tf.gradients()
machine learning
deep learning

tf.gradients sums over ys, does it?

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Yes. tf.gradients computes gradients of the sum of ys with respect to xs unless you override that behavior with grad_ys. This is a key detail because many people expect a full Jacobian-like result, but tf.gradients is designed for backpropagation, where accumulated contributions are exactly what you want.

What tf.gradients Returns

In TensorFlow 1 style graph mode, tf.gradients(ys, xs) returns, for each x in xs, the total gradient contribution coming from all values in ys.

That means:

  • if ys is a list, the contributions are added together
  • if ys is a tensor, TensorFlow seeds the backward pass with ones by default

So the default behavior is effectively "differentiate the sum of ys."

Scalar Example

python
1import tensorflow as tf
2
3tf.compat.v1.disable_eager_execution()
4
5x = tf.compat.v1.placeholder(tf.float32, shape=())
6y1 = x * x
7y2 = 3.0 * x
8
9grad = tf.compat.v1.gradients([y1, y2], x)[0]
10
11with tf.compat.v1.Session() as sess:
12    print(sess.run(grad, feed_dict={x: 2.0}))

At x = 2:

  • derivative of y1 = x^2 is 4
  • derivative of y2 = 3x is 3

So the result is 7, which is the sum of both contributions.

Non-Scalar ys

If ys is a vector, the same idea applies:

python
1x = tf.compat.v1.placeholder(tf.float32, shape=())
2y = tf.stack([x, x * x])
3
4grad = tf.compat.v1.gradients(y, x)[0]
5
6with tf.compat.v1.Session() as sess:
7    print(sess.run(grad, feed_dict={x: 3.0}))

By default, TensorFlow behaves as if the output vector were weighted by ones. So at x = 3, the result is:

  • derivative of x, which is 1
  • plus derivative of x^2, which is 6

Total: 7.

That is why tf.gradients is not the same thing as asking for every partial derivative separately.

Using grad_ys to Control the Weights

You can change the default all-ones weighting with grad_ys:

python
1x = tf.compat.v1.placeholder(tf.float32, shape=())
2y = tf.stack([x, x * x])
3weights = tf.constant([10.0, 0.5])
4
5grad = tf.compat.v1.gradients(y, x, grad_ys=weights)[0]
6
7with tf.compat.v1.Session() as sess:
8    print(sess.run(grad, feed_dict={x: 4.0}))

Now the backward pass computes:

  • '10 * d(x)/dx'
  • plus 0.5 * d(x^2)/dx

At x = 4, that becomes 10 * 1 + 0.5 * 8 = 14.

So grad_ys is the mechanism that lets you weight or seed each output contribution explicitly.

Why the API Works This Way

Backpropagation usually needs the gradient of a scalar objective such as a loss with respect to model parameters. Summing output contributions fits that training use case exactly, which is why tf.gradients is designed around accumulated gradients rather than a full Jacobian matrix.

If you need the full output-by-input derivative structure, use a Jacobian-oriented approach instead of expecting tf.gradients to return it automatically.

TensorFlow 2 Note

tf.gradients is a TensorFlow 1 style graph-mode API. In modern TensorFlow 2 code, the standard tool is tf.GradientTape.

For example:

python
1import tensorflow as tf
2
3x = tf.Variable(3.0)
4
5with tf.GradientTape() as tape:
6    y = tf.stack([x, x * x])
7    total = tf.reduce_sum(y)
8
9grad = tape.gradient(total, x)
10print(grad.numpy())

Here the summation is explicit because you reduce the output yourself before asking for a gradient.

Common Pitfalls

The biggest mistake is expecting tf.gradients to return a full Jacobian. It returns accumulated gradients, not a structured matrix of every partial derivative.

Another mistake is forgetting that vector ys values are effectively weighted by ones when grad_ys is omitted.

People also try to use tf.gradients in eager TensorFlow 2 code and run into API-model mismatches. In current TensorFlow, prefer tf.GradientTape unless you are intentionally working with graph-mode compatibility APIs.

Finally, if you need per-output derivatives, compute them separately or use Jacobian-specific APIs rather than relying on the summed behavior of tf.gradients.

Summary

  • Yes, tf.gradients sums gradient contributions over ys.
  • For non-scalar ys, the default seed is effectively a tensor of ones.
  • 'grad_ys lets you weight each output contribution explicitly.'
  • 'tf.gradients is for accumulated backprop-style gradients, not full Jacobians.'
  • In TensorFlow 2, prefer tf.GradientTape and make the scalar target explicit.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.