!26399 [assistant][ops] Add CropAndResizeGradBoxes

Merge pull request !26399 from wangyantao/CropAndResizeGradBoxes
This commit is contained in:
i-robot 2022-03-26 09:41:38 +00:00 committed by Gitee
commit d66af6eb86
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 678 additions and 0 deletions

View File

@ -0,0 +1,260 @@
/**
* Copyright 2021 Huawei Technologies Co., Ltd
*
* 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 "plugin/device/cpu/kernel/crop_and_resize_grad_boxes_cpu_kernel.h"
#include "plugin/device/cpu/hal/device/cpu_device_address.h"
namespace mindspore {
namespace kernel {
void CropAndResizeGradBoxesCpuKernelMod::InitKernel(const CNodePtr &kernel_node) {
MS_EXCEPTION_IF_NULL(kernel_node);
kernel_name_ = common::AnfAlgo::GetCNodeName(kernel_node);
// input grads
grads_shape_ = common::AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, kGrads);
size_t input_grads_shape_len = grads_shape_.size();
if (input_grads_shape_len != kGradsShapeLen) {
MS_LOG(ERROR) << "Grads tensor is " << input_grads_shape_len << "-D, but CropAndResizeGradBoxes supports only "
<< kGradsShapeLen << "-D for grads tensor.";
}
// input image
image_shape_ = common::AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, kImages);
size_t input_image_shape_len = image_shape_.size();
if (input_image_shape_len != kImageShapeLen) {
MS_LOG(ERROR) << "Images tensor is " << input_image_shape_len << "-D, but CropAndResizeGradBoxes supports only "
<< kImageShapeLen << "-D for images tensor.";
}
// input boxes
boxes_shape_ = common::AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, kBoxes);
size_t input_boxes_shape_len = boxes_shape_.size();
if (input_boxes_shape_len != kBoxesShapeLen) {
MS_LOG(ERROR) << "Boxes tensor is " << input_boxes_shape_len << "-D, but CropAndResizeGradBoxes supports only "
<< kBoxesShapeLen << "-D for boxes tensor.";
}
if (boxes_shape_[1] != kCoordinateLen) {
MS_LOG(ERROR) << "The coordinate size of boxes is " << boxes_shape_[1]
<< ", but CropAndResizeGradBoxes supports only " << kCoordinateLen << "for boxes.";
}
// input box_index
box_in_shape_ = common::AnfAlgo::GetPrevNodeOutputInferShape(kernel_node, kBoxIndex);
size_t input_box_index_shape_len = box_in_shape_.size();
if (input_box_index_shape_len != kBoxIndexShapeLen) {
MS_LOG(ERROR) << "Box_index tensor is " << input_box_index_shape_len
<< "-D, but CropAndResizeGradBoxes supports only " << kBoxIndexShapeLen << "-D for box_index.";
}
// output
output_shape_ = common::AnfAlgo::GetOutputInferShape(kernel_node, kOutputIndex);
auto output_shape_len = output_shape_.size();
if (output_shape_len != kOutputShapeLen) {
MS_LOG(ERROR) << "Output tensor is " << output_shape_len << "-D, but CropAndResizeGradBoxes supports only "
<< kOutputShapeLen << "-D for output tensor.";
}
auto kernel_attr = GetKernelAttrFromNode(kernel_node);
auto [is_match, index] = MatchKernelAttr(kernel_attr, GetOpSupport());
if (!is_match) {
MS_LOG(EXCEPTION) << "Concat does not support this kernel data type: " << kernel_attr;
}
kernel_func_ = func_list_[index].second;
}
void CropAndResizeGradBoxesCpuKernelMod::OutputZeroing(const std::vector<kernel::AddressPtr> &outputs) {
auto *outputDatas = reinterpret_cast<float *>(outputs[0]->addr);
const int nums_boxes = grads_shape_[0];
int num = nums_boxes * kCoordinateLen;
float zero_num = static_cast<float>(0);
for (int i = 0; i < num; i++) {
*(outputDatas + i) = zero_num;
}
}
template <typename T>
bool CropAndResizeGradBoxesCpuKernelMod::LaunchKernel(const std::vector<kernel::AddressPtr> &inputs,
const std::vector<kernel::AddressPtr> &outputs) {
CHECK_KERNEL_INPUTS_NUM(inputs.size(), kInputNums, kernel_name_);
CHECK_KERNEL_OUTPUTS_NUM(outputs.size(), kOutNum, kernel_name_);
auto *grads = reinterpret_cast<float *>(inputs[kGrads]->addr);
auto *image = reinterpret_cast<T *>(inputs[kImages]->addr);
auto *boxes = reinterpret_cast<float *>(inputs[kBoxes]->addr);
auto *box_ind = reinterpret_cast<int *>(inputs[kBoxIndex]->addr);
auto *outputDatas = reinterpret_cast<float *>(outputs[0]->addr);
const int image_batch = image_shape_[kBatch];
const int image_height = image_shape_[kHeight];
const int image_width = image_shape_[kWidth];
const int depth = image_shape_[kDepth];
const int nums_boxes = grads_shape_[kNumBoxes];
const int crop_height = grads_shape_[kHeight];
const int crop_width = grads_shape_[kWidth];
const int crop_depth = grads_shape_[kDepth];
const int boxesCoordinateNum = boxes_shape_[1];
const int num_image2 = image_height * image_width * depth;
const int num_image3 = image_width * depth;
const int num_crop2 = crop_height * crop_width * crop_depth;
const int num_crop3 = crop_width * crop_depth;
// Output zeroing.
OutputZeroing(outputs);
for (int b = 0; b < nums_boxes; b++) {
const float y1 = *(boxes + b * boxesCoordinateNum + kCoordY1);
const float x1 = *(boxes + b * boxesCoordinateNum + kCoordX1);
const float y2 = *(boxes + b * boxesCoordinateNum + kCoordY2);
const float x2 = *(boxes + b * boxesCoordinateNum + kCoordX2);
const int b_in = *(box_ind + b);
if (b_in >= image_batch || b_in < 0) {
continue;
}
const float height_ratio = (crop_height > 1) ? static_cast<float>(image_height - 1) / (crop_height - 1) : 0;
const float width_ratio = (crop_width > 1) ? static_cast<float>(image_width - 1) / (crop_width - 1) : 0;
const float height_scale = (crop_height > 1) ? (y2 - y1) * height_ratio : 0;
const float width_scale = (crop_width > 1) ? (x2 - x1) * width_ratio : 0;
for (int y = 0; y < crop_height; y++) {
const float y_in =
(crop_height > 1) ? y1 * (image_height - 1) + y * height_scale : 0.5 * (y1 + y2) * (image_height - 1);
if (y_in < 0 || y_in > image_height - 1) {
continue;
}
const int top_y_index = floorf(y_in);
const int bottom_y_index = ceilf(y_in);
const float y_lerp = y_in - top_y_index;
for (int x = 0; x < crop_width; x++) {
const float x_in =
(crop_width > 1) ? x1 * (image_width - 1) + x * width_scale : 0.5 * (x1 + x2) * (image_width - 1);
if (x_in < 0 || x_in > image_width - 1) {
continue;
}
const int left_x_ind = floorf(x_in);
const int right_x_ind = ceilf(x_in);
const float x_lerp = x_in - left_x_ind;
for (int d = 0; d < depth; d++) {
const float top_left_value(
static_cast<float>(*(image + b_in * num_image2 + top_y_index * num_image3 + left_x_ind * depth + d)));
const float top_right_value(
static_cast<float>(*(image + b_in * num_image2 + top_y_index * num_image3 + right_x_ind * depth + d)));
const float bottom_left_value(
static_cast<float>(*(image + b_in * num_image2 + bottom_y_index * num_image3 + left_x_ind * depth + d)));
const float bottom_right_value(
static_cast<float>(*(image + b_in * num_image2 + bottom_y_index * num_image3 + right_x_ind * depth + d)));
// Compute the image gradient
float image_ygrad_value =
(1 - x_lerp) * (bottom_left_value - top_left_value) + x_lerp * (bottom_right_value - top_right_value);
float image_xgrad_value =
(1 - y_lerp) * (top_right_value - top_left_value) + y_lerp * (bottom_right_value - bottom_left_value);
// Modulate the image gradient with the incoming gradient
const float top_grad = *(grads + b * num_crop2 + y * num_crop3 + x * crop_depth + d);
image_ygrad_value *= top_grad;
image_xgrad_value *= top_grad;
// dy1,dy2
if (crop_height > 1) {
*(outputDatas + b * kCoordinateLen + 0) += image_ygrad_value * (image_height - 1 - y * height_ratio);
*(outputDatas + b * kCoordinateLen + kCoordY2) += image_ygrad_value * (y * height_ratio);
} else {
*(outputDatas + b * kCoordinateLen + kCoordY1) += image_ygrad_value * kNum * (image_height - 1);
*(outputDatas + b * kCoordinateLen + kCoordY2) += image_ygrad_value * kNum * (image_height - 1);
}
// dx1,dx2
if (crop_width > 1) {
*(outputDatas + b * kCoordinateLen + kCoordX1) += image_xgrad_value * (image_width - 1 - x * width_ratio);
*(outputDatas + b * kCoordinateLen + kCoordX2) += image_xgrad_value * (x * width_ratio);
} else {
*(outputDatas + b * kCoordinateLen + kCoordX1) += image_xgrad_value * kNum * (image_width - 1);
*(outputDatas + b * kCoordinateLen + kCoordX2) += image_xgrad_value * kNum * (image_width - 1);
}
}
}
}
}
return true;
}
std::vector<std::pair<KernelAttr, CropAndResizeGradBoxesCpuKernelMod::CropAndResizeGradBoxesFunc>>
CropAndResizeGradBoxesCpuKernelMod::func_list_ = {{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeUInt8)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<uint8_t>},
{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeUInt16)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<uint16_t>},
{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt8)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<int8_t>},
{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt16)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<int16_t>},
{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<int32_t>},
{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt64)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<int64_t>},
{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeFloat16)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<float16>},
{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<float>},
{KernelAttr()
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeFloat64)
.AddInputAttr(kNumberTypeFloat32)
.AddInputAttr(kNumberTypeInt32)
.AddOutputAttr(kNumberTypeFloat32),
&CropAndResizeGradBoxesCpuKernelMod::LaunchKernel<double>}};
std::vector<KernelAttr> CropAndResizeGradBoxesCpuKernelMod::GetOpSupport() {
std::vector<KernelAttr> support_list;
(void)std::transform(func_list_.begin(), func_list_.end(), std::back_inserter(support_list),
[](const std::pair<KernelAttr, CropAndResizeGradBoxesFunc> &pair) { return pair.first; });
return support_list;
}
MS_KERNEL_FACTORY_REG(NativeCpuKernelMod, CropAndResizeGradBoxes, CropAndResizeGradBoxesCpuKernelMod);
} // namespace kernel
} // namespace mindspore

View File

@ -0,0 +1,88 @@
/**
* Copyright 2021 Huawei Technologies Co., Ltd
*
* 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.
*/
#ifndef MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_CROP_AND_RESIZE_GRAD_BOXES_CPU_KERNEL_H_
#define MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_CROP_AND_RESIZE_GRAD_BOXES_CPU_KERNEL_H_
#include <vector>
#include <string>
#include <algorithm>
#include <memory>
#include <utility>
#include "plugin/device/cpu/kernel/cpu_kernel.h"
#include "plugin/factory/ms_factory.h"
namespace mindspore {
namespace kernel {
constexpr size_t kInputNums = 4;
constexpr size_t kOutNum = 1;
constexpr size_t kGrads = 0;
constexpr size_t kGradsShapeLen = 4;
constexpr size_t kNumBoxes = 0;
constexpr size_t kHeight = 1;
constexpr size_t kWidth = 2;
constexpr size_t kDepth = 3;
constexpr size_t kBatch = 0;
constexpr size_t kImages = 1;
constexpr size_t kImageShapeLen = 4;
constexpr size_t kBoxes = 2;
constexpr size_t kCoordY1 = 0;
constexpr size_t kCoordX1 = 1;
constexpr size_t kCoordY2 = 2;
constexpr size_t kCoordX2 = 3;
constexpr size_t kBoxesShapeLen = 2;
constexpr size_t kCoordinateLen = 4;
constexpr size_t kBoxIndex = 3;
constexpr size_t kBoxIndexShapeLen = 1;
constexpr size_t kOutputIndex = 0;
constexpr size_t kOutputShapeLen = 2;
constexpr float kNum = 0.5;
class CropAndResizeGradBoxesCpuKernelMod : public NativeCpuKernelMod {
public:
CropAndResizeGradBoxesCpuKernelMod() = default;
~CropAndResizeGradBoxesCpuKernelMod() override = default;
void InitKernel(const CNodePtr &kernel_node) override;
bool Launch(const std::vector<AddressPtr> &inputs, const std::vector<AddressPtr> &,
const std::vector<AddressPtr> &outputs) override {
return kernel_func_(this, inputs, outputs);
}
void OutputZeroing(const std::vector<AddressPtr> &outputs);
protected:
std::vector<KernelAttr> GetOpSupport() override;
private:
template <typename T>
bool LaunchKernel(const std::vector<kernel::AddressPtr> &inputs, const std::vector<kernel::AddressPtr> &outputs);
using CropAndResizeGradBoxesFunc =
std::function<bool(CropAndResizeGradBoxesCpuKernelMod *, const std::vector<kernel::AddressPtr> &,
const std::vector<kernel::AddressPtr> &)>;
static std::vector<std::pair<KernelAttr, CropAndResizeGradBoxesFunc>> func_list_;
CropAndResizeGradBoxesFunc kernel_func_;
std::vector<size_t> grads_shape_;
std::vector<size_t> image_shape_;
std::vector<size_t> boxes_shape_;
std::vector<size_t> box_in_shape_;
std::vector<size_t> output_shape_;
};
} // namespace kernel
} // namespace mindspore
#endif // MINDSPORE_CCSRC_BACKEND_KERNEL_COMPILER_CPU_CROP_AND_RESIZE_GRAD_BOXES_CPU_KERNEL_H_

View File

@ -38,6 +38,9 @@ constexpr auto kAddcdiv = "Addcdiv";
constexpr auto kAddcmul = "Addcmul";
constexpr auto kCdist = "Cdist";
constexpr auto kCdistGrad = "CdistGrad";
// image
constexpr auto kCropAndResizeGradBoxes = "CropAndResizeGradBoxes";
// Arithmetic
constexpr auto kScalarAdd = "ScalarAdd";
constexpr auto kScalarSub = "ScalarSub";
@ -369,6 +372,9 @@ GVAR_DEF(PrimitivePtr, kPrimLowerBound, std::make_shared<Primitive>(kLowerBound)
GVAR_DEF(PrimitivePtr, kPrimUpperBound, std::make_shared<Primitive>(kUpperBound));
GVAR_DEF(PrimitivePtr, kPrimCummax, std::make_shared<Primitive>(kCummax));
// image
GVAR_DEF(PrimitivePtr, kPrimCropAndResizeGradBoxes, std::make_shared<Primitive>(kCropAndResizeGradBoxes));
// NN
GVAR_DEF(PrimitivePtr, kPrimCeLU, std::make_shared<Primitive>("CeLU"));
GVAR_DEF(PrimitivePtr, kPrimAdam, std::make_shared<Primitive>("Adam"));

View File

@ -0,0 +1,116 @@
/**
* Copyright 2021 Huawei Technologies Co., Ltd
*
* 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 "ops/crop_and_resize_grad_boxes.h"
#include <set>
#include <memory>
#include "utils/check_convert_utils.h"
#include "ops/op_utils.h"
#include "mindapi/src/helper.h"
#include "abstract/primitive_infer_map.h"
namespace mindspore {
namespace ops {
void CropAndResizeGradBoxes::Init(ResizeMethod method) { this->set_method(method); }
void CropAndResizeGradBoxes::set_method(ResizeMethod method) {
auto swi = (int64_t)method;
(void)this->AddAttr(kMethod, api::MakeValue(swi));
}
ResizeMethod CropAndResizeGradBoxes::get_method() const {
auto value_ptr = GetAttr(kMethod);
return ResizeMethod(GetValue<int64_t>(value_ptr));
}
namespace {
constexpr size_t kInputNums = 4;
constexpr size_t kGrads = 0;
constexpr size_t kGradsShapeLen = 4;
constexpr size_t kHeight = 1;
constexpr size_t kWidth = 2;
constexpr size_t kDepth = 3;
constexpr size_t kImages = 1;
constexpr size_t kImageShapeLen = 4;
constexpr size_t kBoxes = 2;
constexpr size_t kBoxesShapeLen = 2;
constexpr size_t kCoordinateLen = 4;
constexpr size_t kBoxIndex = 3;
constexpr size_t kBoxIndShapeLen = 1;
abstract::ShapePtr CropAndResizeGradBoxesInferShape(const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
MS_EXCEPTION_IF_NULL(primitive);
auto prim_name = primitive->name();
// Infer shape
auto input_shape0 = CheckAndConvertUtils::ConvertShapePtrToShapeMap(input_args[kGrads]->BuildShape())[kShape];
(void)CheckAndConvertUtils::CheckInteger("grads rank", SizeToLong(input_shape0.size()), kEqual, kGradsShapeLen,
prim_name);
auto input_shape1 = CheckAndConvertUtils::ConvertShapePtrToShapeMap(input_args[kImages]->BuildShape())[kShape];
(void)CheckAndConvertUtils::CheckInteger("images rank", SizeToLong(input_shape1.size()), kEqual, kImageShapeLen,
prim_name);
auto input_shape2 = CheckAndConvertUtils::ConvertShapePtrToShapeMap(input_args[kBoxes]->BuildShape())[kShape];
(void)CheckAndConvertUtils::CheckInteger("boxes rank", SizeToLong(input_shape2.size()), kEqual, kBoxesShapeLen,
prim_name);
(void)CheckAndConvertUtils::CheckInteger("shape[1] of boxes", SizeToLong(input_shape2[1]), kEqual, kCoordinateLen,
prim_name);
auto input_shape3 = CheckAndConvertUtils::ConvertShapePtrToShapeMap(input_args[kBoxIndex]->BuildShape())[kShape];
(void)CheckAndConvertUtils::CheckInteger("box_index rank", SizeToLong(input_shape3.size()), kEqual, kBoxIndShapeLen,
prim_name);
if (!(input_shape1[kHeight] > 0 && input_shape1[kWidth] > 0)) {
MS_EXCEPTION(ValueError) << "the height and width of images must be over 0 ";
}
if (!(input_shape0[kHeight] > 0 && input_shape0[kWidth] > 0)) {
MS_EXCEPTION(ValueError) << "the height and width of grads must be over 0 ";
}
if (!(input_shape0[0] == input_shape3[0] && input_shape2[0] == input_shape0[0])) {
MS_EXCEPTION(ValueError) << "the first dimension of the tensors in {grads, boxes, box_index} must be equal.";
}
if (input_shape0[kDepth] != input_shape1[kDepth]) {
MS_EXCEPTION(ValueError) << "the depth of grads and images must be equal.";
}
return std::make_shared<abstract::Shape>(input_shape2);
}
TypePtr CropAndResizeGradBoxesInferType(const PrimitivePtr &prim, const std::vector<AbstractBasePtr> &input_args) {
for (const auto &item : input_args) {
MS_EXCEPTION_IF_NULL(item);
}
MS_EXCEPTION_IF_NULL(prim);
auto prim_name = prim->name();
(void)CheckAndConvertUtils::CheckInputArgs(input_args, kEqual, kInputNums, prim_name);
const std::set<TypePtr> valid_types = {kInt8, kInt16, kInt32, kInt64, kUInt8, kUInt16, kFloat16, kFloat32, kFloat64};
(void)CheckAndConvertUtils::CheckTensorTypeValid("grads", input_args[kGrads]->BuildType(), {kFloat32}, prim_name);
(void)CheckAndConvertUtils::CheckTensorTypeValid("images", input_args[kImages]->BuildType(), valid_types, prim_name);
(void)CheckAndConvertUtils::CheckTensorTypeValid("boxes", input_args[kBoxes]->BuildType(), {kFloat32}, prim_name);
(void)CheckAndConvertUtils::CheckTensorTypeValid("box_index", input_args[kBoxIndex]->BuildType(), {kInt32},
prim_name);
return kFloat32;
}
} // namespace
MIND_API_BASE_IMPL(CropAndResizeGradBoxes, PrimitiveC, BaseOperator);
AbstractBasePtr CropAndResizeGradBoxesInfer(const abstract::AnalysisEnginePtr &, const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args) {
auto type = CropAndResizeGradBoxesInferType(primitive, input_args);
auto shape = CropAndResizeGradBoxesInferShape(primitive, input_args);
return abstract::MakeAbstract(shape, type);
}
REGISTER_PRIMITIVE_EVAL_IMPL(CropAndResizeGradBoxes, prim::kPrimCropAndResizeGradBoxes, CropAndResizeGradBoxesInfer,
nullptr, true);
} // namespace ops
} // namespace mindspore

View File

@ -0,0 +1,58 @@
/**
* Copyright 2021 Huawei Technologies Co., Ltd
*
* 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.
*/
#ifndef MINDSPORE_CORE_OPS_CROP_AND_RESIZE_GRAD_BOXES_H_
#define MINDSPORE_CORE_OPS_CROP_AND_RESIZE_GRAD_BOXES_H_
#include <vector>
#include <memory>
#include "ops/primitive_c.h"
#include "ops/base_operator.h"
#include "abstract/abstract_value.h"
#include "utils/check_convert_utils.h"
#include "mindapi/base/types.h"
namespace mindspore {
namespace ops {
constexpr auto kNameCropAndResizeGradBoxes = "CropAndResizeGradBoxes";
/// \brief Computes the gradient of the crop_and_resize op wrt the input boxes tensor .
/// Refer to Python API @ref mindspore.ops.CropAndResizeGradBoxes for more details.
class MIND_API CropAndResizeGradBoxes : public BaseOperator {
public:
MIND_API_BASE_MEMBER(CropAndResizeGradBoxes);
/// \brief Constructor.
CropAndResizeGradBoxes() : BaseOperator(kNameCropAndResizeGradBoxes) {
InitIOName({"grads", "images", "boxes", "box_index"}, {"y"});
}
/// \brief Init. Refer to the parameters of Python API @ref mindspore.ops.CropAndResizeGradBoxes for the inputs.
void Init(ResizeMethod method);
/// \brief Set method.
void set_method(ResizeMethod method);
/// \brief Get method.
ResizeMethod get_method() const;
};
AbstractBasePtr CropAndResizeGradBoxesInfer(const abstract::AnalysisEnginePtr &, const PrimitivePtr &primitive,
const std::vector<AbstractBasePtr> &input_args);
using PrimCropAndResizeGradBoxesPtr = std::shared_ptr<CropAndResizeGradBoxes>;
} // namespace ops
} // namespace mindspore
#endif // MINDSPORE_CORE_OPS_CROP_AND_RESIZE_GRAD_BOXES_H_

View File

@ -71,6 +71,7 @@ from .matrix_determinant import _matrix_determinant_aicpu
from .log_matrix_determinant import _log_matrix_determinant_aicpu
from .lstsq import _lstsq_aicpu
from .crop_and_resize import _crop_and_resize_aicpu
from .crop_and_resize_grad_boxes import _crop_and_resize_grad_boxes_aicpu
from .acosh import _acosh_aicpu
from .acosh_grad import _acosh_grad_aicpu
from .rnnt_loss import _rnnt_loss_aicpu

View File

@ -0,0 +1,68 @@
# Copyright 2021 Huawei Technologies Co., Ltd
#
# 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.
# ============================================================================
"""CropAndResizeGradBoxes op"""
from mindspore.ops.op_info_register import op_info_register, AiCPURegOp, DataType
crop_and_resize_grad_boxes_op_info = AiCPURegOp("CropAndResizeGradBoxes") \
.fusion_type("OPAQUE") \
.input(0, "grads", "required") \
.input(1, "images", "required") \
.input(2, "boxes", "required") \
.input(3, "box_index", "required") \
.output(0, "y", "required") \
.attr("method", "str", "bilinear") \
.dtype_format(DataType.F32_Default, DataType.U8_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_Default, DataType.U16_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_Default, DataType.I8_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_Default, DataType.I16_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_Default, DataType.I32_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_Default, DataType.I64_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_Default, DataType.F16_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_Default, DataType.F32_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_Default, DataType.F64_Default, DataType.F32_Default, DataType.I32_Default,
DataType.F32_Default) \
.dtype_format(DataType.F32_NHWC, DataType.U8_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.dtype_format(DataType.F32_NHWC, DataType.U16_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.dtype_format(DataType.F32_NHWC, DataType.I8_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.dtype_format(DataType.F32_NHWC, DataType.I16_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.dtype_format(DataType.F32_NHWC, DataType.I32_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.dtype_format(DataType.F32_NHWC, DataType.I64_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.dtype_format(DataType.F32_NHWC, DataType.F16_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.dtype_format(DataType.F32_NHWC, DataType.F32_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.dtype_format(DataType.F32_NHWC, DataType.F64_NHWC, DataType.F32_NHWC, DataType.I32_NHWC,
DataType.F32_NHWC) \
.get_op_info()
@op_info_register(crop_and_resize_grad_boxes_op_info)
def _crop_and_resize_grad_boxes_aicpu():
"""CropAndResizeGradBoxes AiCPU register"""
return

View File

@ -239,3 +239,75 @@ class HSVToRGB(Primitive):
@prim_attr_register
def __init__(self):
pass
class CropAndResizeGradBoxes(Primitive):
"""
Computes the gradient of the CropAndResize op with respect to the input boxes tensor.
Note:
Input images and grads must be a 4-D tensor.
Args:
method (str): A string specifying the interpolation method. Only "bilinear" is supported for now.
Default: "bilinear".
Inputs:
- **grads** (Tensor) - A 4-D tensor of shape [num_boxes, crop_height, crop_width, depth].
The format must be NHWC. Types allowed: float32.
- **images** (Tensor) - A 4-D tensor of shape [batch, image_height, image_width, depth].
The format must be NHWC. Types allowed: int8, int16, int32, int64, float16, float32, float64, uint8, uint16.
Both image_height and image_width need to be positive.
- **boxes** (Tensor) - A 2-D tensor of shape [num_boxes, 4].
The i-th row of the tensor specifies the coordinates of a box in the box_index[i] image
and is specified in normalized coordinates [y1, x1, y2, x2]. A normalized coordinate value of y is mapped to
the image coordinate at y * (image_height - 1), so as the [0, 1] interval of normalized image height is
mapped to [0, image_height - 1] in image height coordinates. We do allow y1 > y2, in which case the sampled
crop is an up-down flipped version of the original image. The width dimension is treated similarly.
Normalized coordinates outside the [0, 1] range are allowed, in which case we use extrapolation_value to
extrapolate the input image values. Types allowed: float32.
- **box_index** (Tensor) - A 1-D tensor of shape [num_boxes] with int32 values in [0, batch).
The value of box_index[i] specifies the image that the i-th box refers to. Types allowed: int32.
Outputs:
A 2-D tensor of shape [num_boxes, 4] with type: float32.
Raises:
TypeError: If `method` is not a str.
TypeError: If `grads` is not tensor or its dtype is not float32.
TypeError: If `images` is not tensor or its dtype is incorrect.
TypeError: If `boxes` is not tensor or its dtype is not float32.
TypeError: If `box_index` is not tensor or its dtype is not int32.
ValueError: If `method` is not 'bilinear'.
ValueError: If the size of `grads` tensor shape is not equal to 4.
ValueError: If the size of `images` tensor shape is not equal to 4.
ValueError: If the value of image_height or image_width of `image` tensor shape is not positive.
ValueError: If the size of `boxes` tensor shape is not equal to 2.
ValueError: If the length of the second dimension of `boxes` is not equal to 4.
ValueError: If the size of `box_index` tensor shape is not equal to 1.
ValueError: If the length of `box_index` is not equal to num_boxes.
Supported Platforms:
``Ascend`` ``CPU``
Examples:
>>> crop_and_resize_grad_boxes = ops.CropAndResizeGradBoxes(method = "bilinear")
>>> grads = Tensor(np.array([[[[2.0], [5.0]], [[1.0], [4.0]]]]), mindspore.float32)
>>> image = Tensor(np.array([[[[9.0], [5.0], [2.0], [1.0]],
... [[6.0], [1.0], [9.0], [7.0]],
... [[6.0], [0.0], [2.0], [9.0]],
... [[1.0], [2.0], [6.0], [7.0]]]]), mindspore.float32)
>>> boxes = Tensor(np.array([[0.3, 0.8, 0.3, 0.8]]), mindspore.float32)
>>> box_index = Tensor(np.array([0]), mindspore.int32)
>>> output = crop_and_resize_grad_boxes(grads, image, boxes, box_index)
>>> print(output.asnumpy())
[138.6,-17.1,99.0,-51.300003]
"""
@prim_attr_register
def __init__(self, method="bilinear"):
"""Initialize CropAndResizeGradBoxes"""
self.init_prim_io_names(inputs=['grads', 'images', 'boxes', 'box_index'], outputs=['y'])
validator.check_value_type("method", method, [str], self.name)
validator.check_string(method, ["bilinear"], "method", self.name)
self.method = method

View File

@ -26,6 +26,7 @@ from mindspore import ms_function
from mindspore.common import dtype as mstype
from mindspore.ops import functional as F
from mindspore.ops import operations as P
from mindspore.ops.operations.image_ops import CropAndResizeGradBoxes
from mindspore.ops.operations import _grad_ops as G
from mindspore.ops.operations import _inner_ops as inner
from mindspore.ops.operations import _quant_ops as Q
@ -3133,6 +3134,14 @@ test_case_other_ops = [
'desc_inputs': [Tensor([2, 3], mstype.int32),
Tensor(1, mstype.float32)],
'desc_bprop': [Tensor([[1, 1, 1], [1, 1, 1]], mstype.float32)]}),
('CropAndResizeGradBoxes', {
'block': CropAndResizeGradBoxes(),
'desc_inputs': [Tensor(np.random.uniform(0, 10, size=(4, 10, 10, 3)).astype(np.float32)),
Tensor(np.random.randint(0, 10, size=(4, 50, 50, 3)).astype(np.int32)),
Tensor(np.random.uniform(0, 1, size=(4, 4)).astype(np.float32)),
Tensor(np.random.randint(0, 4, size=(4)).astype(np.int32))
],
'skip': ['backward']}),
]
test_case_quant_ops = [