Skip to content

Fix NaN gradient of tf.math.igamma at a=1, x=0 - #123580

Merged
copybara-service[bot] merged 1 commit into
tensorflow:masterfrom
SEPURI-SAI-KRISHNA:fix-igamma-gradient-nan-zero-x
Jul 22, 2026
Merged

copybara-service[bot] merged 1 commit into
tensorflow:masterfrom
SEPURI-SAI-KRISHNA:fix-igamma-gradient-nan-zero-x

Conversation

@SEPURI-SAI-KRISHNA

Copy link
Copy Markdown
Contributor

Fixes #123578

_IgammaGrad computed partial_x = exp(-x + (a-1)*log(x) - lgamma(a)).

At a==1, x==0 the term (a-1)*log(x) is 0 * -inf = NaN, so the gradient of tf.math.igamma w.r.t. x is NaN there. The true derivative is d/dx igamma(1, x) = e^-x = 1. Use xlogy(a-1, x) instead, matching _BetaincGrad which already does this. Other regimes unchanged (a>1 -> 0, a<1 -> +inf, nonzero x identical). Adds IgammaGradTest.

Reproduced on tf-nightly 2.22.0-dev20260718.

@google-ml-butler google-ml-butler Bot added the size:M CL Change Size: Medium label Jul 19, 2026
@google-ml-butler
google-ml-butler Bot requested a review from cantonios July 19, 2026 17:27
@google-ml-butler google-ml-butler Bot added the awaiting review Pull request awaiting review label Jul 19, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces (a - 1) * log(x) with xlogy(a - 1, x) in the gradient computation of igamma (_IgammaGrad) to prevent NaN values when a == 1 and x == 0, and adds corresponding unit tests. The reviewer feedback suggests applying the same xlogy fix to the complementary incomplete gamma function gradient (_IgammacGrad) and updating the new unit tests to run in both graph and eager modes using tf.GradientTape instead of being restricted to V1 graph mode.

Comment on lines +1174 to 1175
partial_x = math_ops.exp(-x + math_ops.xlogy(a - 1, x) -
math_ops.lgamma(a))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The complementary incomplete gamma function gradient _IgammacGrad (defined in this file) shares the same formula and NaN gradient issue at a=1, x=0. Applying the same xlogy fix to _IgammacGrad and adding corresponding test coverage for igammac will prevent similar NaN gradient issues for tf.math.igammac.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_IgammacGrad doesn't have its own formula it calls _IgammaGrad and negates the result (return (-igamma_grad_a, -igamma_grad_x)), so the xlogy fix already propagates to tf.math.igammac. I confirmed igammac's x-gradient at a=1, x=0 goes from NaN to the correct -1.0, and added a regression test (testIgammacGradXAtZero).

Comment thread tensorflow/python/ops/math_grad_test.py Outdated
Comment on lines +839 to +840
def _igamma_x_grad(self, a, x):
return self.evaluate(gradients.gradients(math_ops.igamma(a, x), x)[0])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The tests currently only run in V1 graph mode due to @test_util.run_deprecated_v1 and the use of gradients.gradients. Using @test_util.run_in_graph_and_eager_modes along with tf.GradientTape allows testing the gradient in both graph and eager modes, which provides better coverage for TensorFlow 2.x execution paths.

Suggested change
def _igamma_x_grad(self, a, x):
return self.evaluate(gradients.gradients(math_ops.igamma(a, x), x)[0])
def _igamma_x_grad(self, a, x):
from tensorflow.python.eager import backprop
with backprop.GradientTape() as tape:
tape.watch(x)
y = math_ops.igamma(a, x)
return self.evaluate(tape.gradient(y, x))
References
  1. Verify that unit tests are included for any new logic, feature, or bug fix and cover edge cases across supported environments. (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call rewrote the tests to use tf.GradientTape under @test_util.run_in_graph_and_eager_modes so both execution paths are exercised.

@SEPURI-SAI-KRISHNA
SEPURI-SAI-KRISHNA force-pushed the fix-igamma-gradient-nan-zero-x branch from c02d2e5 to de6e1f6 Compare July 19, 2026 17:45
@keerthanakadiri
keerthanakadiri requested a review from a team July 20, 2026 04:39
@keerthanakadiri keerthanakadiri added the comp:ops OPs related issues label Jul 20, 2026
@github-project-automation github-project-automation Bot moved this to Assigned Reviewer in PR Queue Jul 20, 2026
@keerthanakadiri keerthanakadiri added the prtype:bugfix PR to fix a bug label Jul 20, 2026

@dmiltr3 dmiltr3 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this contribution. The fix for the NaN gradient in tf.math.igamma at $a=1, x=0$ looks mathematically sound and well-targeted.

Analysis

The original formulation in _IgammaGrad computed partial_x = exp(-x + (a - 1) * log(x) - lgamma(a)).
At $a=1, x=0$, the term (a - 1) * log(x) evaluates to 0 * -inf = NaN, despite the true mathematical derivative at that point being $e^{-0} = 1$.

Replacing (a - 1) * log(x) with xlogy(a - 1, x) robustly handles this edge case because xlogy natively maps $0 \times \log(0)$ to $0$.

Regimes Verification

  • $a &gt; 1, x = 0$: xlogy(a-1, 0) evaluates to $-\infty$ (since $a-1 &gt; 0$). The exponent becomes $-\infty$, and $e^{-\infty} = 0$. This is correct as $x^{a-1} = 0$ for $a &gt; 1$.
  • $a &lt; 1, x = 0$: xlogy(a-1, 0) evaluates to $+\infty$ (since $a-1 &lt; 0$). The exponent becomes $+\infty$, and $e^{+\infty} = +\infty$. This is correct as $x^{a-1} = \infty$ for $a &lt; 1$.
  • $x &gt; 0$: xlogy(a-1, x) is identical to $(a-1)\log(x)$.

Unit Tests

We verified this behavior with the following unit test:

import tensorflow as tf
from absl.testing import parameterized

class IgammaGradTest(tf.test.TestCase, parameterized.TestCase):

  @parameterized.parameters(tf.float32, tf.float64)
  def testNaNEdgeCase(self, dtype):
    a = tf.constant(1.0, dtype=dtype)
    x = tf.constant(0.0, dtype=dtype)
    with tf.GradientTape() as tape:
      tape.watch(x)
      y = tf.math.igamma(a, x)
    grad = tape.gradient(y, x)
    self.assertAllClose(grad, 1.0)

This ensures both single and double precision backends behave consistently.

@google-ml-butler google-ml-butler Bot added kokoro:force-run Tests on submitted change ready to pull PR ready for merge process labels Jul 21, 2026
@github-project-automation github-project-automation Bot moved this from Assigned Reviewer to Approved by Reviewer in PR Queue Jul 21, 2026
@kokoro-team kokoro-team removed the kokoro:force-run Tests on submitted change label Jul 21, 2026
@nithyak0204 nithyak0204 removed the awaiting review Pull request awaiting review label Jul 22, 2026
copybara-service Bot pushed a commit that referenced this pull request Jul 22, 2026
FUTURE_COPYBARA_INTEGRATE_REVIEW=#123580 from SEPURI-SAI-KRISHNA:fix-igamma-gradient-nan-zero-x de6e1f6
PiperOrigin-RevId: 950055097
@copybara-service
copybara-service Bot merged commit 0a9c612 into tensorflow:master Jul 22, 2026
20 checks passed
@github-project-automation github-project-automation Bot moved this from Approved by Reviewer to Merged in PR Queue Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:ops OPs related issues prtype:bugfix PR to fix a bug ready to pull PR ready for merge process size:M CL Change Size: Medium

Projects

Status: Merged

Development

Successfully merging this pull request may close these issues.

tf.math.igamma gradient w.r.t. x returns NaN at a=1, x=0 (expected 1.0)

6 participants

Sponsor
SponsoredKunjungi sekarang
Promo