Skip to content

fix: stabilize image embedding normalization - #288

Closed
emecii wants to merge 1 commit into
Anush008:mainfrom
emecii:fix/stable-image-normalization
Closed

fix: stabilize image embedding normalization#288
emecii wants to merge 1 commit into
Anush008:mainfrom
emecii:fix/stable-image-normalization

Conversation

@emecii

@emecii emecii commented Sep 7, 2026

Copy link
Copy Markdown

Summary

Make the shared image-embedding normalization helper stable for finite large f32 values.

The previous direct squared sum overflowed for inputs such as [f32::MAX, f32::MAX], producing [0.0, 0.0]. This scales values by their largest absolute component before accumulating the squared norm, and divides through the scaled norm so it never has to form an overflowing product.

Validation

  • cargo fmt --all -- --check
  • RUSTFLAGS=-Dwarnings cargo clippy
  • cargo test --lib (16 passed)

The new regression tests cover ordinary vectors, zero vectors, and finite near-maximum values. The large-value test fails against the prior implementation and passes with this change.

@Anush008

Anush008 commented Sep 7, 2026

Copy link
Copy Markdown
Owner

@emecii, thanks for taking the time to contribute.

Did you hit this limitation a real model/output?

Embeddings we see are small, so val*val overflowing shouldn't happen in practice. If you have a repro model/vector, can you share it?

@emecii

emecii commented Sep 7, 2026

Copy link
Copy Markdown
Author

Thanks for checking. I tested this against the repository’s documented ClipVitB32 image path using the two bundled fixture images, and I could not reproduce large real-model outputs. The raw 512-dimensional vectors had max absolute values of 0.711 and 0.761, with f64 L2 norms of 0.9999996 and 0.9999998, so they were already near unit length and far from the f32 squaring-overflow range.

So I should describe this as a numerical-robustness fix rather than a currently observed image-model failure. The existing regression demonstrates the underlying arithmetic issue for finite inputs such as [f32::MAX, f32::MAX]: direct val * val overflow causes the former implementation to return zeroes. The scale-first normalization avoids that failure while preserving ordinary and zero-vector behavior.

I only measured the default CLIP model and the bundled images, so I cannot claim this occurs with a supported production model. If that defensive scope is not useful for the project, I understand if you would prefer to close the PR.

@Anush008

Anush008 commented Sep 7, 2026

Copy link
Copy Markdown
Owner

I'd prefer keeping the normalization simple if it's working fine practically.

@emecii

emecii commented Sep 7, 2026

Copy link
Copy Markdown
Author

Understood — thank you for the review. Since I could not reproduce this with the documented model path and the defensive scope is not useful for the project, I am closing the PR.

@emecii emecii closed this Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants