Skip to content

Fix NumPy normalize shape for 1D inputs - #23428

Merged
hertschuh merged 3 commits into
keras-team:masterfrom
aswanth-07:fix-normalize-numpy-1d-shape
Sep 1, 2026
Merged

Fix NumPy normalize shape for 1D inputs#23428
hertschuh merged 3 commits into
keras-team:masterfrom
aswanth-07:fix-normalize-numpy-1d-shape

Conversation

@aswanth-07

@aswanth-07 aswanth-07 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Description

keras.utils.normalize() currently changes a one-dimensional NumPy input from shape (n,) to (1, n), while the backend-tensor path correctly preserves (n,).

For a 1D input, np.linalg.norm returns a scalar. Wrapping that scalar with np.atleast_1d gives it shape (1,); the subsequent np.expand_dims produces (1, 1), and NumPy broadcasting adds an unintended leading dimension to the result.

This change keeps the scalar or array returned by np.linalg.norm, replaces zero norms with np.where, and returns x / norm directly when axis=None. For an explicit axis, expanding the denominator along that axis preserves the one-dimensional input shape.

The regression test covers axis=-1, axis=0, and axis=None and checks both the output shape and normalized values.

Validation

  • KERAS_BACKEND=numpy python -m pytest keras/src/utils/numerical_utils_test.py -q (16 passed)
  • KERAS_BACKEND=jax python -m pytest keras/src/utils/numerical_utils_test.py -q (16 passed)
  • python -m ruff check keras/src/utils/numerical_utils.py keras/src/utils/numerical_utils_test.py (passed)
  • python -m ruff format --check keras/src/utils/numerical_utils.py keras/src/utils/numerical_utils_test.py (passed)
  • git diff --check (passed)

AI assistance disclosure

OpenAI Codex assisted with repository auditing, reproduction, implementation, upstream synchronization, and test execution. The reported tests were run against the final diff.

Contributor Agreement

Please review the AI-Assisted Contribution Policy and confirm these before marking the PR ready:

  • I am a human, and not a bot.
  • I will be responsible for responding to review comments in a timely manner.
  • I will work with the maintainers to push this PR forward until submission.

@google-cla

google-cla Bot commented Aug 12, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@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 updates the normalize utility to use np.asarray instead of np.atleast_1d for NumPy inputs, and adds a test to ensure shape preservation for 1D arrays. The review feedback highlights that 0D inputs still face shape-preservation issues when axis is None due to np.expand_dims being applied to the norm. It suggests a code adjustment to directly return x / norm in this scenario, along with adding a corresponding test case to prevent regressions.

Comment thread keras/src/utils/numerical_utils.py Outdated
Comment thread keras/src/utils/numerical_utils_test.py
@codecov-commenter

codecov-commenter commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.02%. Comparing base (19d533a) to head (63d839e).
⚠️ Report is 6 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #23428      +/-   ##
==========================================
+ Coverage   84.91%   85.02%   +0.10%     
==========================================
  Files         468      468              
  Lines       71091    71091              
  Branches    11788    11788              
==========================================
+ Hits        60368    60446      +78     
+ Misses       7717     7632      -85     
- Partials     3006     3013       +7     
Flag Coverage Δ
keras 84.83% <100.00%> (+0.10%) ⬆️
keras-cpu 84.10% <100.00%> (ø)
keras-gpu 69.96% <100.00%> (+<0.01%) ⬆️
keras-jax 58.63% <100.00%> (+0.11%) ⬆️
keras-numpy 53.95% <100.00%> (ø)
keras-openvino 59.66% <100.00%> (+<0.01%) ⬆️
keras-tensorflow 60.23% <100.00%> (+<0.01%) ⬆️
keras-torch 59.74% <100.00%> (+<0.01%) ⬆️
keras-tpu 57.47% <100.00%> (+35.42%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@aswanth-07
aswanth-07 marked this pull request as ready for review August 15, 2026 06:34
@aswanth-07

Copy link
Copy Markdown
Contributor Author

The TensorFlow CPU job reached the two-hour workflow limit and was cancelled; the NumPy, JAX, JAX NNX, Torch, OpenVINO, formatting, security, and CLA checks passed. I cannot rerun upstream Actions jobs from the fork, so could a maintainer please rerun the failed job when convenient?

@keerthanakadiri keerthanakadiri added the stat:awaiting keras-eng Awaiting response from Keras engineer label Aug 27, 2026

@hertschuh hertschuh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for addressing this!

Comment thread keras/src/utils/numerical_utils.py Outdated
if isinstance(x, np.ndarray):
# NumPy input
norm = np.atleast_1d(np.linalg.norm(x, order, axis))
norm = np.asarray(np.linalg.norm(x, order, axis))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Remove np.asarray, it doesn't do anything.

norm = np.linalg.norm(x, order, axis)

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.

Removed np.asarray in f5348f6. norm now comes directly from np.linalg.norm, and scalar-safe zero replacement uses np.where. All 16 numerical utility tests pass with both the NumPy and JAX backends.

@aswanth-07
aswanth-07 force-pushed the fix-normalize-numpy-1d-shape branch from b5fdf68 to f5348f6 Compare August 29, 2026 04:58
@aswanth-07

aswanth-07 commented Sep 1, 2026

Copy link
Copy Markdown
Contributor Author

@hertschuh The requested np.asarray removal is in f5348f6, and the affected numerical utility tests pass with both the NumPy and JAX backends. When convenient, could you take another look? Thanks.

@hertschuh hertschuh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks!

@google-ml-butler google-ml-butler Bot added kokoro:force-run ready to pull Ready to be merged into the codebase labels Sep 1, 2026
@hertschuh hertschuh removed stat:awaiting keras-eng Awaiting response from Keras engineer kokoro:force-run labels Sep 1, 2026
@hertschuh
hertschuh merged commit 83320b5 into keras-team:master Sep 1, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready to pull Ready to be merged into the codebase size:S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants