diff --git a/mindspore/lite/nnacl/l2_norm.c b/mindspore/lite/nnacl/l2_norm.c new file mode 100644 index 0000000000..a45658e64a --- /dev/null +++ b/mindspore/lite/nnacl/l2_norm.c @@ -0,0 +1,51 @@ +/** + * Copyright 2020 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 "nnacl/l2_norm.h" +#include + +int L2NormFp32(const float *input_ptr, float *output_ptr, + L2NormParameter *param) { + int *axis = param->axis_; + size_t axis_num = param->axis_num_; + float epsilon = param->epsilon_; + int shape_num = param->shape_num_; + + // default case, axis is set default + if (shape_num == axis_num) { + bool default_case_flag = true; + for (int i = 0; i < axis_num; i++) { + if (axis[i] != i) { + default_case_flag = false; + } + } + if (default_case_flag) { + int data_num = param->data_num_; + float sum = 0; + for (int i = 0; i < data_num; i++) { + sum = sum + input_ptr[i] * input_ptr[i]; + } + float res = sqrt(sum > epsilon ? sum : epsilon); + for (int i = 0; i < data_num; i++) { + output_ptr[i] = input_ptr[i] / res; + } + return 0; + } + } else { + return -1; + } + return 0; +} diff --git a/mindspore/lite/nnacl/l2_norm.h b/mindspore/lite/nnacl/l2_norm.h new file mode 100644 index 0000000000..1c55648472 --- /dev/null +++ b/mindspore/lite/nnacl/l2_norm.h @@ -0,0 +1,30 @@ +/** + * Copyright 2020 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_LITE_NNACL_L2NORM_H_ +#define MINDSPORE_LITE_NNACL_L2NORM_H_ +#include "nnacl/l2_norm_parameter.h" + +#ifdef __cplusplus +extern "C" { +#endif +int L2NormFp32(const float *input_ptr, float *output_ptr, + L2NormParameter *param); +#ifdef __cplusplus +} +#endif + +#endif // MINDSPORE_LITE_NNACL_L2NORM_H_ diff --git a/mindspore/lite/nnacl/l2_norm_parameter.h b/mindspore/lite/nnacl/l2_norm_parameter.h new file mode 100644 index 0000000000..1ffc0cf78d --- /dev/null +++ b/mindspore/lite/nnacl/l2_norm_parameter.h @@ -0,0 +1,32 @@ +/** + * Copyright 2020 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_LITE_NNACL_L2NORM_PARAMETER_H_ +#define MINDSPORE_LITE_NNACL_L2NORM_PARAMETER_H_ + +#include "nnacl/op_base.h" + +typedef struct L2NormParameter { + OpParameter op_parameter_; + int *axis_; + size_t axis_num_; + float epsilon_; + float data_num_; + int *shape_; + int shape_num_; +} L2NormParameter; + +#endif // MINDSPORE_LITE_NNACL_L2NORM_PARAMETER_H_ diff --git a/mindspore/lite/src/populate_parameter.cc b/mindspore/lite/src/populate_parameter.cc index 5fa7e0fd47..8cab2c7501 100644 --- a/mindspore/lite/src/populate_parameter.cc +++ b/mindspore/lite/src/populate_parameter.cc @@ -112,6 +112,7 @@ #include "src/ops/ceil.h" #include "src/ops/round.h" #include "src/ops/sparse_to_dense.h" +#include "src/ops/l2_norm.h" #include "nnacl/op_base.h" #include "nnacl/fp32/arg_min_max.h" #include "nnacl/fp32/cast.h" @@ -169,6 +170,7 @@ #include "nnacl/fp32/elu.h" #include "nnacl/leaky_relu_parameter.h" #include "nnacl/sparse_to_dense.h" +#include "nnacl/l2_norm_parameter.h" namespace mindspore::kernel { @@ -1513,6 +1515,33 @@ OpParameter *PopulateEluParameter(const mindspore::lite::PrimitiveC *primitive) return reinterpret_cast(elu_parameter); } +OpParameter *PopulateL2NormParameter( + const mindspore::lite::PrimitiveC *primitive) { + L2NormParameter *l2_norm_parameter = + reinterpret_cast(malloc(sizeof(L2NormParameter))); + if (l2_norm_parameter == nullptr) { + MS_LOG(ERROR) << "malloc L2NormParameter failed."; + return nullptr; + } + memset(l2_norm_parameter, 0, sizeof(L2NormParameter)); + l2_norm_parameter->op_parameter_.type_ = primitive->Type(); + auto param = reinterpret_cast( + const_cast(primitive)); + auto axis_vec = param->GetAxis(); + l2_norm_parameter->axis_num_ = axis_vec.size(); + l2_norm_parameter->axis_ = + reinterpret_cast(malloc(axis_vec.size() * sizeof(int))); + for (size_t i = 0; i < axis_vec.size(); i++) { + l2_norm_parameter->axis_[i] = axis_vec[i]; + } + if (param->GetEpsilon() < 1e-12) { + l2_norm_parameter->epsilon_ = 1e-12; + } else { + l2_norm_parameter->epsilon_ = param->GetEpsilon(); + } + return reinterpret_cast(l2_norm_parameter); +} + PopulateParameterRegistry::PopulateParameterRegistry() { populate_parameter_funcs_[schema::PrimitiveType_SparseToDense] = PopulateSparseToDenseParameter; populate_parameter_funcs_[schema::PrimitiveType_SoftMax] = PopulateSoftmaxParameter; @@ -1610,6 +1639,7 @@ PopulateParameterRegistry::PopulateParameterRegistry() { populate_parameter_funcs_[schema::PrimitiveType_Lstm] = PopulateLstmParameter; populate_parameter_funcs_[schema::PrimitiveType_EmbeddingLookup] = PopulateEmbeddingLookupParameter; populate_parameter_funcs_[schema::PrimitiveType_Elu] = PopulateEluParameter; + populate_parameter_funcs_[schema::PrimitiveType_L2Norm] = PopulateL2NormParameter; } PopulateParameterRegistry *PopulateParameterRegistry::GetInstance() { diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/l2_norm.cc b/mindspore/lite/src/runtime/kernel/arm/fp32/l2_norm.cc new file mode 100644 index 0000000000..2fb00a6783 --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/l2_norm.cc @@ -0,0 +1,98 @@ +/** + * Copyright 2020 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 +#include "src/runtime/kernel/arm/fp32/l2_norm.h" +#include "include/errorcode.h" +#include "nnacl/l2_norm.h" + + +using mindspore::kernel::KERNEL_ARCH::kCPU; +using mindspore::lite::KernelRegistrar; +using mindspore::lite::RET_ERROR; +using mindspore::lite::RET_OK; +using mindspore::schema::PrimitiveType_L2Norm; + +namespace mindspore::kernel { +int L2NormCPUKernel::Init() { + l2_norm_param_->data_num_ = in_tensors_.at(kInputIndex)->DataSize(); + auto shape = in_tensors_.at(kInputIndex)->shape(); + l2_norm_param_->shape_ = reinterpret_cast(malloc(shape.size() * sizeof(int))); + l2_norm_param_->shape_num_ = shape.size(); + for (size_t i = 0; i < shape.size(); i++) { + l2_norm_param_->shape_[i] = shape[i]; + } + return RET_OK; +} + +kernel::LiteKernel * +CpuL2NormFp32KernelCreator(const std::vector &inputs, + const std::vector &outputs, + OpParameter *param, const lite::Context *ctx, + const kernel::KernelKey &desc, + const mindspore::lite::PrimitiveC *primitive) { + if (param == nullptr) { + MS_LOG(ERROR) << "input param is nullptr!"; + return nullptr; + } + MS_ASSERT(desc.type == schema::PrimitiveType_L2Norm); + auto *kernel = new (std::nothrow) + L2NormCPUKernel(param, inputs, outputs, ctx, primitive); + if (kernel == nullptr) { + MS_LOG(ERROR) << "new L2NormCPUKernel fail!"; + return nullptr; + } + auto ret = kernel->Init(); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Init kernel failed, name: " << param->name_ << ", type: " + << schema::EnumNamePrimitiveType( + static_cast(param->type_)); + delete kernel; + return nullptr; + } + return kernel; +} + +int L2NormCPUKernel::Run() { + auto ret = Prepare(); + if (ret != RET_OK) { + MS_LOG(ERROR) << "Prepare fail!ret: " << ret; + return ret; + } + auto input_ptr = + reinterpret_cast(in_tensors_.at(kInputIndex)->Data()); + auto output_ptr = + reinterpret_cast(out_tensors_.at(kOutputIndex)->Data()); + ret = L2NormFp32(input_ptr, output_ptr, l2_norm_param_); + if (ret != 0) { + MS_LOG_ERROR << "unsupported axis setting, more work will be done"; + return ret; + } + return RET_OK; +} + +L2NormCPUKernel::~L2NormCPUKernel() { + if (l2_norm_param_->shape_ != nullptr) { + free(l2_norm_param_->shape_); + } + if (l2_norm_param_->axis_ != nullptr) { + free(l2_norm_param_->axis_); + } +} + +REG_KERNEL(kCPU, kNumberTypeFloat32, PrimitiveType_L2Norm, + CpuL2NormFp32KernelCreator) +} // namespace mindspore::kernel diff --git a/mindspore/lite/src/runtime/kernel/arm/fp32/l2_norm.h b/mindspore/lite/src/runtime/kernel/arm/fp32/l2_norm.h new file mode 100644 index 0000000000..0db39d736e --- /dev/null +++ b/mindspore/lite/src/runtime/kernel/arm/fp32/l2_norm.h @@ -0,0 +1,51 @@ +/** + * Copyright 2020 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_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_RESHAPE_H_ +#define MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_RESHAPE_H_ + +#include +#include "include/context.h" +#include "src/lite_kernel.h" +#include "nnacl/l2_norm_parameter.h" +#include "schema/model_generated.h" +#include "src/kernel_registry.h" + +using mindspore::lite::Context; + +namespace mindspore::kernel { +class L2NormCPUKernel : public LiteKernel { + public: + L2NormCPUKernel(OpParameter *parameter, + const std::vector &inputs, + const std::vector &outputs, + const Context *ctx, + const mindspore::lite::PrimitiveC *primitive) + : LiteKernel(parameter, inputs, outputs, ctx, primitive) { + l2_norm_param_ = reinterpret_cast(op_parameter_); + } + ~L2NormCPUKernel(); + + int Init() override; + int ReSize() override { return 0; } + int Run() override; + + private: + L2NormParameter * l2_norm_param_; +}; +} // namespace mindspore::kernel + +#endif // MINDSPORE_LITE_SRC_RUNTIME_KERNEL_ARM_FP32_RESHAPE_H_ diff --git a/mindspore/lite/test/models_tflite.cfg b/mindspore/lite/test/models_tflite.cfg index 25514d057b..8a57052c5e 100644 --- a/mindspore/lite/test/models_tflite.cfg +++ b/mindspore/lite/test/models_tflite.cfg @@ -103,3 +103,5 @@ mnasnet_1.0_160_1_metadata_1.tflite mnasnet_1.0_192_1_metadata_1.tflite mnasnet_1.0_224_1_metadata_1.tflite mnasnet_1.0_96_1_metadata_1.tflite +lite-model_on_device_vision_classifier_popular_us_products_V1_1.tflite +lite-model_on_device_vision_classifier_popular_wine_V1_1.tflite diff --git a/mindspore/lite/tools/converter/parser/tflite/tflite_quantize_parser.cc b/mindspore/lite/tools/converter/parser/tflite/tflite_quantize_parser.cc new file mode 100644 index 0000000000..c9a49d78f3 --- /dev/null +++ b/mindspore/lite/tools/converter/parser/tflite/tflite_quantize_parser.cc @@ -0,0 +1,72 @@ +/** + * Copyright 2019 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 "tools/converter/parser/tflite/tflite_quantize_parser.h" +#include +#include +#include + +namespace mindspore { +namespace lite { +STATUS TfliteQuantizeParser::Parse(const std::unique_ptr &tflite_op, + const std::vector> &tflite_tensors, + const std::vector> &tflite_model_buffer, + schema::CNodeT *op, + std::vector *tensors_id, + std::vector *tensors_format, + std::map *tensors_id_map) { + MS_LOG(DEBUG) << "parse TfliteQuantizeNParser"; + if (op == nullptr) { + MS_LOG(ERROR) << "op is null"; + return RET_NULL_PTR; + } + op->primitive = std::make_unique(); + if (op->primitive == nullptr) { + MS_LOG(ERROR) << "op->primitive is null"; + return RET_NULL_PTR; + } + + std::unique_ptr attr = std::make_unique(); + if (attr == nullptr) { + MS_LOG(ERROR) << "new op failed"; + return RET_NULL_PTR; + } + + const auto &in_tensor = tflite_tensors[tflite_op->inputs[0]]; + if (in_tensor == nullptr) { + MS_LOG(ERROR) << "input tensor is null"; + return RET_NULL_PTR; + } + attr->srcT = GetTfliteDataType(in_tensor->type); + const auto &out_tensor = tflite_tensors[tflite_op->outputs[0]]; + if (out_tensor == nullptr) { + MS_LOG(ERROR) << "output tensor is null"; + return RET_NULL_PTR; + } + attr->dstT = GetTfliteDataType(out_tensor->type); + + op->primitive->value.type = schema::PrimitiveType_QuantDTypeCast; + op->primitive->value.value = attr.release(); + + AddOpInput(op, tensors_id, tensors_format, tensors_id_map, + tflite_op->inputs[0], tensors_id->size(), tflite_tensors.size(), schema::Format_NHWC); + AddOpOutput(op, tensors_id, tensors_format, tensors_id_map, + tflite_op->outputs[0], tensors_id->size(), tflite_tensors.size(), schema::Format_NHWC); + return RET_OK; +} + +TfliteNodeRegister g_tfliteQuantizeParser("QUANTIZE", new TfliteQuantizeParser()); +} // namespace lite +} // namespace mindspore diff --git a/mindspore/lite/tools/converter/parser/tflite/tflite_quantize_parser.h b/mindspore/lite/tools/converter/parser/tflite/tflite_quantize_parser.h new file mode 100644 index 0000000000..834d6f1861 --- /dev/null +++ b/mindspore/lite/tools/converter/parser/tflite/tflite_quantize_parser.h @@ -0,0 +1,42 @@ +/** + * Copyright 2019 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_LITE_TOOLS_CONVERTER_PARSER_TFLITE_QUANTIZE_PARSER_H +#define MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_TFLITE_QUANTIZE_PARSER_H + +#include +#include +#include +#include "tools/converter/parser/tflite/tflite_node_parser.h" +#include "tools/converter/parser/tflite/tflite_node_parser_registry.h" + +namespace mindspore { +namespace lite { +class TfliteQuantizeParser : public TfliteNodeParser { + public: + TfliteQuantizeParser() : TfliteNodeParser("Quantize") {} + + STATUS Parse(const std::unique_ptr &tflite_op, + const std::vector> &tflite_tensors, + const std::vector> &tflite_model_buffer, + schema::CNodeT *op, + std::vector *tensors_id, + std::vector *tensors_format, + std::map *tensors_id_map) override; +}; +} // namespace lite +} // namespace mindspore + +#endif // MINDSPORE_LITE_TOOLS_CONVERTER_PARSER_TFLITE_QUANTIZE_PARSER_H