Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mark scales as optional and remove tf_half_pixel_for_nn in resize op #3026

Merged
merged 14 commits into from
Oct 14, 2020

Conversation

daquexian
Copy link
Member

@daquexian daquexian commented Sep 20, 2020

  1. mark 'scales' of the resize op as an optional input (Doc update for Resize to correct some wrong information #2948 (comment)).

  2. remove coordinate_transformation_mode 'tf_half_pixel_for_nn'. This mode was introduced by me for resize_nearest half_pixel of tensorflow, but it is indeed unnecessary.
    The equation of nearest + half_pixel is x' = round((x + 0.5) / scale - 0.5), while in tf it is optimized as x' = floor((x + 0.5) / scale). As a result, I introduced a transformation mode 'tf_half_pixel_for_nn' for the transformation (x + 0.5) / scale in PR Update resize op #2057.
    However, as shown above, it should be replaced with a plain 'half_pixel' + 'round_prefer_ceil'

@daquexian daquexian requested a review from a team as a code owner September 20, 2020 06:05
…favor of half_pixel + round_prefer_ceil

Signed-off-by: daquexian <daquexian566@gmail.com>
Signed-off-by: daquexian <daquexian566@gmail.com>
<dt><tt>scales</tt> : tensor(float)</dt>
<dd>The scale array along each dimension. It takes value greater than 0. If it's less than 1, it's sampling down, otherwise, it's upsampling. The number of elements of 'scales' should be the same as the rank of input 'X'. Only one of 'scales' and 'sizes' can be specified. If 'size' is specified, then set scales to empty data (zero shape) in this operator's input list.</dd>
<dt><tt>scales</tt> (optional) : tensor(float)</dt>
<dd>The scale array along each dimension. It takes value greater than 0. If it's less than 1, it's sampling down, otherwise, it's upsampling. The number of elements of 'scales' should be the same as the rank of input 'X'. Only one of 'scales' and 'sizes' can be specified. If 'size' is needed, the user can use an empty string as the name of 'scales' in this operator's input list.</dd>
<dt><tt>sizes</tt> (optional) : tensor(int64)</dt>
<dd>The size of the output tensor. The number of elements of 'sizes' should be the same as the rank of input 'X'. Only one of 'scales' and 'sizes' can be specified.</dd>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since both scales and sizes are now "optional" per schema - should we go ahead and include a line that says - one of the two optional inputs MUST be specified. We already have a line that says "only one can be specified...", maybe we can say - "one of the two MUST be specified and it is an error if both are specified."

Also does the onnx checker catch cases where the Resize node has only two inputs - which means it is missing one of the two ? Also, Inputs (2-4) - is that correct ?

Copy link
Member Author

@daquexian daquexian Oct 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also does the onnx checker catch cases where the Resize node has only two inputs - which means it is missing one of the two ? Also, Inputs (2-4) - is that correct ?

Agree. But it seems like the infra (checker and doc generator) cannot support "one of these optional inputs must be specified".

@@ -15669,15 +15666,15 @@ x_original = length_resized > 1 ? start_x * (length_original - 1) + x_resized *
<dd>Four modes: round_prefer_floor (default, as known as round half down), round_prefer_ceil (as known as round half up), floor, ceil. Only used by nearest interpolation. It indicates how to get "nearest" pixel in input tensor from x_original, so this attribute is valid only if "mode" is "nearest".</dd>
</dl>

#### Inputs (3 - 4)
#### Inputs (2 - 4)

<dl>
<dt><tt>X</tt> : T1</dt>
<dd>N-D tensor</dd>
<dt><tt>roi</tt> : T2</dt>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not make roi optional as well? since it only takes effect when coordinate_transformation_mode is "tf_crop_and_resize"

@@ -15669,15 +15666,15 @@ x_original = length_resized > 1 ? start_x * (length_original - 1) + x_resized *
<dd>Four modes: round_prefer_floor (default, as known as round half down), round_prefer_ceil (as known as round half up), floor, ceil. Only used by nearest interpolation. It indicates how to get "nearest" pixel in input tensor from x_original, so this attribute is valid only if "mode" is "nearest".</dd>
</dl>

#### Inputs (3 - 4)
#### Inputs (2 - 4)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be 2 to 3? Because Sizes and Scales should not be specified together right.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@askhade @hariharans29 I agree that here should be 2-3, but this line is generated automatically. Is there any way to overwrite it?

@askhade askhade added this to the 1.8 milestone Oct 2, 2020
@askhade
Copy link
Contributor

askhade commented Oct 2, 2020

@daquexian : Marking this PR for 1.8 release. Let's try and get this change checked in before 1.8 to avoid another version bump for resize.

@daquexian
Copy link
Member Author

@askhade @hariharans29 I have updated the spec to "one of the two MUST be specified and it is an error if both are specified" and made the input "roi" also optional. When it comes to "input (2-4)" and the checker problem, maybe we need to update the infra to support the case "one of these optional inputs must be specified" first?

@hariharans29
Copy link
Contributor

hariharans29 commented Oct 7, 2020

@askhade @hariharans29 I have updated the spec to "one of the two MUST be specified and it is an error if both are specified" and made the input "roi" also optional. When it comes to "input (2-4)" and the checker problem, maybe we need to update the infra to support the case "one of these optional inputs must be specified" first?

Thanks for adding the line to the spec. It leaves no place for ambiguity atleast with the spec description. It does a look a little weird to see (2-4) when actually the correct line there must read (2-3), but looks like ONNX doesn't have the infrastructure to deal with "inter-dependence" of optional inputs/outputs (i.e.) we are not able to say - 'scales' and 'sizes' are individually optional both they are NOT both optional and both can't co-exist. So, I guess we can leave it for now and enhance the infrastructure for later.

For the second aspect of the PR - deprecating tf_half_pixel_for_nn- does this cause any issue for a model that is using this attribute and trying to upgrade to opset-13 ? It seems like (from your comment in the PR) that all the converter (or opset upgrader) would have to do is replace tf_half_pixel_for_nn with half_pixel' + 'round_prefer_ceil and the upgrade will be seamless. Is this correct or do you foresee any other upgrade issues faced by models already using this attribute ?

@@ -9760,7 +9760,6 @@ data = np.array([[[
]]], dtype=np.float32)

roi = np.array([], dtype=np.float32)
scales = np.array([], dtype=np.float32)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add a test where scales exists and sizes does not ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. There are already such tests before this PR submitted (e.g., https://github.com/onnx/onnx/blob/master/onnx/backend/test/case/node/resize.py#L341) .

.Input(
2,
"scales",
"The scale array along each dimension. It takes value greater than 0. If it's less than 1,"
" it's sampling down, otherwise, it's upsampling. The number of elements of 'scales' should"
" be the same as the rank of input 'X'. Only one of 'scales' and 'sizes' can be specified. If 'size' is specified, then set scales to empty data (zero shape) in this operator's input list.",
" be the same as the rank of input 'X'. One of 'scales' and 'sizes' MUST be specified and it is an error if both are specified. If 'size' is needed, the user can use an empty string as the name of 'scales' in this operator's input list.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: If 'sizes' is needed (not if 'size' is needed) for consistency

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Fixed

@hariharans29
Copy link
Contributor

Overall, I am good with this PR - left a couple of minor comments

@daquexian
Copy link
Member Author

For the second aspect of the PR - deprecating tf_half_pixel_for_nn- does this cause any issue for a model that is using this attribute and trying to upgrade to opset-13 ? It seems like (from your comment in the PR) that all the converter (or opset upgrader) would have to do is replace tf_half_pixel_for_nn with half_pixel' + 'round_prefer_ceil and the upgrade will be seamless. Is this correct or do you foresee any other upgrade issues faced by models already using this attribute ?

@hariharans29 Yes, it is correct. All the converter only have to replace replace 'tf_half_pixel_for_nn' with 'half_pixel' + 'round_prefer_ceil'.

Copy link
Contributor

@hariharans29 hariharans29 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@askhade askhade self-requested a review October 12, 2020 19:02
Copy link
Contributor

@askhade askhade left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@daquexian : It seems the tests were not updated after roi was made optional. Can you update the test script and regenerate the tests again. Thanks!

@askhade askhade added the operator Issues related to ONNX operators label Oct 12, 2020
@daquexian
Copy link
Member Author

@daquexian : It seems the tests were not updated after roi was made optional. Can you update the test script and regenerate the tests again. Thanks!

Thanks. Updated.

@askhade
Copy link
Contributor

askhade commented Oct 13, 2020

@daquexian : The tests are checked in with the test script. So you need to update the generated tests as well. I think you only updated the test script.
FYI: We are cutting the release branch tomorrow morning and as much as possible I want to check this change in otherwise we will need another version bump for resize op.

@gramalingam
Copy link
Contributor

It is true that the documentation-generator does not have infrastructure to fix the number of inputs expected. However, the type-and-shape-inference checker can be augmented to verify that exactly one of two inputs is specified. (Well, sort of ... we can do the check using both getNumInputs and getInputType; we will need to use getInputType as a proxy for whether a particular input is specified; it is not perfect, but it is reasonable. The only minor issue would be a misleading error-message in the case where an input is specified, but type-inference could not infer its type.

@gramalingam
Copy link
Contributor

Specifically: a utility function like below should help:

   inline bool hasInput(InferenceContext& ctx, size_t n) {
       return ctx.getNumInputs() > static_cast<size_t>(n) && ctx.getInputType(n);
}

We can then add a check one of the two inputs is specified.

@askhade
Copy link
Contributor

askhade commented Oct 13, 2020

Shape inference code for resize needs fixes.

if (is_resize_op && ctx.getNumInputs() == 4) {

Current shape inference code will pick sizes input only if number of inputs is 4 but with roi and scales being optional inputs shape inference will fail.

Signed-off-by: daquexian <daquexian566@gmail.com>
Signed-off-by: daquexian <daquexian566@gmail.com>
@daquexian
Copy link
Member Author

daquexian commented Oct 14, 2020

@daquexian : The tests are checked in with the test script. So you need to update the generated tests as well. I think you only updated the test script.

@askhade Thanks! Updated.

Current shape inference code will pick sizes input only if number of inputs is 4 but with roi and scales being optional inputs shape inference will fail.

I don't think so.

for (const auto& input : n.input()) {
auto valueTypesIter = valueTypesByName.find(input);
if (valueTypesIter != valueTypesByName.end()) {
allInputTypes_.push_back(valueTypesIter->second);
} else {
allInputTypes_.push_back(nullptr);
}

size_t getNumInputs() const override {
return allInputTypes_.size();
}

The allInputTypes_ will be [input_type, nullptr, nullptr, sizes_type] and the number of inputs will still be 4.

@daquexian
Copy link
Member Author

It is true that the documentation-generator does not have infrastructure to fix the number of inputs expected. However, the type-and-shape-inference checker can be augmented to verify that exactly one of two inputs is specified. (Well, sort of ... we can do the check using both getNumInputs and getInputType; we will need to use getInputType as a proxy for whether a particular input is specified; it is not perfect, but it is reasonable. The only minor issue would be a misleading error-message in the case where an input is specified, but type-inference could not infer its type.

Good advice! Let's merge this PR for 1.8 release and I can submit another pr for this in the future.

@askhade askhade merged commit fbeb7b1 into onnx:master Oct 14, 2020
@daquexian daquexian deleted the update_resize branch October 14, 2020 03:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
operator Issues related to ONNX operators
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants