forked from mindspore-Ecosystem/mindspore
!26399 [assistant][ops] Add CropAndResizeGradBoxes
Merge pull request !26399 from wangyantao/CropAndResizeGradBoxes
This commit is contained in:
commit
d66af6eb86
|
@ -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
|
|
@ -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_
|
|
@ -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"));
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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 = [
|
||||
|
|
Loading…
Reference in New Issue