Resize a symbolic input to a fixed output size with the iOS17 resize op - #2791
Open
LeSingh1 wants to merge 1 commit into
Open
Resize a symbolic input to a fixed output size with the iOS17 resize op#2791LeSingh1 wants to merge 1 commit into
LeSingh1 wants to merge 1 commit into
Conversation
F.interpolate(x, size=(H, W), mode="bilinear") aborts conversion as soon as
the input's spatial dims are flexible:
File ".../sympy/core/expr.py", line 375, in __float__
TypeError: Cannot convert expression to float
mb.upsample_bilinear resizes by a constant scale factor, so the converter
derives one from the requested output size, i.e. output_size / input_size.
When input_size is a sympy symbol that division has no constant answer and
the floor inside _get_scales_from_output_size raises.
The iOS17 resize op takes the target size directly, exactly for the case
where a tensor is resized to a shape that is not known at build time. Lower
to it when the input's height or width is symbolic, no scale factor was
supplied, and the output size is a compile-time constant. Static input shapes
and every scale-factor form keep going through mb.upsample_bilinear.
Core ML's UNALIGN_CORNERS sampling mode is bit-identical to torch's
align_corners=False and ALIGN_CORNERS to align_corners=True, so the mapping
is exact. Below iOS17 no op can express this, so it now raises a
NotImplementedError naming the deployment target to raise.
Bilinear only: mb.resize with NEAREST_NEIGHBOR interpolation accepts only the
DEFAULT sampling mode, whose rounding disagrees with torch unless the scale is
an exact integer, so upsample_nearest2d keeps its current behavior.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
F.interpolate(x, size=(H, W), mode="bilinear")— resize to a fixed output size — aborts conversion as soon as the input's spatial dims are flexible:mb.upsample_bilinearresizes by a constant scale factor, so the converter derives one from the requested output size via_get_scales_from_output_size, i.e.output_size / input_size. Wheninput_sizeis a sympy symbol that division has no constant answer and thefloorinside raises, from the middle of the converter with nothing pointing at what the model did.Resizing a variably-sized input down to a fixed size is the normal shape of image preprocessing inside a model, and it is a long-standing complaint — the same
_get_scales_from_output_sizefailure is what #970 hit, and #1916 is the nearest-neighbor sibling of it.Fix
The iOS 17
resizeop takes the target size directly rather than a scale factor, precisely for "a tensor needs to be resized to a dynamic shape" (its own docstring). So whenlower to
mb.resizeinstead. Static input shapes are untouched and still go throughmb.upsample_bilinear, as do all the scale-factor forms.Sampling mode: I checked
mb.resizeagainst torch for every mode on this shape —UNALIGN_CORNERSis bit-identical to torch'salign_corners=FalseandALIGN_CORNERStoalign_corners=True, so the mapping is exact rather than approximate.Below iOS 17 there is no op that can express this, so it now raises a
NotImplementedErrornaming the deployment target to raise, instead of the sympyTypeError.Scope
Deliberately bilinear-only. I probed
mb.resizewithinterpolation_mode="NEAREST_NEIGHBOR"forupsample_nearest2dand it only acceptsDEFAULTsampling, whose rounding disagrees with torch except when the scale is an exact integer, so mapping it would trade a crash for silently different numbers.upsample_nearest2d(the failure in #1916) keeps its current behavior.Test
TestUpsample::test_upsample_bilinear2d_with_output_size_dynamicresizes a(1, 3, 9, 22)input with both spatial dims flexible to(4, 4)(down) and(16, 20)(up, and non-square) withalign_cornersboth ways, on the TorchScript and torch.export frontends, and compares against torch at two different input sizes.Without the fix all 8
mlprogramparametrizations fail with the sympyTypeError; with it they pass.neuralnetworkis skipped sinceresizeis an iOS 17 mlprogram op.Verification
passes on macOS / Apple silicon, torch 2.12, with the pre-existing xfails unchanged.