You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by jx...@apache.org on 2017/11/20 19:57:25 UTC

[incubator-mxnet] branch vision updated: [Image OP] Normalize (#8731)

This is an automated email from the ASF dual-hosted git repository.

jxie pushed a commit to branch vision
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git


The following commit(s) were added to refs/heads/vision by this push:
     new e997559  [Image OP] Normalize (#8731)
e997559 is described below

commit e997559513afd4339f93a23ab2ee3f32b612c1e4
Author: Yizhi Liu <ja...@gmail.com>
AuthorDate: Mon Nov 20 11:57:22 2017 -0800

    [Image OP] Normalize (#8731)
    
    * image normalize op
    
    * image normalize op param check
---
 src/operator/image/image_random-inl.h | 93 +++++++++++++++++++++++++++++++++++
 src/operator/image/image_random.cc    | 34 ++++++++++++-
 2 files changed, 125 insertions(+), 2 deletions(-)

diff --git a/src/operator/image/image_random-inl.h b/src/operator/image/image_random-inl.h
index c50ecb7..6f9cdc0 100644
--- a/src/operator/image/image_random-inl.h
+++ b/src/operator/image/image_random-inl.h
@@ -106,12 +106,105 @@ static void ToTensor(const nnvm::NodeAttrs &attrs,
   });
 }
 
+struct NormalizeParam : public dmlc::Parameter<NormalizeParam> {
+  nnvm::Tuple<float> mean;
+  nnvm::Tuple<float> std;
+  DMLC_DECLARE_PARAMETER(NormalizeParam) {
+    DMLC_DECLARE_FIELD(mean)
+    .describe("Sequence of mean for each channel.");
+    DMLC_DECLARE_FIELD(std)
+    .describe("Sequence of standard deviations for each channel.");
+  }
+};
+
+struct normalize {
+  template<typename DType>
+  MSHADOW_XINLINE static void Map(int i, DType *out, const DType *in,
+                                  const OpReqType req,
+                                  const int nchannel, const int size,
+                                  const float *mean, const float *std) {
+    int c = 0;
+    switch (nchannel) {
+      case 1:
+        break;
+      case 3:
+        if (i < size) {
+          c = 0;
+        } else if (i < (size << 1)) {
+          c = 1;
+        } else {
+          c = 2;
+        }
+        break;
+      default:
+        LOG(FATAL) << "not support channel" << nchannel;
+    }
+    float m = (mean ? mean[c] : 0);
+    KERNEL_ASSIGN(out[i], req, static_cast<DType>((in[i] - m) / std[c]));
+  }
+};
+
+static void NormalizeCheckParam(const nnvm::Tuple<float> &mean,
+                                const nnvm::Tuple<float> &std,
+                                const int nchannel) {
+  CHECK(mean.ndim() == 1 || mean.ndim() == 3)
+    << "Mean must be in dimension 1 or 3.";
+  CHECK(std.ndim() == 1 || std.ndim() == 3)
+    << "Standard deviations must be in dimension 1 or 3.";
+  CHECK(nchannel == 1 || nchannel == 3) << "Image channel must be 1 or 3.";
+  CHECK_EQ(mean.ndim(), nchannel)
+    << "Mean dimension does not agree with image channel.";
+  CHECK_EQ(std.ndim(), nchannel)
+    << "Standard deviations dimension does not agree with image channel.";
+  for (uint32_t c = 0; c < std.ndim(); ++c) {
+    CHECK(std[c] > 0) << "Invalid standard deviation " << std[c];
+  }
+}
+
 template<typename xpu>
 static void Normalize(const nnvm::NodeAttrs &attrs,
                       const OpContext &ctx,
                       const std::vector<TBlob> &inputs,
                       const std::vector<OpReqType> &req,
                       const std::vector<TBlob> &outputs) {
+  const NormalizeParam &param = nnvm::get<NormalizeParam>(attrs.parsed);
+  auto mean = param.mean;
+  auto std = param.std;
+
+  int nchannel = inputs[0].shape_[0];
+  NormalizeCheckParam(mean, std, nchannel);
+
+  int size = inputs[0].Size() / nchannel;
+  mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
+  MXNET_ASSIGN_REQ_SWITCH(req[0], Req, {
+    MSHADOW_TYPE_SWITCH(outputs[0].type_flag_, DType, {
+      mxnet_op::Kernel<normalize, xpu>::Launch(
+        s, inputs[0].Size(), outputs[0].dptr<DType>(), inputs[0].dptr<DType>(),
+        Req, nchannel, size, mean.begin(), std.begin());
+    });
+  });
+}
+
+template<typename xpu>
+static void NormalizeBackward(const nnvm::NodeAttrs &attrs,
+                              const OpContext &ctx,
+                              const std::vector<TBlob> &inputs,
+                              const std::vector<OpReqType> &req,
+                              const std::vector<TBlob> &outputs) {
+  const NormalizeParam &param = nnvm::get<NormalizeParam>(attrs.parsed);
+  int nchannel = inputs[0].shape_[0];
+
+  NormalizeCheckParam(param.mean, param.std, nchannel);
+
+  int size = inputs[0].Size() / nchannel;
+  mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
+  MXNET_ASSIGN_REQ_SWITCH(req[0], Req, {
+    MSHADOW_TYPE_SWITCH(outputs[0].type_flag_, DType, {
+      mxnet_op::Kernel<normalize, xpu>::Launch(
+        s, inputs[0].Size(), outputs[0].dptr<DType>(), inputs[0].dptr<DType>(),
+        Req, nchannel, size, nullptr, param.std.begin());
+      });
+  });
 }
 
 struct RandomBrightnessParam : public dmlc::Parameter<RandomBrightnessParam> {
diff --git a/src/operator/image/image_random.cc b/src/operator/image/image_random.cc
index 26fa843..e32a677 100644
--- a/src/operator/image/image_random.cc
+++ b/src/operator/image/image_random.cc
@@ -28,8 +28,6 @@
 #include "../operator_common.h"
 #include "../elemwise_op_common.h"
 
-
-
 namespace mxnet {
 namespace op {
 
@@ -46,6 +44,38 @@ NNVM_REGISTER_OP(_image_to_tensor)
 .set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseNone{ "_copy" })
 .add_argument("data", "NDArray-or-Symbol", "The input.");
 
+DMLC_REGISTER_PARAMETER(NormalizeParam);
+NNVM_REGISTER_OP(_image_normalize)
+.describe(R"code()code" ADD_FILELINE)
+.set_num_inputs(1)
+.set_num_outputs(1)
+.set_attr_parser(ParamParser<NormalizeParam>)
+.set_attr<FResourceRequest>("FResourceRequest", [](const NodeAttrs& attrs) {
+  return std::vector<ResourceRequest>{ResourceRequest::kRandom};
+})
+.set_attr<nnvm::FInferShape>("FInferShape", ElemwiseShape<1, 1>)
+.set_attr<nnvm::FInferType>("FInferType", ElemwiseType<1, 1>)
+.set_attr<nnvm::FInplaceOption>("FInplaceOption",
+[](const NodeAttrs& attrs){
+  return std::vector<std::pair<int, int> >{{0, 0}};
+})
+.set_attr<FCompute>("FCompute<cpu>", Normalize<cpu>)
+.set_attr<nnvm::FGradient>("FGradient", ElemwiseGradUseNone{ "_image_backward_normalize" })
+.add_argument("data", "NDArray-or-Symbol", "The input.")
+.add_arguments(NormalizeParam::__FIELDS__());
+
+NNVM_REGISTER_OP(_image_backward_normalize)
+.describe(R"code()code" ADD_FILELINE)
+.set_num_inputs(1)
+.set_num_outputs(1)
+.set_attr_parser(ParamParser<NormalizeParam>)
+.set_attr<nnvm::TIsBackward>("TIsBackward", true)
+.set_attr<nnvm::FInplaceOption>("FInplaceOption",
+[](const NodeAttrs& attrs){
+  return std::vector<std::pair<int, int> >{{0, 0}};
+})
+.set_attr<FCompute>("FCompute<cpu>", NormalizeBackward<cpu>);
+
 DMLC_REGISTER_PARAMETER(RandomBrightnessParam);
 NNVM_REGISTER_OP(_image_random_brightness)
 .describe(R"code()code" ADD_FILELINE)

-- 
To stop receiving notification emails like this one, please contact
['"commits@mxnet.apache.org" <co...@mxnet.apache.org>'].