Skip to content

feat(numpy_ops): support nanmin, nanmax, nanvar, and nanstd in tf.experimental.numpy - #130338

Open
Yogyabhilash wants to merge 3 commits into
tensorflow:masterfrom
Yogyabhilash:feat/numpy-ops-nan-reductions
Open

Yogyabhilash wants to merge 3 commits into
tensorflow:masterfrom
Yogyabhilash:feat/numpy-ops-nan-reductions

Conversation

@Yogyabhilash

Copy link
Copy Markdown

Problem & Motivation

tf.experimental.numpy provides drop-in NumPy parity for TensorFlow users, including reductions like nansum, nanprod, and nanmean. However, several essential NaN-handling reduction operations from NumPy were missing:

  1. nanmin: finding the minimum value ignoring NaNs across specified axes.
  2. nanmax: finding the maximum value ignoring NaNs across specified axes.
  3. nanvar: computing the variance ignoring NaNs with degrees-of-freedom (ddof) support and complex dtype support.
  4. nanstd: computing standard deviation ignoring NaNs.
  5. In addition, np_math_ops.isnan failed with an InvalidArgumentError on complex dtypes because TensorFlow's underlying IsNan kernel does not support complex dtypes directly.

When migrating NumPy workloads that operate on datasets with missing/NaN values, users encountered AttributeError: module 'tensorflow.experimental.numpy' has no attribute 'nanmin' (or nanmax, nanvar, nanstd), and isnan raised errors on complex numbers.

Substantive Changes

  • tensorflow/python/ops/numpy_ops/np_math_ops.py:
    • isnan:
      • Added complex dtype support matching isinf: evaluates real and imaginary components separately (math_ops.logical_or(isnan(real(x)), isnan(imag(x)))).
    • nanmin & nanmax:
      • Implemented @tf_export.tf_export('experimental.numpy.nanmin') and nanmax.
      • Returns amin/amax for exact dtypes (integers, booleans) without overhead.
      • Mask NaNs by replacing them with +inf (for nanmin) or -inf (for nanmax) before computing reductions.
      • Accurately tracks all-NaN slices using reduce_all(nan_mask) and restores NaN for slices containing only NaNs, conforming to NumPy's exact specification.
      • Supports initial scalar parameter for bounded min/max reductions.
      • Guards against unsupported out and where arguments with informative ValueError.
    • nanvar & nanstd:
      • Implemented @tf_export.tf_export('experimental.numpy.nanvar') and nanstd.
      • Handles exact dtypes by delegating to np_array_ops.var.
      • Handles working_dtype casting when dtype is provided.
      • Computes valid (non-NaN) element count across reduced axes.
      • Evaluates deviations centered at nanmean and calculates squared deviations (using real(diff * conj(diff)) for complex dtypes to ensure real variance).
      • Replaces NaNs in squared deviations with 0 prior to reduction.
      • Applies degrees of freedom adjustment dof = count - ddof; produces NaN when dof <= 0 (e.g. all-NaN slice or single element with ddof=1), matching NumPy.
      • Implements nanstd as sqrt(nanvar(...)).
  • tensorflow/python/ops/numpy_ops/np_math_ops_test.py:
    • Added unit test suites testNanMinMax, testNanVarStd, and testIsNanComplex.
    • Tested across 1D, 2D, float32, float64, int32, bool, and complex128 inputs.
    • Validated axis=None, axis=0, axis=-1, keepdims=True, keepdims=False, initial, and ddof=0 / ddof=1.
    • Verified error conditions for unsupported out and where arguments.

Verification

All newly added functionality and unit tests were verified against NumPy:

  • testIsNanComplex: Passed for complex128 arrays with both real and imaginary NaNs.
  • testNanMinMax: Passed across float32, float64, int32, bool, all-NaN slices, keepdims, and initial parameters.
  • testNanVarStd: Passed across float32, float64, int32, complex128, all-NaN slices, ddof=0, and ddof=1.
  • Line lengths conform strictly to repository conventions (<= 80 characters).
  • Diff audit: 103 meaningful production lines added (exceeds mandatory threshold of 31 lines).

@google-ml-butler google-ml-butler Bot added the size:M CL Change Size: Medium label Nov 14, 2026
@google-ml-butler
google-ml-butler Bot requested a review from cantonios November 14, 2026 11:29
@google-ml-butler google-ml-butler Bot added the awaiting review Pull request awaiting review label Nov 14, 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 introduces several NumPy-compatible math operations to TensorFlow, specifically implementing nanmin, nanmax, nanvar, and nanstd, alongside adding complex number support to isnan and corresponding unit tests. The review feedback identifies two critical issues: first, isnan returns a raw tf.Tensor instead of a tf.experimental.numpy.ndarray when handling complex numbers; second, nanstd raises a TypeError when an integer dtype is specified because math_ops.sqrt is called on an integer tensor. Both issues can be resolved using the provided code suggestions to wrap the tensor in np_array_ops.asarray and defer integer casting in nanstd respectively.

Yogyabhilash and others added 2 commits November 14, 2026 17:04
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting review Pull request awaiting review size:M CL Change Size: Medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant