Hit this converting a model with F.interpolate(x, scale_factor=1.5, mode='bilinear') — ncnn doesn't match PyTorch, but only for bilinear/bicubic. nearest is fine.
It's the same problem as #3555: when resizing by a scale factor (no explicit size), the coordinate scale should be 1/scale_factor, not w/outw (input over rounded output). #3555 / 76e32e9 fixed that for nearest, but bilinear/bicubic still compute w/outw in linear_coeffs/cubic_coeffs. For integer scales the two are equal so it never shows up; for 1.5x on 7px, outw=10 and 7/10=0.7 vs 1/1.5=0.667 — every sample is offset.
Affects both front ends (PyTorch's default recompute_scale_factor=False, and ONNX Resize half_pixel — same as #3555).
Repro (pnnx, 3x7x7 fp32, vs PyTorch):
bilinear scale=1.5 ac=False max|diff| = 0.28
bicubic scale=1.5 ac=False max|diff| = 0.36
bilinear scale=2.0 ac=False 0 (integer)
bilinear scale=1.5 ac=True 0
nearest scale=1.5 0
bilinear size=(10,10) 0 (explicit size)
So it's bilinear/bicubic + non-integer scale + align_corners=False, no warning during conversion.
Fix is the same shape as 76e32e9 — use 1/width_scale in the scale-factor path instead of w/outw. Explicit size stays w/outw (correct), integer scales stay bit-exact. I've got it working locally across the backends + a test; happy to send a PR.
Hit this converting a model with
F.interpolate(x, scale_factor=1.5, mode='bilinear')— ncnn doesn't match PyTorch, but only for bilinear/bicubic. nearest is fine.It's the same problem as #3555: when resizing by a scale factor (no explicit size), the coordinate scale should be
1/scale_factor, notw/outw(input over rounded output). #3555 / 76e32e9 fixed that for nearest, but bilinear/bicubic still computew/outwinlinear_coeffs/cubic_coeffs. For integer scales the two are equal so it never shows up; for 1.5x on 7px, outw=10 and7/10=0.7vs1/1.5=0.667— every sample is offset.Affects both front ends (PyTorch's default
recompute_scale_factor=False, and ONNX Resizehalf_pixel— same as #3555).Repro (pnnx, 3x7x7 fp32, vs PyTorch):
So it's bilinear/bicubic + non-integer scale + align_corners=False, no warning during conversion.
Fix is the same shape as 76e32e9 — use
1/width_scalein the scale-factor path instead ofw/outw. Explicit size staysw/outw(correct), integer scales stay bit-exact. I've got it working locally across the backends + a test; happy to send a PR.