Repository navigation
feat(losses): add ContrastiveLoss computation dtype - #9210
JoaoMarcos44 wants to merge 8 commits into
Conversation
On unmodified dev bbebca6, 11 of 25 focused tests fail with NaN or infinite loss at temperatures 0.01 and 0.001. Covers analytic values, singleton batches, and independent cross-entropy loss/gradient reference. Disposable sandbox removed after validation. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: joaomarcos <joaomarcosdias444@gmail.com>
Exclude diagonal similarities before logsumexp and subtract the positive logit instead of exponentiating a ratio. All 25 focused tests pass, including 18 new analytic and independent loss/gradient regression cases; Ruff, Black, and isort pass. CPU validation with isolated dependencies and sandbox cleanup. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: joaomarcos <joaomarcosdias444@gmail.com>
Adversarial review reproduced 10 failing cases on d9b7927 among 35 tests: float16/bfloat16 output promotion and nonzero gradient checks, float16 batch reduction overflow, and cancellation for tiny temperatures. Both independent reviewers rejected the initial fix. Red validation completed in a removed disposable sandbox. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: joaomarcos <joaomarcosdias444@gmail.com>
CPU autocast and numerical gradcheck pass on the intermediate correction. One additional regression reproduces float64 temperature 1e-50 becoming zero through default float32 scalar construction; 1 of 39 focused cases fails until the scalar dtype is preserved. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: joaomarcos <joaomarcosdias444@gmail.com>
Adversarial review found a new float16 sum overflow from lost float32 promotion and residual cancellation after logsumexp. Compute reduced-precision inputs in float32, shift similarities by the positive before temperature scaling, and preserve the temperature dtype for float64. All 39 focused tests, finite-difference gradcheck, CPU autocast, and independent gradient references pass. Changed loss module line coverage is 93%; Ruff, Black, and isort pass. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: joaomarcos <joaomarcosdias444@gmail.com>
Isolated cosine backward roundoff and compared seven evaluation strategies across 1363 diagnostic configurations. Passing float64 embeddings before the loss reduces the measured gradient residual; casting the computed loss does not. Normalization prototypes leave residuals or alter near-epsilon backward semantics, so the algorithm stays unchanged. All 39 focused tests, Ruff, Black, and isort pass; module line coverage remains 93 percent. CPU evidence only; no universal gradient-accuracy claim or automatic dtype policy. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: joaomarcos <joaomarcosdias444@gmail.com>
On parent PR Project-MONAI#9208 head49542ec8, all 49 new API cases fail because compute_dtype is unavailable; all 39 inherited cases pass. Cases specify float64 extreme-temperature zero gradients, equivalence to input casting, input/output dtypes, autocast, invalid options, singleton loss and legacy arguments. Red validation completed in a cleaned sandbox. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: joaomarcos <joaomarcosdias444@gmail.com>
Expose keyword-only compute_dtype=None/float32/float64. Cast connected embeddings before cosine and temperature construction, preserving the parent default path. All 91 CPU tests pass, including 52 new cases and mixed-dtype backward controls; coverage97 percent and Ruff/Black/isort pass. In 24 identical-vector controls at temperature1e-8, explicit float64 reduces maximum gradient residual from2.0 to3.725290298461914e-9. This is an opt-in precision policy, not a universal accuracy guarantee or automatic dtype change. Depends on upstream PR#9208. Assisted-by: OpenAI Codex <noreply@openai.com> Signed-off-by: joaomarcos <joaomarcosdias444@gmail.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
Fixes #9209.
Dependency and review scope
This PR depends on PR #9208, which supplies log-space forward stabilization. The new capability here is explicit computation precision for the remaining backward-roundoff limitation. The default path is unchanged.
Because #9208 is still open, this branch includes its commits while targeting
dev. Review this contribution's two commits in the incremental comparison. This PR is ready for review and remains dependent on #9208 until the parent is integrated; the branch can then incorporate updateddevso the review diff contains only this increment. This is a separate precision-control enhancement, with its own issue and acceptance tests.Description
At temperature
1e-8, the parent implementation can return the correct lossln(3)but a float32 gradient residual of1.0for identical nonzero embeddings whose mathematical gradient is zero. The new keyword-onlycompute_dtypeoption makes the validated higher-precision workaround part of the loss configuration:The connected embeddings are cast before cosine similarity and temperature construction. The output uses the requested dtype; gradients still propagate to the original inputs and are stored in their original dtypes. Input tensors are not mutated.
Nonekeeps the parent default behavior, including mixed-input promotion and float16/bfloat16 computation in at least float32.torch.float32ortorch.float64selects the computation/output dtype. Explicit float32 can downcast float64 inputs.ValueError. Existing positional temperature/batch-size arguments remain valid.Validation
Source:
116bc2a409604fd05953634a8314ac2bb3169ee3. Windows, Python 3.14.1, PyTorch 2.12.1+cpu, NumPy 2.3.5.49542ec8compute_dtypewas unavailable; 39 inherited cases passedThe new cases cover analytical zero gradients for identical embeddings, exact forward/backward equivalence to manual input casting for nonzero gradients, input preservation, mixed input dtypes, explicit float32/float64 output, CPU autocast, invalid options, singleton batches, and legacy arguments. Default behavior is also covered by all 39 parent cases.
The validator records the checkout revision before the final source commit; its source/test SHA-256 values match the final committed files.
A separate fixed-seed measurement repeats each of 24 vectors four times, split into two inputs of batch size 2, with feature sizes 3/5/17. At temperature
1e-8, the mathematical gradient is zero:2.0compute_dtype=torch.float643.725290298461914e-9These CPU observations demonstrate reduced roundoff for the evaluated inputs. They do not guarantee exact gradients at every temperature, recover quantized embedding information, or expand the range of gradients stored in lower-precision inputs. Float64 requires device support and has additional memory/computation costs. GPU, distributed execution, full integration, training convergence, documentation builds, and performance were not tested. The inherited test named
test_with_cudaused its CPU fallback.Dragon infographic
The native-generated image explains the architecture, backward-roundoff problem, explicit float64 computation, and measured results. It is hosted separately from the code diff. No training benchmark or universal precision guarantee is implied.
Complete documentation and reproducibility
The backward limitation is real: cosine-similarity derivatives contain terms that should cancel for identical embeddings, but floating-point rounding can leave a residual. Scaling by
1 / temperaturecan amplify that residual at small temperatures. Stabilizing the forward reduction does not by itself correct the preceding cosine backward arithmetic. Computing cosine similarity in float64 reduces this error in the measured controls; casting the final scalar loss is too late.116bc2a409604fd05953634a8314ac2bb3169ee3, copy the three published Python helper scripts intoqa/gradient_precision/at that checkout's root, then runpython -B qa/gradient_precision/run_validation.py --phase greenandpython -B qa/gradient_precision/observe_precision.py. The helpers use disposable sandboxes and one thread per numerical library; the validator installs its small test-tool dependencies into the sandbox. PyTorch and NumPy must already be installed. These helpers use a minimal module bootstrap, so the recorded result is scoped CPU loss validation rather than a full MONAI integration run.At the publication update, all six GitHub checks displayed success: DCO, pre-commit.ci, DeepSource Python/Shell/Docker, and CodeRabbit. This status does not imply GPU or training validation; the local validation limits above still apply. This PR is open and ready for review; merge dependency on parent #9208 remains in effect.
Duplicate check
Open and closed issues/PRs were searched for ContrastiveLoss dtype, compute_dtype, float64, precision, gradient, and roundoff. Related #9207/#9208 document the limitation and manual casting, but do not implement this explicit control. This increment leaves their forward stabilization in the parent contribution.
Checklist
AI assistance disclosure: investigation, implementation, tests and documentation were prepared with OpenAI Codex, including independent adversarial reviews. The Dragon infographic was generated with native OpenAI image generation. All commits carry DCO sign-offs and AI assistance trailers; the submitting author remains responsible under MONAI's tool-assisted contribution policy.