feat: allow NaN in targets when masks are provided for metric computation#821
feat: allow NaN in targets when masks are provided for metric computation#821haoyu-haoyu wants to merge 2 commits into
Conversation
…tion
When evaluating imputation on irregularly sampled time series, the
ground truth (targets) itself may contain NaN values at naturally
missing positions. Previously, _check_inputs() rejected any NaN
in targets unconditionally, blocking this legitimate workflow.
Changes to _check_inputs():
- Return (lib, targets, masks) tuple instead of just lib, so callers
receive NaN-safe versions of targets and masks
- When masks are provided AND targets contain NaN:
1. Extend masks to exclude NaN positions (mask *= ~isnan(targets))
2. Replace NaN in targets with 0.0 to prevent NaN * 0 = NaN
propagation in arithmetic
- When masks are NOT provided AND targets contain NaN: raise
ValueError with clear message (no way to determine eval positions)
- predictions NaN check unchanged (model output should never be NaN)
All calc_* functions updated to unpack the new 3-tuple return.
Fully backward compatible: existing code with NaN-free targets
works identically.
Fixes WenjieDu#708
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Hi @haoyu-haoyu, please add unit testing cases for your updates. Thanks :) |
9 test cases covering all scenarios for _check_inputs NaN handling: - backward compat (NaN-free inputs unchanged) - NaN targets + masks → auto-exclude (numpy + torch) - NaN targets without masks → ValueError - all-NaN targets → metric ≈ 0 - MSE/RMSE/MRE no NaN propagation - predictions NaN still rejected - masks already excluding NaN → same result Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Hi @WenjieDu, thanks for the feedback! Unit tests added in 9 test cases covering all scenarios:
|
|
Pull Request Test Coverage Report for Build 23260746779Details
💛 - Coveralls |
|
This pull request had no activity for 14 days. It will be closed in 1 week unless there is some new activity. |
|
@WenjieDu Friendly ping — unit tests were added per your feedback (9 test cases, 100% coverage on new code, CI green, SonarCloud passed). Would you have a chance to take another look? Happy to address any further feedback. Thanks! |
|
Note: the CI failure on The |
|
This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 10 days. |
|
This PR was closed because it has been stalled for 10 days with no activity. |



Summary
Implements the feature requested in #708 (and attempted in the now-closed PR #707).
When evaluating imputation on irregularly sampled time series, the ground truth (
targets) itself may contain NaN values at naturally missing positions. Previously,_check_inputs()rejected any NaN intargetsunconditionally, blocking this legitimate workflow.Why PR #707 failed
The previous attempt used
logical_notincorrectly (reversed mask semantics — PyPOTS convention is mask=1 for observed, mask=0 for missing) and didn't complete tests before being auto-closed.The hidden trap:
NaN * 0 = NaNSimply removing the NaN assertion is not sufficient. In both NumPy and PyTorch,
NaN * 0producesNaN, not0. So even when the mask correctly zeroes out NaN positions, the arithmetic(predictions - targets) * maskswill propagate NaN through the result. The fix must replace NaN with 0 in targets before any arithmetic.Solution
_check_inputs()now returns(lib, targets, masks)instead of justlib:Three behaviors:
ValueErrorwith clear messageExample
Files changed
pypots/nn/functional/error.py_check_inputsreturns(lib, targets, masks), allcalc_*functions updatedTest plan
Fixes #708