prior box operator for ssd#6150
prior box operator for ssd#6150wanghaox merged 12 commits intoPaddlePaddle:developfrom wanghaox:prior_box
Conversation
pkuyym
left a comment
There was a problem hiding this comment.
Maybe we can make PriorBoxOp more general to support both Faster RCNN and SSD, please refer the design of TensorFlow. Thanks.
paddle/operators/prior_box_op.cc
Outdated
|
|
||
| void InferShape(framework::InferShapeContext* ctx) const override { | ||
| PADDLE_ENFORCE(ctx->HasInput("Input"), | ||
| "Input(X) of SequenceSliceOp should not be null."); |
paddle/operators/prior_box_op.cc
Outdated
| PADDLE_ENFORCE(ctx->HasInput("Input"), | ||
| "Input(X) of SequenceSliceOp should not be null."); | ||
| PADDLE_ENFORCE(ctx->HasInput("Image"), | ||
| "Input(Offset) of SequenceSliceOp should not be null."); |
There was a problem hiding this comment.
Same as above.
I think we only use the shape of image. Is it necessary to pass the full image ?
There was a problem hiding this comment.
done
I think to pass the full image is easy for the user to use, and maybe easy to update algo. And the
| "The format of input tensor is NCHW."); | ||
|
|
||
| auto min_sizes = ctx->Attrs().Get<std::vector<int>>("min_sizes"); | ||
| auto max_sizes = ctx->Attrs().Get<std::vector<int>>("max_sizes"); |
There was a problem hiding this comment.
Any possible to make 'max_sizes' optional?
There was a problem hiding this comment.
add SetDefault({}) to max_sizes at line 126
paddle/operators/prior_box_op.cc
Outdated
| ctx->Attrs().Get<std::vector<float>>("aspect_ratios"); | ||
| bool flip = ctx->Attrs().Get<bool>("flip"); | ||
|
|
||
| PADDLE_ENFORCE_GT(min_sizes.size(), 0, "must provide min_size."); |
There was a problem hiding this comment.
Please refine this comment and make sure the first character is upper-case.
I think 'Size of min_size must be at least 1.' is more accurate.
paddle/operators/prior_box_op.cc
Outdated
| PADDLE_ENFORCE_GT(step_w, 0.0, "step_w should be larger than 0."); | ||
|
|
||
| const int layer_height = input_dims[3]; | ||
| const int layer_width = input_dims[2]; |
There was a problem hiding this comment.
The shape of input is NCHW or NCWH?
paddle/operators/prior_box_op.cc
Outdated
| dim_vec[2] = layer_width * layer_height * num_priors * 4; | ||
| PADDLE_ENFORCE_GT(dim_vec[2], 0, | ||
| "output_dim[2] must larger than 0." | ||
| "check your data dims"); |
There was a problem hiding this comment.
If possible, please find the illegal input. For example, layer_width is illegal or layer_height is illegal etc.
There was a problem hiding this comment.
done, add PADDLE_ENFORCE(input_dims.size() == 4) and check layer_width or layer_height is smaller than image's.
paddle/operators/prior_box_op.cc
Outdated
| framework::OpAttrChecker* op_checker) | ||
| : OpProtoAndCheckerMaker(proto, op_checker) { | ||
| AddInput("Input", | ||
| "(Tensor), " |
There was a problem hiding this comment.
Please give type info like default Tensor<float>.
paddle/operators/prior_box_op.cc
Outdated
| : OpProtoAndCheckerMaker(proto, op_checker) { | ||
| AddInput("Input", | ||
| "(Tensor), " | ||
| "the input feature data of PriorBoxOp."); |
There was a problem hiding this comment.
Lack shape information and no need to start in a newline.
paddle/operators/prior_box_op.cc
Outdated
|
|
||
| void InferShape(framework::InferShapeContext* ctx) const override { | ||
| PADDLE_ENFORCE(ctx->HasInput("Input"), | ||
| "Input(X) of SequenceSliceOp should not be null."); |
paddle/operators/prior_box_op.cc
Outdated
| PADDLE_ENFORCE(ctx->HasInput("Input"), | ||
| "Input(X) of SequenceSliceOp should not be null."); | ||
| PADDLE_ENFORCE(ctx->HasInput("Image"), | ||
| "Input(Offset) of SequenceSliceOp should not be null."); |
There was a problem hiding this comment.
done
I think to pass the full image is easy for the user to use, and maybe easy to update algo. And the
| "The format of input tensor is NCHW."); | ||
|
|
||
| auto min_sizes = ctx->Attrs().Get<std::vector<int>>("min_sizes"); | ||
| auto max_sizes = ctx->Attrs().Get<std::vector<int>>("max_sizes"); |
There was a problem hiding this comment.
add SetDefault({}) to max_sizes at line 126
paddle/operators/prior_box_op.cc
Outdated
| ctx->Attrs().Get<std::vector<float>>("aspect_ratios"); | ||
| bool flip = ctx->Attrs().Get<bool>("flip"); | ||
|
|
||
| PADDLE_ENFORCE_GT(min_sizes.size(), 0, "must provide min_size."); |
paddle/operators/prior_box_op.cc
Outdated
| PADDLE_ENFORCE_GT(step_w, 0.0, "step_w should be larger than 0."); | ||
|
|
||
| const int layer_height = input_dims[3]; | ||
| const int layer_width = input_dims[2]; |
paddle/operators/prior_box_op.cc
Outdated
| dim_vec[2] = layer_width * layer_height * num_priors * 4; | ||
| PADDLE_ENFORCE_GT(dim_vec[2], 0, | ||
| "output_dim[2] must larger than 0." | ||
| "check your data dims"); |
There was a problem hiding this comment.
done, add PADDLE_ENFORCE(input_dims.size() == 4) and check layer_width or layer_height is smaller than image's.
paddle/operators/prior_box_op.cc
Outdated
| framework::OpAttrChecker* op_checker) | ||
| : OpProtoAndCheckerMaker(proto, op_checker) { | ||
| AddInput("Input", | ||
| "(Tensor), " |
paddle/operators/prior_box_op.cc
Outdated
| : OpProtoAndCheckerMaker(proto, op_checker) { | ||
| AddInput("Input", | ||
| "(Tensor), " | ||
| "the input feature data of PriorBoxOp."); |
paddle/operators/prior_box_op.h
Outdated
| inline void expand_aspect_ratios(const std::vector<float> input_aspect_ratior, | ||
| bool flip, | ||
| std::vector<float>& output_aspect_ratior) { | ||
| constexpr float eps = 1e-6; |
There was a problem hiding this comment.
eps建议epsilon,在重构后的版本中看到好像都用这个词。
另外这个建议做成参数
paddle/operators/prior_box_op.cc
Outdated
There was a problem hiding this comment.
Need to explain 2, layer_height, layer_width, num_priors, 4. Need more explanation for the layout.
paddle/operators/prior_box_op.cc
Outdated
There was a problem hiding this comment.
Why need attrs of img_w and img_h?
paddle/operators/prior_box_op.cc
Outdated
There was a problem hiding this comment.
Why need .SetDefault({}) ?
paddle/operators/prior_box_op.cc
Outdated
There was a problem hiding this comment.
I think we need to give more doc for this operator, how to generator box? how to calculate the number of prior boxes, and so on?
The TF doc is:
There was a problem hiding this comment.
I cannot see any information in this comments.
paddle/operators/prior_box_op.cu
Outdated
There was a problem hiding this comment.
If not implement the GPU, do not need to register GPU kernel.
paddle/operators/prior_box_op.h
Outdated
There was a problem hiding this comment.
int64_t, since the type in input->dims() is int64_t
paddle/operators/prior_box_op.h
Outdated
There was a problem hiding this comment.
Now support multi-device, there is no need to copy tensor from GPU to CPU.
paddle/operators/prior_box_op.h
Outdated
There was a problem hiding this comment.
这里的clip看下能不能调用Eigen的函数,而不是4层for循环。
There was a problem hiding this comment.
可以参考 https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/operators/compare_op.h#L72 ,用 platform::Transform 也行。
paddle/operators/prior_box_op.h
Outdated
There was a problem hiding this comment.
同上,这种赋值,看看下能不能调用Eigen的函数,而不是4层for循环。
There was a problem hiding this comment.
Python单测需要改进,尽量向量操作,不用这么多层的for循环。
paddle/operators/prior_box_op.cc
Outdated
paddle/operators/prior_box_op.cc
Outdated
paddle/operators/prior_box_op.cc
Outdated
paddle/operators/prior_box_op.cc
Outdated
paddle/operators/prior_box_op.cc
Outdated
paddle/operators/prior_box_op.cc
Outdated
paddle/operators/prior_box_op.h
Outdated
paddle/operators/prior_box_op.h
Outdated
paddle/operators/prior_box_op.h
Outdated
| inline void expand_aspect_ratios(const std::vector<float> input_aspect_ratior, | ||
| bool flip, | ||
| std::vector<float>& output_aspect_ratior) { | ||
| constexpr float eps = 1e-6; |
paddle/operators/prior_box_op.cc
Outdated
| AddAttr<std::vector<float>>( | ||
| "aspect_ratios", "(vector<float>) ", | ||
| "List of aspect ratios of generated prior boxes.") | ||
| .SetDefault({}); |
There was a problem hiding this comment.
Remove .SetDefault({}) too.
paddle/operators/prior_box_op.cc
Outdated
| } | ||
| } | ||
|
|
||
| if (variances.size() > 1) { |
There was a problem hiding this comment.
It seems line 68 should be removed.
paddle/operators/prior_box_op.h
Outdated
| for (int w = 0; w < layer_width; ++w) { | ||
| float center_x = (w + offset) * step_width; | ||
| float center_y = (h + offset) * step_height; | ||
| float box_width, box_height; |
There was a problem hiding this comment.
template <typename Place, typename T>
If T is double, here also should be double.
| center_x + box_width / 2.) / self.image_w | ||
| # ymax | ||
| out_boxes[h, w, idx, 3] = ( | ||
| center_y + box_height / 2.) / self.image_h |
There was a problem hiding this comment.
这块代码可以简化下,
c_x = (w + self.offset) * self.step_w
c_y = (h + self.offset) * self.step_h
# ...
c_w = c_h = min_size/2.
out_boxes[h, w, idx, :] = [(c_x - c_w)/self.image_w, (c_y - c_h)/self.image_h, ..., ...]
# ...下面两处计算相同,可以使代码更短一些。
paddle/operators/prior_box_op.cc
Outdated
|
|
||
| void InferShape(framework::InferShapeContext* ctx) const override { | ||
| PADDLE_ENFORCE(ctx->HasInput("Input"), | ||
| "Input(X) of PriorBoxOp should not be null."); |
There was a problem hiding this comment.
Not Input(X), should be Input(Input).
paddle/operators/prior_box_op.cc
Outdated
| PADDLE_ENFORCE(ctx->HasInput("Input"), | ||
| "Input(X) of PriorBoxOp should not be null."); | ||
| PADDLE_ENFORCE(ctx->HasInput("Image"), | ||
| "Input(Offset) of PriorBoxOp should not be null."); |
There was a problem hiding this comment.
Input(Offset) --> Input(Image)
paddle/operators/prior_box_op.cc
Outdated
|
|
||
| auto image_dims = ctx->GetInputDim("Image"); | ||
| auto input_dims = ctx->GetInputDim("Input"); | ||
| PADDLE_ENFORCE(image_dims.size() == 4, "The format of image is NCHW."); |
There was a problem hiding this comment.
I think The layout of data is NCHW is better.
paddle/operators/prior_box_op.cc
Outdated
| bool flip = ctx->Attrs().Get<bool>("flip"); | ||
|
|
||
| PADDLE_ENFORCE_GT(min_sizes.size(), 0, | ||
| "Size of min_size must be at least 1."); |
paddle/operators/prior_box_op.cc
Outdated
| int num_priors = aspect_ratios_vec.size() * min_sizes.size(); | ||
| if (max_sizes.size() > 0) { | ||
| PADDLE_ENFORCE_EQ(max_sizes.size(), min_sizes.size(), | ||
| "The length of min_size and max_size must be equal."); |
|
|
||
| auto min_sizes = ctx->Attrs().Get<std::vector<int>>("min_sizes"); | ||
| auto max_sizes = ctx->Attrs().Get<std::vector<int>>("max_sizes"); | ||
| auto variances = ctx->Attrs().Get<std::vector<float>>("variances"); |
There was a problem hiding this comment.
Should be variances optional?
There was a problem hiding this comment.
here variances are needed for output "Variances"
paddle/operators/prior_box_op.h
Outdated
| boxes->data<T>(), clip_func); | ||
| } | ||
|
|
||
| Eigen::Tensor<T, 2, Eigen::RowMajor> var_et(1, variances.size()); |
There was a problem hiding this comment.
I think it is more efficiency to use framework::Tensor whose memory is allocated from internal pool. @qingqing01 Please help to confirm.
There was a problem hiding this comment.
Yeah, should use Fluid's memory (or Tenosr) to allocate auxiliary workspace.
paddle/operators/prior_box_op.cc
Outdated
| AddOutput("Boxes", | ||
| "(Tensor, default Tensor<float>), the output prior boxes of " | ||
| "PriorBoxOp. The layout is [layer_height, layer_width, " | ||
| "num_priors, 4]. layer_height is the height of input, " |
There was a problem hiding this comment.
layer_height -> H,
layer_width -> W
same as below.
paddle/operators/prior_box_op.h
Outdated
| auto img_height = image->dims()[2]; | ||
|
|
||
| auto layer_width = input->dims()[3]; | ||
| auto layer_height = input->dims()[2]; |
There was a problem hiding this comment.
layer_width -> feature_width or width.
Same as layer_height
resolve #6015