-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Clearer description of Slice #3908
Conversation
@@ -769,18 +769,31 @@ ONNX_OPERATOR_SET_SCHEMA( | |||
static const char* Slice_ver13_doc = R"DOC( | |||
Produces a slice of the input tensor along multiple axes. Similar to numpy: | |||
https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html | |||
Slices uses `starts`, `ends`, `axes` and `steps` inputs to specify the start and end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if https://numpy.org/doc/stable/user/basics.indexing.html?highlight=slice#slicing-and-striding is a better link?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A link to NumPy would make more sense for something preceded by "Similar to numpy".
onnx/defs/tensor/defs.cc
Outdated
|
||
All negative values in `starts[i]` and `ends[i]` have `dims[axes[i]]` added to them, | ||
where `dims` are the dimensions of `input`. Then `start[axes[i]]` is the adjusted | ||
`starts[i]` clamped into range `[0, dims[axes[i]]]`. The clamping for the adjusted |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should that be dims[axes[i]]-1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification. The spec is somewhat ambiguous. One interpretation would be that the sliced indices are all the values "start + jstep" that lie within the valid range obtained by clamping. The other interpretation would be to clamp start first, and generate values "clamped(start) + jstep". Do we know which is intended? Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's dim[axes[i]]
since you want -1
to go to the last element.
The problem with negative steps is that there is really no clean way to stop at 0 since end
is exclusive and negative values get shifted by the dimension size; you need to pick a really big negative end that is still below 0 when shifted by the size.
There is some code just below the doc that does some of this stuff; it looked similar to what I had implemented in our fork of glow based on experiments with numpy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you meant now. It gets a little confusing with [] being closed intervals, start being inclusive and end being exclusive. I also made the code and the text consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Everything seems fine, except one point I am confused about: what happens if starts[i] = dims[axes[i]]
and steps is negative ? Your new version says it will get clamped into the value dims[axes[i]] - 1
. I tried it is onnxruntime, and this is what happens. But, then, this line in the shape-inference code doesn't seem to be consistent with that:
Line 824 in 50a1981
start = clamp(start, 0, input_rank); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the PR I had changed that to input_rank - 1
.
BTW, when looking for that I noticed a one-word typo/omitto which I just fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, my fault. I saw that, but it didn't register, I thought the changes were only in the documentation, not the code. LGTM, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification! Please use update_doc.sh or update_doc.bat to update Operator.md as well.
Thanks Jacky for the update! |
@diyessi Do you have bandwidth to finish this PR? If not, please allow me to send a duplicate PR of yours and go forward. Thank you for your contribution. |
I might today; I need to re-figure out how to run the ONNX stuff (the README needs some updates). If I don't, feel free to jump in. Do I just need to merge from main, run |
Thank you for the quick reply. Other than those, you will also need to fix the DCO issue because some of your commits were not sign-offed. A faster way to solve it is to squash all your old commits into one (for instance, git reset softly to the base and make/sign-off a single commit with your whole change). |
@jwchen I think it's ready now. |
Thank you for the quick update! Sorry that I might not be clear: actually using update_doc.sh will update |
Signed-off-by: Scott Cyphers <cyphers@lightmatter.co>
It actually updates a lot of things when I run it. Hopefully this time it will all be good. |
The clamping for the adjusted `ends[i]` depends on the sign of `steps[i]` and must | ||
accommodate copying 0 through `dims[axes[i]]` elements, so for positive stepping | ||
`end[axes[i]]` is clamped to `[0, dims[axes[i]]]`, while for negative stepping it | ||
is clamped to `[-1, ends[i]-1]`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this read dims[axes[i]]-1
or am I mis-understanding something ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Starts are inclusive, ends are exclusive, so the slice covers indices {i | start <= i < end}
.
If it still seems wrong or you see a way to make it clearer, let me know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for not being clear enough. I think the logic is right. Looking at it, it seems inconsistent with the way it is worded
.
"...so for positive stepping ends[axes[i]]
is clamped to [0, dims[axes[i]]]
..."
Looking at the above line, I would have thought, the last set of words should be .... is clamped to [-1, dims[axes[i]] - 1]
instead of the ends
you are referencing. Does this make sense or am I on the wrong track ? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's say we have a tensor X[5]. Then a slice(X, start=0, end=0)
is empty, slice(X, start=0, end=5)
is all of X, and slice(X, start=0, end=101086)
is the same as slice(X, start=0, start=5)
.
In ranges, [
and ]
are inclusive, (
and )
are exclusive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with everything above.
I was just pointing out the clamping wording while negative stepping:
[-1, ends[i]-1]
-> [-1, dims[axes[i]] - 1]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And change the textual description accordingly. (Since we are not bumping the opset version, this PR should be only a clarification, not a change in behavior.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that sound reasonable? Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not seeing how the step > 0 case above is correct; start is inclusive, which is [0, input_rank), not [0, input_rank].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NumPy does behave like the original.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gramalingam : I think reverting to the old shape inference will be a good idea. It atleast maintains status quo and as you rightly say changing any behavior without an opset bump up is not a good idea.
@diyessi : Try this example on Numpy (this is for step > 0),
x = np.array([1, 2, 3])
x[5:6:1]
array([], dtype=int32)
If start
had been clamped to an inclusive value as you are suggesting, with the ends
clamping the way we all agree it to be, the result would actually be non-empty
Signed-off-by: Scott Cyphers <cyphers@lightmatter.co>
Signed-off-by: Scott Cyphers <cyphers@lightmatter.co>
Signed-off-by: Scott Cyphers cyphers@lightmatter.co
Description
Slice
.Motivation and Context