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

Fix shape inference pass #14153

Merged
merged 5 commits into from
Mar 5, 2019
Merged

Conversation

ptrendx
Copy link
Member

@ptrendx ptrendx commented Feb 14, 2019

Description

This PR fixes shape inference, which currently results in wrong result for some cases.

An example problematic case (as it works in current version of MXNet, before applying this change):
If I do

import mxnet as mx

data = mx.sym.Variable('data', shape=(1,0,512,512))
weight = mx.sym.Variable('weight')
cdata = mx.sym.cast(data, dtype='float16')
cweight = mx.sym.cast(weight, dtype='float16')
test = mx.sym.Convolution(data=cdata, weight=cweight,layout='NCHW', pad=(3, 3), num_filter=64, stride=(2, 2), no_bias=True, dilate=(1, 1), kernel=(7, 7), num_group=1)

print(test.infer_shape_partial())

I get expected result:

([(1, 0, 512, 512), (64, 0, 7, 7)], [(1, 64, 256, 256)], [])

but when I change H and W dimensions in the shape to 0s,

import mxnet as mx

data = mx.sym.Variable('data', shape=(1,0,0,0))
weight = mx.sym.Variable('weight')
cdata = mx.sym.cast(data, dtype='float16')
cweight = mx.sym.cast(weight, dtype='float16')
test = mx.sym.Convolution(data=cdata, weight=cweight,layout='NCHW', pad=(3, 3), num_filter=64, stride=(2, 2), no_bias=True, dilate=(1, 1), kernel=(7, 7), num_group=1)

print(test.infer_shape_partial())

I get

([(1, 0, 0, 0), ()], [(1, 64, 0, 0)], [])

so the shape of the weight changed to ().

Checklist

Essentials

Please feel free to remove inapplicable items for your PR.

  • 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)
  • Code is well-documented:
  • For new C++ functions in header files, their functionalities and arguments are documented.
  • To the my best knowledge, examples are either not affected by this change, or have been fixed to be compatible with this change

Changes

  • Change to the way passes are done so that both forward and backward inference is performed every time - I'm not sure if this is necessary - @eric-haibin-lin, thoughts?
  • Change to the way shape inference works. Currently a shape contributes 1 to the num_unknown if it has at least 1 zero. After the change number of 0 elements is added to the num_unknown - that way shape inference pass does not end prematurely if only some of the elements of shape were deduced.

Comments

@ankkhedia
Copy link
Contributor

@ptrendx Thanks for your contribution! Could you please look into CI failures?

@mxnet-label-bot add [pr-awaiting-review , python]

@marcoabreu marcoabreu added pr-awaiting-review PR is waiting for code review Python labels Feb 14, 2019
Copy link
Member

@eric-haibin-lin eric-haibin-lin left a comment

Choose a reason for hiding this comment

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

Could you add an unit test for this?

@junrushao1994 @reminisce FYI ndim() API is used here.

src/executor/infer_graph_attr_pass.cc Outdated Show resolved Hide resolved
src/executor/infer_graph_attr_pass.cc Outdated Show resolved Hide resolved
src/executor/infer_graph_attr_pass.cc Outdated Show resolved Hide resolved
Copy link
Contributor

@reminisce reminisce left a comment

Choose a reason for hiding this comment

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

Thanks for the fix. I am not sure about the last two params. They were addd by @eric-haibin-lin. We can add comments in later PRs. This PR is good to merge.

* \param fdefault default function used for inference if the node does not
* provide its own implementation.
* \param scalars_only whether the inferred attribute may be only a scalar
* \param bwd_identity_assign TODO
Copy link
Contributor

Choose a reason for hiding this comment

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

Only equal to false in inferring storage types. It means whether the attributes of forward ndarray and backward ndarray are necessarily the same.

* provide its own implementation.
* \param scalars_only whether the inferred attribute may be only a scalar
* \param bwd_identity_assign TODO
* \param dispatch_mode_name TODO
Copy link
Member

Choose a reason for hiding this comment

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

Name of the dispatch mode attribute on the node. Used for storage type inference.

* \param scalars_only whether the inferred attribute may be only a scalar
* \param bwd_identity_assign TODO
* \param dispatch_mode_name TODO
* param default_mode_val TODO
Copy link
Member

Choose a reason for hiding this comment

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

Default value of the dispatch mode attribute on the node. Used for storage type inference.

@ptrendx
Copy link
Member Author

ptrendx commented Mar 1, 2019

@junrushao1994 I wanted to rebase this PR on top of the current master and I'm confused - in PR #14193 you made InferShapeAttr as a standalone function, but then in #14270 you changed InferShape to use generic InferAttr again. Was this intentional? Which one should I use then?

@junrushao
Copy link
Member

@ptrendx Sorry it is a mistake. I am actually working on two projects, dynamic shape and numpy operators. In dynamic shape, I should make infer shape pass standalone, but in numpy operator everything is just fine. I think these two projects interfere a bit.

@ptrendx
Copy link
Member Author

ptrendx commented Mar 1, 2019

Ok, so I should move it back to InferShapeAttr and make my changes there then?

@junrushao
Copy link
Member

@ptrendx Yes, please. I am so sorry for the inconvenience.

@ptrendx
Copy link
Member Author

ptrendx commented Mar 4, 2019

@junrushao1994 @reminisce I think this PR is good to go. Do you have any other comments?

Copy link
Member

@junrushao junrushao left a comment

Choose a reason for hiding this comment

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

LGTM.

This PR introduces fnum_unknown to the shape inference pass, which counts the number of unknown dimensions in an NDArray, and leverages this function to do shape inference more correctly.

@eric-haibin-lin eric-haibin-lin merged commit 427b6d4 into apache:master Mar 5, 2019
vdantu pushed a commit to vdantu/incubator-mxnet that referenced this pull request Mar 31, 2019
* Fix InferShape pass

* nnvm::TShape -> mxnet::TShape in InferShapeAttr

* More nnvm->mxnet namespace changes

* And more nnvm -> mxnet

* Retrigger CI
nswamy pushed a commit that referenced this pull request Apr 5, 2019
* Fix InferShape pass

* nnvm::TShape -> mxnet::TShape in InferShapeAttr

* More nnvm->mxnet namespace changes

* And more nnvm -> mxnet

* Retrigger CI
haohuanw pushed a commit to haohuanw/incubator-mxnet that referenced this pull request Jun 23, 2019
* Fix InferShape pass

* nnvm::TShape -> mxnet::TShape in InferShapeAttr

* More nnvm->mxnet namespace changes

* And more nnvm -> mxnet

* Retrigger CI
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
pr-awaiting-review PR is waiting for code review Python
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants