Skip to content

Commit

Permalink
Phi prior box (#44431)
Browse files Browse the repository at this point in the history
* phi_prior_box

* add float[] support

* phi_prior_box_optest

* update
  • Loading branch information
zhiboniu authored Jul 30, 2022
1 parent 46be685 commit d92b2f2
Show file tree
Hide file tree
Showing 12 changed files with 667 additions and 101 deletions.
87 changes: 8 additions & 79 deletions paddle/fluid/operators/detection/prior_box_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/operators/detection/prior_box_op.h"

#include <string>
#include "paddle/fluid/framework/infershape_utils.h"
#include "paddle/phi/infermeta/binary.h"

#ifdef PADDLE_WITH_MKLDNN
#include "paddle/fluid/platform/mkldnn_helper.h"
Expand All @@ -28,79 +29,6 @@ class PriorBoxOp : public framework::OperatorWithKernel {
public:
using framework::OperatorWithKernel::OperatorWithKernel;

void InferShape(framework::InferShapeContext* ctx) const override {
OP_INOUT_CHECK(ctx->HasInput("Input"), "Input", "Input", "PriorBoxOp");
OP_INOUT_CHECK(ctx->HasInput("Image"), "Input", "Image", "PriorBoxOp");

auto image_dims = ctx->GetInputDim("Image");
auto input_dims = ctx->GetInputDim("Input");

PADDLE_ENFORCE_EQ(
image_dims.size(),
4,
platform::errors::InvalidArgument(
"The Input(Image) of Op(PriorBoxOp) should be a 4-D Tensor "
"and data format is NCHW. But received Image's dimensions = %d, "
"shape = [%s].",
image_dims.size(),
image_dims));
PADDLE_ENFORCE_EQ(
input_dims.size(),
4,
platform::errors::InvalidArgument(
"The Input(Input) of Op(PriorBoxOp) should be a 4-D Tensor "
"and data format is NCHW. But received Input's dimensions = %d, "
"shape = [%s].",
input_dims.size(),
input_dims));

auto min_sizes = ctx->Attrs().Get<std::vector<float>>("min_sizes");
auto max_sizes = ctx->Attrs().Get<std::vector<float>>("max_sizes");
auto variances = ctx->Attrs().Get<std::vector<float>>("variances");
auto aspect_ratios = ctx->Attrs().Get<std::vector<float>>("aspect_ratios");
bool flip = ctx->Attrs().Get<bool>("flip");

std::vector<float> aspect_ratios_vec;
ExpandAspectRatios(aspect_ratios, flip, &aspect_ratios_vec);

size_t num_priors = aspect_ratios_vec.size() * min_sizes.size();
if (max_sizes.size() > 0) {
PADDLE_ENFORCE_EQ(
max_sizes.size(),
min_sizes.size(),
platform::errors::InvalidArgument(
"The length of min_size and "
"max_size must be equal. But received: min_size's length is %d, "
"max_size's length is %d.",
min_sizes.size(),
max_sizes.size()));
num_priors += max_sizes.size();
for (size_t i = 0; i < max_sizes.size(); ++i) {
PADDLE_ENFORCE_GT(
max_sizes[i],
min_sizes[i],
platform::errors::InvalidArgument(
"max_size[%d] must be greater "
"than min_size[%d]. But received: max_size[%d] is %f, "
"min_size[%d] is %f.",
i,
i,
i,
max_sizes[i],
i,
min_sizes[i]));
}
}

std::vector<int64_t> dim_vec(4);
dim_vec[0] = input_dims[2];
dim_vec[1] = input_dims[3];
dim_vec[2] = num_priors;
dim_vec[3] = 4;
ctx->SetOutputDim("Boxes", phi::make_ddim(dim_vec));
ctx->SetOutputDim("Variances", phi::make_ddim(dim_vec));
}

protected:
framework::OpKernelType GetExpectedKernelType(
const framework::ExecutionContext& ctx) const override {
Expand Down Expand Up @@ -274,17 +202,18 @@ Please get more information from the following papers:
} // namespace operators
} // namespace paddle

DECLARE_INFER_SHAPE_FUNCTOR(prior_box,
PriorBoxInferShapeFunctor,
PD_INFER_META(phi::PriorBoxInferMeta));

namespace ops = paddle::operators;
REGISTER_OPERATOR(
prior_box,
ops::PriorBoxOp,
ops::PriorBoxOpMaker,
paddle::framework::EmptyGradOpMaker<paddle::framework::OpDesc>,
paddle::framework::EmptyGradOpMaker<paddle::imperative::OpBase>);

REGISTER_OP_CPU_KERNEL(prior_box,
ops::PriorBoxOpKernel<float, float>,
ops::PriorBoxOpKernel<double, double>);
paddle::framework::EmptyGradOpMaker<paddle::imperative::OpBase>,
PriorBoxInferShapeFunctor);

REGISTER_OP_KERNEL_WITH_CUSTOM_TYPE(prior_box,
MKLDNN,
Expand Down
5 changes: 0 additions & 5 deletions paddle/fluid/operators/detection/prior_box_op.cu
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,3 @@ class PriorBoxOpCUDAKernel : public framework::OpKernel<T> {

} // namespace operators
} // namespace paddle

namespace ops = paddle::operators;
REGISTER_OP_CUDA_KERNEL(prior_box,
ops::PriorBoxOpCUDAKernel<float>,
ops::PriorBoxOpCUDAKernel<double>);
2 changes: 1 addition & 1 deletion paddle/phi/api/yaml/generator/api_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def parse_input_and_attr(self, api_name, args_config, optional_vars=[]):
'DataLayout': 'DataLayout',
'DataType': 'DataType',
'int64_t[]': 'const std::vector<int64_t>&',
'int[]': 'const std::vector<int>&'
'int[]': 'const std::vector<int>&',
}
optional_types_trans = {
'Tensor': 'const paddle::optional<Tensor>&',
Expand Down
8 changes: 8 additions & 0 deletions paddle/phi/api/yaml/legacy_api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1791,6 +1791,14 @@
func : prelu
backward : prelu_grad

- api : prior_box
args : (Tensor input, Tensor image, float[] min_sizes, float[] aspect_ratios, float[] variances, float[] max_sizes = {}, bool flip=true, bool clip=true, float step_w=0.0, float step_h=0.0, float offset=0.5, bool min_max_aspect_ratios_order=false)
output : Tensor(out), Tensor(var)
infer_meta :
func : PriorBoxInferMeta
kernel :
func : prior_box

- api : psroi_pool
args : (Tensor x, Tensor boxes, Tensor boxes_num, int pooled_height, int pooled_width, int output_channels, float spatial_scale)
output : Tensor
Expand Down
104 changes: 104 additions & 0 deletions paddle/phi/infermeta/binary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1809,6 +1809,110 @@ void PReluInferMeta(const MetaTensor& x,
out->share_lod(x);
}

inline void ExpandAspectRatios(const std::vector<float>& input_aspect_ratior,
bool flip,
std::vector<float>* output_aspect_ratior) {
constexpr float epsilon = 1e-6;
output_aspect_ratior->clear();
output_aspect_ratior->push_back(1.0f);
for (size_t i = 0; i < input_aspect_ratior.size(); ++i) {
float ar = input_aspect_ratior[i];
bool already_exist = false;
for (size_t j = 0; j < output_aspect_ratior->size(); ++j) {
if (fabs(ar - output_aspect_ratior->at(j)) < epsilon) {
already_exist = true;
break;
}
}
if (!already_exist) {
output_aspect_ratior->push_back(ar);
if (flip) {
output_aspect_ratior->push_back(1.0f / ar);
}
}
}
}

void PriorBoxInferMeta(const MetaTensor& input,
const MetaTensor& image,
const std::vector<float>& min_sizes,
const std::vector<float>& aspect_ratios,
const std::vector<float>& variances,
const std::vector<float>& max_sizes,
bool flip,
bool clip,
float step_w,
float step_h,
float offset,
bool min_max_aspect_ratios_order,
MetaTensor* out,
MetaTensor* var) {
auto image_dims = image.dims();
auto input_dims = input.dims();

PADDLE_ENFORCE_EQ(
image_dims.size(),
4,
phi::errors::InvalidArgument(
"The Input(Image) of Op(PriorBoxOp) should be a 4-D Tensor "
"and data format is NCHW. But received Image's dimensions = %d, "
"shape = [%s].",
image_dims.size(),
image_dims));
PADDLE_ENFORCE_EQ(
input_dims.size(),
4,
phi::errors::InvalidArgument(
"The Input(Input) of Op(PriorBoxOp) should be a 4-D Tensor "
"and data format is NCHW. But received Input's dimensions = %d, "
"shape = [%s].",
input_dims.size(),
input_dims));

std::vector<float> aspect_ratios_vec;
ExpandAspectRatios(aspect_ratios, flip, &aspect_ratios_vec);

size_t num_priors = aspect_ratios_vec.size() * min_sizes.size();
if (max_sizes.size() > 0) {
PADDLE_ENFORCE_EQ(
max_sizes.size(),
min_sizes.size(),
phi::errors::InvalidArgument(
"The length of min_size and "
"max_size must be equal. But received: min_size's length is %d, "
"max_size's length is %d.",
min_sizes.size(),
max_sizes.size()));
num_priors += max_sizes.size();
for (size_t i = 0; i < max_sizes.size(); ++i) {
PADDLE_ENFORCE_GT(
max_sizes[i],
min_sizes[i],
phi::errors::InvalidArgument(
"max_size[%d] must be greater "
"than min_size[%d]. But received: max_size[%d] is %f, "
"min_size[%d] is %f.",
i,
i,
i,
max_sizes[i],
i,
min_sizes[i]));
}
}

std::vector<int64_t> dim_vec(4);
dim_vec[0] = input_dims[2];
dim_vec[1] = input_dims[3];
dim_vec[2] = num_priors;
dim_vec[3] = 4;

out->set_dtype(input.dtype());
var->set_dtype(input.dtype());
out->set_dims(phi::make_ddim(dim_vec));
var->set_dims(phi::make_ddim(dim_vec));
}

void SearchsortedInferMeta(const MetaTensor& sorted_sequence,
const MetaTensor& value,
bool out_int32,
Expand Down
15 changes: 15 additions & 0 deletions paddle/phi/infermeta/binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,21 @@ void PReluInferMeta(const MetaTensor& x,
MetaTensor* out,
MetaConfig config = MetaConfig());

void PriorBoxInferMeta(const MetaTensor& input,
const MetaTensor& image,
const std::vector<float>& min_sizes,
const std::vector<float>& aspect_ratios,
const std::vector<float>& variances,
const std::vector<float>& max_sizes,
bool flip,
bool clip,
float step_w,
float step_h,
float offset,
bool min_max_aspect_ratios_order,
MetaTensor* out,
MetaTensor* var);

void SearchsortedInferMeta(const MetaTensor& sorted_sequence,
const MetaTensor& value,
bool out_int32,
Expand Down
Loading

0 comments on commit d92b2f2

Please sign in to comment.