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

Add nn.AdaptiveAvgPool1d and nn.AdaptiveAvgPool3d #5445

Merged
merged 42 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
db27cdc
Generalize 'AdaptiveAvgPool' for 1~3 dims usage
Jul 9, 2021
99a13ac
Implement GPU version
Jul 15, 2021
ecbe95a
Enable pooling with larger 'output_size' which is supported by PyTorch
Jul 16, 2021
53ba214
Add docs for 'AdaptiveAvgPool1d' and 'AdaptiveAvgPool3d'
Jul 16, 2021
d86d3d7
Add functional API for 'AdaptiveAvgPoolXd'
Jul 16, 2021
221d756
Add 'flow.adaptive_avg_poolxd'
Jul 16, 2021
81ffa32
Add test cases for 'flow.adaptive_avg_poolxd'
Jul 16, 2021
ddfbe6f
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 16, 2021
008c842
auto format by CI
oneflow-ci-bot Jul 16, 2021
8741e25
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 16, 2021
51a94d8
Avoid using 'Shape::Count' in for loop
Jul 17, 2021
c66882e
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 18, 2021
d848cc5
Change names of compute functions
Jul 18, 2021
c7187d4
Change 'AdaptivePoolNdGradOp' to functor
Jul 18, 2021
5b790eb
Register integer types for CUDA 'adaptive_avg_poolxd' kernel
Jul 18, 2021
78af94a
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 18, 2021
59f8c8d
Integrate 'adaptive_avg_poolxd' into 'nn.functional.interpolate'
Jul 19, 2021
97dd698
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 19, 2021
33923b5
Correct wrong 'AdaptiveAvgPoolXd' entries
Jul 19, 2021
f7bf773
Merge branch 'add_adaptive_avg_pool_xd' of github.com:Oneflow-Inc/one…
Jul 19, 2021
2803cb6
Add missing 'not None' assertions for 'output_size'
Jul 19, 2021
aa70d48
Support tuple input for 'AdaptiveAvgPool1d'
Jul 19, 2021
0067493
Mark TODO for auto testing 'AdaptiveAvgPoolXd'
Jul 19, 2021
3956b16
Denote return types for 'BackwardOpConfGenFn'
Jul 19, 2021
54ea555
Combine test classes of 'AdaptiveAvgPoolXd' into one
Jul 19, 2021
d9f5dfc
Rename 'AvgXXXCompute'
Jul 19, 2021
1cc90f6
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 19, 2021
3df1154
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 19, 2021
da43e00
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 19, 2021
e82c5f8
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 19, 2021
301c56f
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 19, 2021
96343a8
Merge branch 'master' into add_adaptive_avg_pool_xd
oneflow-ci-bot Jul 21, 2021
b37f407
auto format by CI
oneflow-ci-bot Jul 21, 2021
b6e8d4e
Simplify output shape inference
Jul 21, 2021
bc8ca32
Merge branch 'add_adaptive_avg_pool_xd' of github.com:Oneflow-Inc/one…
Jul 21, 2021
932b16e
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 21, 2021
24421fc
Merge branch 'master' into add_adaptive_avg_pool_xd
oneflow-ci-bot Jul 21, 2021
dbfc987
Delete the wrong 'if' block
Jul 21, 2021
db00657
Merge branch 'add_adaptive_avg_pool_xd' of github.com:Oneflow-Inc/one…
Jul 21, 2021
c3db14a
Merge branch 'master' into add_adaptive_avg_pool_xd
oneflow-ci-bot Jul 21, 2021
63681ab
Merge branch 'master' into add_adaptive_avg_pool_xd
Jul 21, 2021
92a1e0b
Merge branch 'master' into add_adaptive_avg_pool_xd
oneflow-ci-bot Jul 21, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/source/experimental.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,12 @@ Experimental features
.. autofunction:: oneflow.experimental.nn.AvgPool1d
.. autofunction:: oneflow.experimental.nn.AvgPool2d
.. autofunction:: oneflow.experimental.nn.AvgPool3d
.. autofunction:: oneflow.experimental.nn.AdaptiveAvgPool1d
.. autofunction:: oneflow.experimental.nn.AdaptiveAvgPool2d
.. autofunction:: oneflow.experimental.nn.AdaptiveAvgPool3d
.. autofunction:: oneflow.experimental.adaptive_avg_pool1d
.. autofunction:: oneflow.experimental.adaptive_avg_pool2d
.. autofunction:: oneflow.experimental.adaptive_avg_pool3d
.. autofunction:: oneflow.experimental.nn.MaxPool1d
.. autofunction:: oneflow.experimental.nn.MaxPool2d
.. autofunction:: oneflow.experimental.nn.MaxPool3d
Expand Down
43 changes: 31 additions & 12 deletions oneflow/core/autograd/gradient_funcs/adaptive_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ limitations under the License.
#include "oneflow/core/framework/op_expr.h"
#include "oneflow/core/framework/op_expr_helper.h"
#include "oneflow/core/framework/op_interpreter/op_interpreter_util.h"
#include "oneflow/core/functional/functional.h"

namespace oneflow {
namespace one {
Expand All @@ -26,49 +27,67 @@ struct AdaptivePoolInterpState : public OpExprInterpState {
bool requires_grad;
};

class AdaptivePool : public OpExprGradFunction<AdaptivePoolInterpState> {
class AdaptivePoolNdGrad : public OpExprGradFunction<AdaptivePoolInterpState> {
public:
Maybe<void> Init(const OpExpr& op) override;
Maybe<void> Init(const OpExpr& op, std::string mode, const int& ndims);
Maybe<void> Capture(AdaptivePoolInterpState* ctx, const TensorTuple& inputs,
const TensorTuple& outputs, const AttrMap& attrs) const override;
Maybe<void> Apply(const AdaptivePoolInterpState* ctx, const TensorTuple& out_grads,
TensorTuple* in_grads) const override;

private:
AttrMap base_attrs_;
std::shared_ptr<OpExpr> grad_op_;
std::string mode_;
int32_t ndims_;
};

Maybe<void> AdaptivePool::Init(const OpExpr& op) {
Maybe<void> AdaptivePoolNdGrad::Init(const OpExpr& op, std::string mode, const int& ndims) {
const UserOpExpr* fw_op_expr = dynamic_cast<const UserOpExpr*>(&op);
CHECK_NOTNULL_OR_RETURN(fw_op_expr);
base_attrs_ = MakeAttrMapFromUserOpConf(fw_op_expr->proto());
const std::string& op_name = fw_op_expr->op_name();
grad_op_ = JUST(op_expr_helper::AdaptivePoolGradOp(GradientOpName(op_name)));
mode_ = mode;
ndims_ = ndims;
return Maybe<void>::Ok();
}

Maybe<void> AdaptivePool::Capture(AdaptivePoolInterpState* ctx, const TensorTuple& inputs,
const TensorTuple& outputs, const AttrMap& attrs) const {
Maybe<void> AdaptivePoolNdGrad::Capture(AdaptivePoolInterpState* ctx, const TensorTuple& inputs,
const TensorTuple& outputs, const AttrMap& attrs) const {
ctx->requires_grad = inputs.at(0)->requires_grad();
if (!ctx->requires_grad) { return Maybe<void>::Ok(); }

ctx->SaveTensorForBackward(inputs.at(0));
return Maybe<void>::Ok();
}

Maybe<void> AdaptivePool::Apply(const AdaptivePoolInterpState* ctx, const TensorTuple& out_grads,
TensorTuple* in_grads) const {
Maybe<void> AdaptivePoolNdGrad::Apply(const AdaptivePoolInterpState* ctx,
const TensorTuple& out_grads, TensorTuple* in_grads) const {
if (!ctx->requires_grad) { return Maybe<void>::Ok(); }
CHECK_EQ_OR_RETURN(out_grads.size(), 1);

const std::shared_ptr<oneflow::one::Tensor>& x = ctx->SavedTensors().at(0);
in_grads->resize(1);
in_grads->at(0) = JUST(OpInterpUtil::Dispatch<Tensor>(*grad_op_, {x, out_grads.at(0)}));
in_grads->at(0) = JUST(functional::AdaptivePoolNdGrad(x, out_grads.at(0), mode_, ndims_));
return Maybe<void>::Ok();
}

REGISTER_OP_EXPR_GRAD_FUNCTION("adaptive_avg_pool2d", AdaptivePool);
class AdaptiveAvgPool1dGrad final : public AdaptivePoolNdGrad {
public:
Maybe<void> Init(const OpExpr& op) override { return AdaptivePoolNdGrad::Init(op, "avg", 1); }
};

class AdaptiveAvgPool2dGrad final : public AdaptivePoolNdGrad {
public:
Maybe<void> Init(const OpExpr& op) override { return AdaptivePoolNdGrad::Init(op, "avg", 2); }
};

class AdaptiveAvgPool3dGrad final : public AdaptivePoolNdGrad {
public:
Maybe<void> Init(const OpExpr& op) override { return AdaptivePoolNdGrad::Init(op, "avg", 3); }
};

REGISTER_OP_EXPR_GRAD_FUNCTION("adaptive_avg_pool1d", AdaptiveAvgPool1dGrad);
REGISTER_OP_EXPR_GRAD_FUNCTION("adaptive_avg_pool2d", AdaptiveAvgPool2dGrad);
REGISTER_OP_EXPR_GRAD_FUNCTION("adaptive_avg_pool3d", AdaptiveAvgPool3dGrad);

} // namespace one
} // namespace oneflow
11 changes: 0 additions & 11 deletions oneflow/core/framework/op_expr_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -852,17 +852,6 @@ Maybe<one::UserOpExpr> PoolNdGradOp(const std::string& mode, const std::string&
.Build();
}

Maybe<one::UserOpExpr> AdaptivePoolGradOp() {
return AdaptivePoolGradOp(UniqueOpName("adaptive_pool_grad"));
}
Maybe<one::UserOpExpr> AdaptivePoolGradOp(const std::string& name) {
return one::OpBuilder("adaptive_avg_pool2d_grad", name)
.Input("x")
.Input("dy")
.Output("dx")
.Build();
}

Maybe<one::UserOpExpr> UnsortedSegmentSumLikeOp(const int64_t& axis) {
return UnsortedSegmentSumLikeOp(axis, UniqueOpName("unsorted_segment_sum_like"));
}
Expand Down
3 changes: 0 additions & 3 deletions oneflow/core/framework/op_expr_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,6 @@ Maybe<one::UserOpExpr> PoolNdGradOp(const std::string& mode, const std::string&
const std::vector<int32_t>& strides, const bool& ceil_mode,
const std::string& name);

Maybe<one::UserOpExpr> AdaptivePoolGradOp();
Maybe<one::UserOpExpr> AdaptivePoolGradOp(const std::string& name);

Maybe<one::UserOpExpr> UnsortedSegmentSumLikeOp(const int64_t& axis);
Maybe<one::UserOpExpr> UnsortedSegmentSumLikeOp(const int64_t& axis, const std::string& name);

Expand Down
19 changes: 19 additions & 0 deletions oneflow/core/functional/functional_api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,25 @@
String data_format=\"channels_first\", Bool ceil_mode=False)"
bind_python: True

- name: "adaptive_avg_pool1d"
signature:
"Tensor AdaptiveAvgPool1D(Tensor x, *, Int64List output_size)"
bind_python: True

- name: "adaptive_avg_pool2d"
signature:
"Tensor AdaptiveAvgPool2D(Tensor x, *, Int64List output_size)"
bind_python: True

- name: "adaptive_avg_pool3d"
signature:
"Tensor AdaptiveAvgPool3D(Tensor x, *, Int64List output_size)"
bind_python: True

- name: "adaptive_pool_grad"
signature:
"Tensor AdaptivePoolNdGrad(Tensor x, Tensor dy, *, String mode, Int32 ndims)"

- name: "pool_grad"
signature:
"Tensor PoolNdGrad(Tensor x, Tensor y, Tensor dy, *, String mode, Int32 ndims, String data_format,
Expand Down
39 changes: 39 additions & 0 deletions oneflow/core/functional/impl/nn_functor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,42 @@ class Maxpool3DFunctor : public PoolingNDFunctor {
}
};

class AdaptivePoolNDFunctor {
public:
AdaptivePoolNDFunctor() = default;
virtual ~AdaptivePoolNDFunctor() = default;
Maybe<Tensor> operator()(const std::shared_ptr<one::Tensor>& x,
const std::vector<int64_t>& output_size) const {
MutableAttrMap attrs;
JUST(attrs.SetAttr<std::vector<int64_t>>("output_size", output_size));
return OpInterpUtil::Dispatch<Tensor>(*op_, {x}, attrs);
}

protected:
std::shared_ptr<OpExpr> op_;
};

class AdaptiveAvgPool1DFunctor : public AdaptivePoolNDFunctor {
public:
AdaptiveAvgPool1DFunctor() {
op_ = CHECK_JUST(one::OpBuilder("adaptive_avg_pool1d").Input("x").Output("y").Build());
}
};

class AdaptiveAvgPool2DFunctor : public AdaptivePoolNDFunctor {
public:
AdaptiveAvgPool2DFunctor() {
op_ = CHECK_JUST(one::OpBuilder("adaptive_avg_pool2d").Input("x").Output("y").Build());
}
};

class AdaptiveAvgPool3DFunctor : public AdaptivePoolNDFunctor {
public:
AdaptiveAvgPool3DFunctor() {
op_ = CHECK_JUST(one::OpBuilder("adaptive_avg_pool3d").Input("x").Output("y").Build());
}
};

class SparseSoftmaxCrossEntropyFunctor {
public:
SparseSoftmaxCrossEntropyFunctor() {
Expand Down Expand Up @@ -479,6 +515,9 @@ ONEFLOW_FUNCTION_LIBRARY(m) {
m.add_functor<impl::Maxpool2DFunctor>("Maxpool2D");
m.add_functor<impl::Maxpool3DFunctor>("Maxpool3D");
m.add_functor<impl::MaxPool2DFunctor>("MaxPool2D");
m.add_functor<impl::AdaptiveAvgPool1DFunctor>("AdaptiveAvgPool1D");
m.add_functor<impl::AdaptiveAvgPool2DFunctor>("AdaptiveAvgPool2D");
m.add_functor<impl::AdaptiveAvgPool3DFunctor>("AdaptiveAvgPool3D");
m.add_functor<impl::SparseSoftmaxCrossEntropyFunctor>("SparseSoftmaxCrossEntropy");
m.add_functor<impl::SmoothL1LossFunctor>("SmoothL1Loss");
m.add_functor<impl::NormalizationFunctor>("Normalization");
Expand Down
30 changes: 30 additions & 0 deletions oneflow/core/functional/impl/nn_grad_functor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,35 @@ class PoolNdGradFunctor {
std::unordered_map<std::string, std::shared_ptr<OpExpr>> op_expr_map_;
};

class AdaptivePoolNdGradFunctor {
public:
AdaptivePoolNdGradFunctor() {
for (const auto& mode : {"avg"}) {
for (int ndims = 1; ndims <= 3; ++ndims) {
const auto& op_type_name = GetOpTypeName(mode, ndims);
op_expr_map_[op_type_name] =
CHECK_JUST(one::OpBuilder(op_type_name).Input("x").Input("dy").Output("dx").Build());
}
}
}
static std::string GetOpTypeName(const std::string& mode, const int32_t& ndims) {
return "adaptive_" + mode + "_pool" + std::to_string(ndims) + "d_grad";
}
Maybe<Tensor> operator()(const std::shared_ptr<one::Tensor>& x,
const std::shared_ptr<one::Tensor>& dy, const std::string& mode,
const int32_t& ndims) const {
const auto& op_type_name = GetOpTypeName(mode, ndims);
const auto& it = op_expr_map_.find(op_type_name);
CHECK_OR_RETURN(it != op_expr_map_.end())
<< "Encounter unsupported op " << op_type_name << " in AdaptivePoolNdGradFunctor.";
CHECK_NOTNULL_OR_RETURN(it->second);
return OpInterpUtil::Dispatch<Tensor>(*it->second, {x, dy});
}

protected:
std::unordered_map<std::string, std::shared_ptr<OpExpr>> op_expr_map_;
};

class SmoothL1LossGradFunctor {
public:
SmoothL1LossGradFunctor() {
Expand Down Expand Up @@ -281,6 +310,7 @@ ONEFLOW_FUNCTION_LIBRARY(m) {
m.add_functor<impl::ConvFilterGradFunctor>("ConvFilterGrad");
m.add_functor<impl::ConvDataGradFunctor>("ConvDataGrad");
m.add_functor<impl::PoolNdGradFunctor>("PoolNdGrad");
m.add_functor<impl::AdaptivePoolNdGradFunctor>("AdaptivePoolNdGrad");
m.add_functor<impl::SmoothL1LossGradFunctor>("SmoothL1LossGrad");
m.add_functor<impl::PoolingNdGradFunctor>("PoolingNdGrad");
m.add_functor<impl::PadGradFunctor>("PadGrad");
Expand Down
Loading