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

【PaddlePaddle Hackathon 2】11新增 API index_fill 【错误分支请删除】 #42453

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
115 changes: 115 additions & 0 deletions paddle/fluid/operators/index_fill_op.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <memory>
#include "paddle/fluid/framework/infershape_utils.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/op_version_registry.h"
#include "paddle/phi/core/infermeta_utils.h"
#include "paddle/phi/infermeta/binary.h"

namespace paddle {
namespace operators {

class IndexFillOp : public framework::OperatorWithKernel {
public:
using framework::OperatorWithKernel::OperatorWithKernel;

framework::OpKernelType GetExpectedKernelType(
const framework::ExecutionContext& ctx) const override {
return framework::OpKernelType(
OperatorWithKernel::IndicateVarDataType(ctx, "X"), ctx.GetPlace());
}
};

class IndexFillOpMaker : public framework::OpProtoAndCheckerMaker {
public:
void Make() override {
AddInput("X",
"(Tensor, default input Tensor<float>), "
"the input feature data of IndexFillOp, dtype should be"
"int32, int64, float16, float32, float64.");
AddInput("Index",
"(Tensor, default 1-d Tensor<int>), "
"the 1-D tensor containing the indices to index, "
"dtype should be int32, int64");
AddAttr<int>("axis",
"(int, default 0), "
"the dimension in which we index.")
.SetDefault(0);
AddAttr<float>("fill_value",
"(float, default 0.0f) The value to be filled.")
.SetDefault(0.0f);
AddOutput("Out",
"(Tensor, default Tensor<float>),"
" the output of IndexFillOp, whose dtype is the same as X.");
AddComment(R"DOC(
IndexFill operator
Fills the elements of the input tensor with value
by selecting the indices in the order given in index.

This operator also supports inplace modification.
)DOC");
}
};

template <typename T>
class IndexFillGradMaker : public framework::SingleGradOpMaker<T> {
public:
using framework::SingleGradOpMaker<T>::SingleGradOpMaker;

void Apply(GradOpPtr<T> op) const override {
op->SetType("index_fill_grad");
op->SetInput("Index", this->Input("Index"));
op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));
op->SetOutput(framework::GradVarName("X"), this->InputGrad("X"));
op->SetAttrMap(this->Attrs());
}
};

class IndexFillGradOp : public framework::OperatorWithKernel {
public:
using framework::OperatorWithKernel::OperatorWithKernel;

protected:
framework::OpKernelType GetExpectedKernelType(
const framework::ExecutionContext& ctx) const override {
return framework::OpKernelType(OperatorWithKernel::IndicateVarDataType(
ctx, framework::GradVarName("Out")),
ctx.GetPlace());
}
};

DECLARE_INPLACE_OP_INFERER(IndexFillInplaceInferer, {"X", "Out"});
DECLARE_INPLACE_OP_INFERER(IndexFillGradInplaceInferer,
{framework::GradVarName("Out"),
framework::GradVarName("X")});
DECLARE_NO_NEED_BUFFER_VARS_INFERER(IndexFillGradNoNeedBufferVarsInferer, "X");

} // namespace operators
} // namespace paddle

namespace ops = paddle::operators;
DECLARE_INFER_SHAPE_FUNCTOR(index_fill, IndexFillInferShapeFunctor,
PD_INFER_META(phi::IndexFillInferMeta));

REGISTER_OPERATOR(index_fill, ops::IndexFillOp, ops::IndexFillOpMaker,
ops::IndexFillGradMaker<paddle::framework::OpDesc>,
ops::IndexFillGradMaker<paddle::imperative::OpBase>,
ops::IndexFillInplaceInferer, IndexFillInferShapeFunctor);

DECLARE_INFER_SHAPE_FUNCTOR(index_fill_grad, IndexFillGradInferShapeFunctor,
PD_INFER_META(phi::IndexFillGradInferMeta));

REGISTER_OPERATOR(index_fill_grad, ops::IndexFillGradOp,
ops::IndexFillGradInplaceInferer,
ops::IndexFillGradNoNeedBufferVarsInferer,
IndexFillGradInferShapeFunctor);
120 changes: 120 additions & 0 deletions paddle/fluid/operators/nanmedian_op.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*Copyright (c) 2019 PaddlePaddle Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <memory>
#include "paddle/fluid/framework/infershape_utils.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/op_version_registry.h"
#include "paddle/phi/core/infermeta_utils.h"
#include "paddle/phi/infermeta/unary.h"

namespace paddle {
namespace operators {

class NanmedianOp : public framework::OperatorWithKernel {
public:
using framework::OperatorWithKernel::OperatorWithKernel;

framework::OpKernelType GetExpectedKernelType(
const framework::ExecutionContext& ctx) const override {
return framework::OpKernelType(
OperatorWithKernel::IndicateVarDataType(ctx, "X"), ctx.GetPlace());
}
};

class NanmedianOpMaker : public framework::OpProtoAndCheckerMaker {
public:
void Make() override {
AddInput("X",
"(Tensor, default Tensor<float>), "
"the input feature data of NanmedianOp, dtype should be"
"int32, int64, float16, float32, float64.");
AddAttr<bool>(
"ignore_nan",
"(bool, default true) Set to true if nan values should be ignored. "
"Set to false when no nan value in x were considered. ")
.SetDefault(true);
AddOutput("Medians",
"The calculation differs in the odd or even of the valid "
"elements amount."
"Along the axis, two elements contributed to the median value in "
"each row."
"If the amount of valid elements were even, both were the same.")
.AsIntermediate()
.AsExtra();
AddOutput("Out",
"(Tensor, default Tensor<float>),"
" the output of NanmedianOp, whose dtype is the same as X");
AddComment(R"DOC(
Nanmedian operator

This operator is considered as an extention of median operation,
which supports specifically the case of nan values in the input.

If all the elements in input are NaN it will also return NaN.
If no elements in input are Nan, this op is identical to thie median op.

This operator can also supports multiple axis,
and could be switched to median operator when `ignore_nan` were set to False.
)DOC");
}
};

template <typename T>
class NanmedianGradMaker : public framework::SingleGradOpMaker<T> {
public:
using framework::SingleGradOpMaker<T>::SingleGradOpMaker;

void Apply(GradOpPtr<T> op) const override {
op->SetType("nanmedian_grad");
op->SetInput("X", this->Input("X"));
op->SetInput("Medians", this->Output("Medians"));
op->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));
op->SetOutput(framework::GradVarName("X"), this->InputGrad("X"));
}
};

class NanmedianGradOp : public framework::OperatorWithKernel {
public:
using framework::OperatorWithKernel::OperatorWithKernel;

void InferShape(framework::InferShapeContext* ctx) const override {
OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "nanmedian");
OP_INOUT_CHECK(ctx->HasInput("Medians"), "Input", "Medians", "nanmedian");
OP_INOUT_CHECK(ctx->HasInput(framework::GradVarName("Out")), "Input",
framework::GradVarName("Out"), "nanmedian");

auto x_dims = ctx->GetInputDim("X");
ctx->SetOutputDim(framework::GradVarName("X"), x_dims);
}

protected:
framework::OpKernelType GetExpectedKernelType(
const framework::ExecutionContext& ctx) const override {
return framework::OpKernelType(OperatorWithKernel::IndicateVarDataType(
ctx, framework::GradVarName("Out")),
ctx.GetPlace());
}
};

} // namespace operators
} // namespace paddle

namespace ops = paddle::operators;
DECLARE_INFER_SHAPE_FUNCTOR(nanmedian, NanmedianInferShapeFunctor,
PD_INFER_META(phi::NanmedianInferMeta));

REGISTER_OPERATOR(nanmedian, ops::NanmedianOp, ops::NanmedianOpMaker,
ops::NanmedianGradMaker<paddle::framework::OpDesc>,
ops::NanmedianGradMaker<paddle::imperative::OpBase>,
NanmedianInferShapeFunctor);

REGISTER_OPERATOR(nanmedian_grad, ops::NanmedianGradOp);
51 changes: 51 additions & 0 deletions paddle/phi/infermeta/binary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,57 @@ void HuberLossInferMeta(const MetaTensor& input,
out->share_lod(input);
}

void IndexFillInferMeta(const MetaTensor& x,
const MetaTensor& index,
int axis,
float fill_value,
MetaTensor* output) {
auto input_dim = x.dims();
auto index_dim = index.dims();

PADDLE_ENFORCE_EQ(
axis < input_dim.size() && axis >= (0 - input_dim.size()),
true,
phi::errors::OutOfRange(
"Attr(axis) is out of range, It's expected "
"to be in range of [-%d, %d]. But received Attr(dim) = %d.",
input_dim.size(),
input_dim.size() - 1,
axis));

PADDLE_ENFORCE_EQ(
index_dim.size() == 1 || (index_dim.size() == 2 && index_dim[1] == 1),
true,
phi::errors::InvalidArgument(
"The 'shape' of Input(Index) must be 1-D tensor. "
"But received: the 'shape' of Input(Index) is [%s], "
"the dimension of Input(Index) is [%d].",
index_dim,
index_dim.size()));

PADDLE_ENFORCE_EQ(
index_dim[0] != 0,
true,
phi::errors::InvalidArgument("The length of Input(Index) can't be 0."));

output->set_dims(x.dims());
output->set_dtype(x.dtype());
output->set_layout(x.layout());
output->share_lod(x);
}

void IndexFillGradInferMeta(const MetaTensor& out_grad,
const MetaTensor& index,
int axis,
float fill_value,
MetaTensor* x_grad) {
auto do_dims = out_grad.dims();
x_grad->set_dims(do_dims);
x_grad->set_dtype(out_grad.dtype());
x_grad->set_layout(out_grad.layout());
x_grad->share_lod(out_grad);
}

void IndexSampleInferMeta(const MetaTensor& x,
const MetaTensor& y,
MetaTensor* out,
Expand Down
12 changes: 12 additions & 0 deletions paddle/phi/infermeta/binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,18 @@ void HuberLossInferMeta(const MetaTensor& input_meta,
MetaTensor* residual,
MetaConfig config = MetaConfig());

void IndexFillInferMeta(const MetaTensor& x,
const MetaTensor& index,
int axis,
float fill_value,
MetaTensor* output);

void IndexFillGradInferMeta(const MetaTensor& out_grad,
const MetaTensor& index,
int axis,
float fill_value,
MetaTensor* x_grad);

void IndexSampleInferMeta(const MetaTensor& x,
const MetaTensor& y,
MetaTensor* out,
Expand Down
24 changes: 24 additions & 0 deletions paddle/phi/infermeta/unary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,30 @@ void MultinomialInferMeta(const MetaTensor& x,
out->set_dtype(DataType::INT64);
}

void NanmedianInferMeta(const MetaTensor& x,
bool ignore_nan,
MetaTensor* out,
MetaTensor* medians) {
auto x_dim = x.dims();
int64_t x_rank = x_dim.size();

std::vector<int64_t> out_dims(x_rank);
std::vector<int64_t> median_dims(x_rank);
for (int64_t i = 0; i < x_rank - 1; i++) {
out_dims[i] = x_dim[i];
median_dims[i] = x_dim[i];
}

out_dims[x_rank - 1] = 1;
median_dims[x_rank - 1] = 2;

out->set_dims(make_ddim(out_dims));
out->set_dtype(x.dtype());

medians->set_dims(make_ddim(median_dims));
medians->set_dtype(x.dtype());
}

void NormInferMeta(const MetaTensor& x,
int axis,
float epsilon,
Expand Down
6 changes: 6 additions & 0 deletions paddle/phi/infermeta/unary.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ void MultinomialInferMeta(const MetaTensor& x,
int num_samples,
bool replacement,
MetaTensor* out);

void NanmedianInferMeta(const MetaTensor& x,
bool ignore_nan,
MetaTensor* out,
MetaTensor* medians);

void NormInferMeta(const MetaTensor& x,
int axis,
float epsilon,
Expand Down
Loading