Skip to content
This repository was archived by the owner on Nov 17, 2023. It is now read-only.

[MXNET-791] Pick with negative indices #12090

Conversation

perdasilva
Copy link
Contributor

@perdasilva perdasilva commented Aug 8, 2018

Description

Updates pick operator to handle negative indices.
Implements #12009

Checklist

Essentials

Please feel free to remove inapplicable items for your PR.

  • The PR title starts with [MXNET-$JIRA_ID], where $JIRA_ID refers to the relevant JIRA issue created (except PRs with tiny changes)
  • Changes are complete (i.e. I finished coding on this PR)
  • All changes have test coverage:
  • Unit tests are added for small changes to verify correctness (e.g. adding a new operator)
  • Nightly tests are added for complicated/long-running ones (e.g. changing distributed kvstore)
  • Build tests will be added for build configuration changes (e.g. adding a new build option with NCCL)
  • Code is well-documented:
  • For user-facing API changes, API doc string has been updated.
  • For new C++ functions in header files, their functionalities and arguments are documented.
  • For new examples, README.md is added to explain the what the example does, the source of the dataset, expected performance on test set and reference to the original paper if applicable
  • Check the API doc at http://mxnet-ci-doc.s3-accelerate.dualstack.amazonaws.com/PR-$PR_ID/$BUILD_ID/index.html
  • To the my best knowledge, examples are either not affected by this change, or have been fixed to be compatible with this change

Changes

Updates pick and pick_grad in broadcast_reduce_op to handle negative indices
Updates pick to include a mode parameter ('pick' or 'wrap') to specify whether out of bounds indices should either be clipped or wrapped.

Comments

Making change as it was tagged with Call for Contribution

@perdasilva perdasilva requested a review from anirudh2290 as a code owner August 8, 2018 16:38
@perdasilva
Copy link
Contributor Author

Hi,

This is my first PR to the project and I'm still learning the ropes. Any and all suggestions would be much welcome. I'm not sure how to handle the case. For simplicity, I handled it with mod arithmetic. But in numpy, you can index in the range [-len, len). Which behaviour should be correct for this issue?
Should the cropping happen for indices < -1*len and >= len ?

Cheers,

Per

@@ -30,6 +30,41 @@
from common import setup_module, with_seed, teardown, assert_raises_cudnn_disabled, assertRaises
import unittest

@with_seed()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will move this back to its proper place - didn't get a chance as my family arrived home =P

@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch 2 times, most recently from efb0c4f to 975c9db Compare August 8, 2018 17:49
@haojin2
Copy link
Contributor

haojin2 commented Aug 8, 2018

Welcome to MXNet family!
I think you can use what I did for take operator as a reference: https://github.com/apache/incubator-mxnet/pull/11326/files#diff-ed06b8d9798aca630313f2a9dd3fcd68R316 for handling negative indices.

@@ -131,7 +130,7 @@ Examples::
pick(x, y=[0,1], 0) = [ 1., 4.]

// picks elements with specified indices along axis 1
pick(x, y=[0,1,0], 1) = [ 1., 4., 5.]
pick(x, y=[0,-1,0], 1) = [ 1., 4., 5.]
Copy link
Contributor

Choose a reason for hiding this comment

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

Please consider adding extra example for the newly supported case instead of modifying the existing cases.
For this case maybe you can do

pick(x, y=[0,1,0,-1], 1) = [ 1.,  4.,  5.,  4.]

@@ -4417,7 +4417,7 @@ def test_pick_helper(index_type=np.int32):
sshape = bshape.copy()
sshape[axis] = 1
data = np.random.uniform(-1, 1, size=bshape)
index = np.random.randint(0, bshape[axis], size=sshape)
index = np.random.randint(-1*bshape[axis], bshape[axis], size=sshape)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer -bshape[axis].

@eric-haibin-lin eric-haibin-lin added Operator pr-awaiting-response PR is reviewed and waiting for contributor to respond labels Aug 9, 2018
@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch 5 times, most recently from 0a4064b to a9fb7c2 Compare August 9, 2018 14:43
@perdasilva
Copy link
Contributor Author

Thank you for the welcome and guidance ^^
I hope I have done everything correctly. I've incorporated the mode into the currently existing pick test. I wonder if they should be split? Or maybe the pick_helper should be extended with the mode?

Cheers!!

Per

@@ -99,6 +99,10 @@ struct ReduceAxisParam : public dmlc::Parameter<ReduceAxisParam> {
}
};

namespace pick_ { // to avoid name conflict
enum TakeOpMode {kRaise, kWrap, kClip};
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer this to be like

enum PickOpMode {kWrap, kClip};

as we do not have raise mode at all.

Copy link
Contributor

Choose a reason for hiding this comment

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

This way you do not need the extra namespace either.

@@ -4417,7 +4417,12 @@ def test_pick_helper(index_type=np.int32):
sshape = bshape.copy()
sshape[axis] = 1
data = np.random.uniform(-1, 1, size=bshape)
index = np.random.randint(0, bshape[axis], size=sshape)
mode = np.random.choice(a=['clip', 'wrap'])
Copy link
Contributor

Choose a reason for hiding this comment

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

Please test both choices for mode using a for-loop instead of randomized testing for mode

@@ -117,7 +117,7 @@ an output array of shape ``(i0,)`` with::
output[i] = input[i, indices[i]]

By default, if any index mentioned is too large, it is replaced by the index that addresses
the last element along an axis (the `clip` mode).
the last element along an axis (the `clip` mode).
Copy link
Contributor

Choose a reason for hiding this comment

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

Please get rid of the unnecessary extra whitespace on this line.

@perdasilva
Copy link
Contributor Author

Will do. I kept the raise there to be consistent with the take implementation. Would you like me to remove raise from take?

@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch from a9fb7c2 to 0326116 Compare August 9, 2018 20:42
@perdasilva
Copy link
Contributor Author

Do you think it would make sense to test 'wrap' with the range -2*-bshape[axis]..2*bshape[axis]? To cover cases where one is wrapping more than the length of the axis in both directions? In my understanding, in numpy indices should generally be [-len, len). So, the current implementation diverges from that.

@haojin2
Copy link
Contributor

haojin2 commented Aug 10, 2018

@perdasilva Sorry for the late reply, I think adding more coverage is totally okay. Regarding the inconsistency with numpy, does this operator has some equivalent op in numpy? There is one for take, but this one I'm not sure.

@perdasilva
Copy link
Contributor Author

perdasilva commented Aug 10, 2018

@haojin2 No problem at all ^^
The only thing I could find that is similar to pick in numpy is numpy.choose. But there's no axis input there. It also seems that 'raise' is the default mode. Upon closer inspection, 'wrap' works the same here as with numpy. Interestingly though, np.array indexing is in the range [-len, len) ^^

I'll also increase the coverage for the test.

@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch from 0326116 to 8b23e19 Compare August 10, 2018 08:35
@haojin2
Copy link
Contributor

haojin2 commented Aug 10, 2018

@perdasilva So if there's no direct equivalence of this one in numpy then we may not need to match the behavior with numpy, please simply ensure we have enough documentation to document the behavior.

@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch from 8b23e19 to 21631b6 Compare August 11, 2018 10:25
@perdasilva
Copy link
Contributor Author

I believe that's all done now. Thanks for everything ^^

@perdasilva perdasilva changed the title [MXNET-791][WIP] Pick with negative indices [MXNET-791] Pick with negative indices Aug 11, 2018
@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch from 21631b6 to eb6baf0 Compare August 13, 2018 08:43
@perdasilva
Copy link
Contributor Author

@haojin2 I believe everything is done as specified. Please merge when you get a chance ^^

@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch 2 times, most recently from be8c120 to ecd90aa Compare August 15, 2018 08:34
Copy link
Contributor

@sandeep-krishnamurthy sandeep-krishnamurthy left a comment

Choose a reason for hiding this comment

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

Overall LGTM.
Thank you @perdasilva for the contributions and @haojin2 for reviewing the code.

I see dmlc-core is being updated with this PR. Is it due to recent revert @haojin2 ? How do we proceed here

.add_enum("wrap", kWrap)
.add_enum("clip", kClip)
.set_default(kClip)
.describe("Specify how out-of-bound indices bahave. Default is \"clip\"."
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: bahave-> behave

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch! Thank you!

@haojin2
Copy link
Contributor

haojin2 commented Aug 15, 2018

Please rebase with the latest master, then do a git submodule update --init --recursive, then do a git push --force origin <your-branch-name>

@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch 2 times, most recently from c106ef2 to 05e2915 Compare August 16, 2018 06:17
@perdasilva
Copy link
Contributor Author

@haojin2 @sandeep-krishnamurthy I've fixed the typo and done as hao jin asked. Thanks for the review guys ^^

@perdasilva
Copy link
Contributor Author

Hmm those dmlc changes seem to have persisted...strange

@perdasilva perdasilva force-pushed the feature/MXNET_791/pick_negative_indices branch from 05e2915 to 63bda11 Compare August 16, 2018 13:59
@perdasilva
Copy link
Contributor Author

Ok - Just did a soft reset, updated the submodule, then re-applied my commits. Seems to have fixed the issue =)

Copy link
Contributor

@sandeep-krishnamurthy sandeep-krishnamurthy left a comment

Choose a reason for hiding this comment

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

Thanks @perdasilva
LGTM.

@sandeep-krishnamurthy
Copy link
Contributor

@haojin2 - This PR is ready for merge after your approval.

@haojin2
Copy link
Contributor

haojin2 commented Aug 17, 2018

@sandeep-krishnamurthy Ready for merge.

@sandeep-krishnamurthy sandeep-krishnamurthy merged commit 633bef3 into apache:master Aug 17, 2018
marcoabreu added a commit that referenced this pull request Aug 17, 2018
piyushghai added a commit to piyushghai/incubator-mxnet that referenced this pull request Aug 17, 2018
XinYao1994 pushed a commit to XinYao1994/incubator-mxnet that referenced this pull request Aug 29, 2018
* Adds Per G. da Silva to CONTRIBUTORS.md

* Updates pick operation to also handle negative indices
@perdasilva perdasilva deleted the feature/MXNET_791/pick_negative_indices branch February 8, 2019 07:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Operator pr-awaiting-response PR is reviewed and waiting for contributor to respond
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants