neuralforecast
neuralforecast copied to clipboard
Incorrect handling of first quantile knot in `isqf_domain_map` of ISQF
trafficstars
What happened + What you expected to happen
Description
The current implementation of isqf_domain_map function applies F.softplus() to all quantile knots, including the first one. This is incorrect because the first quantile knot represents the starting position of the distribution and should be allowed to take negative values.
Current Implementation (Incorrect)
# Line 1739 in neuralforecast/losses/pytorch.py
quantile_knots = F.softplus(input[..., start_index : start_index + num_qk]) + tol
qk_y = torch.cumsum(quantile_knots, dim=-1)
Expected Behavior
The first quantile knot should remain unconstrained (can be negative), while subsequent knots should have positive increments to ensure monotonicity. This matches the reference implementation in isqf.py.
Reference Implementation (Correct)
quantile_knots = torch.cat(
[
input[..., start_index : start_index + 1], # First knot unconstrained
F.softplus(quantile_knots[..., start_index + 1 : start_index + num_qk]) + tol, # Subsequent increments positive
],
dim=-1,
)
qk_y = torch.cumsum(quantile_knots, dim=-1)
Versions / Dependencies
Latest version of neuralforecast
Reproduction script
Wrong code:
# Line 1739 in neuralforecast/losses/pytorch.py
quantile_knots = F.softplus(input[..., start_index : start_index + num_qk]) + tol
qk_y = torch.cumsum(quantile_knots, dim=-1)
Correct code:
quantile_knots = torch.cat(
[
input[..., start_index : start_index + 1], # First knot unconstrained
F.softplus(quantile_knots[..., start_index + 1 : start_index + num_qk]) + tol, # Subsequent increments positive
],
dim=-1,
)
qk_y = torch.cumsum(quantile_knots, dim=-1)
Issue Severity
None