[ML][Training] Dataset.setProperty() refactoring
[platform/core/api/webapi-plugins.git] / src / ml / ml_utils.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include "ml_utils.h"
18
19 #include <memory>
20
21 #include "common/logger.h"
22
23 namespace extension {
24 namespace ml {
25
26 namespace types {
27 const PlatformEnum<ml_nnfw_hw_e> HWTypeEnum{
28     {"ANY", ML_NNFW_HW_ANY},
29     {"AUTO", ML_NNFW_HW_AUTO},
30     {"CPU", ML_NNFW_HW_CPU},
31     {"CPU_NEON", ML_NNFW_HW_CPU_NEON},
32     {"CPU_SIMD", ML_NNFW_HW_CPU_SIMD},
33     {"GPU", ML_NNFW_HW_GPU},
34     {"NPU", ML_NNFW_HW_NPU},
35     {"NPU_EDGE_TPU", ML_NNFW_HW_NPU_EDGE_TPU},
36     {"NPU_MOVIDIUS", ML_NNFW_HW_NPU_MOVIDIUS},
37     {"NPU_SLSI", ML_NNFW_HW_NPU_SLSI},
38     {"NPU_SR", ML_NNFW_HW_NPU_SR},
39     {"NPU_VIVANTE", ML_NNFW_HW_NPU_VIVANTE}};
40
41 const PlatformEnum<ml_nnfw_type_e> NNFWTypeEnum{
42     {"ANY", ML_NNFW_TYPE_ANY},
43     {"ARM_NN", ML_NNFW_TYPE_ARMNN},
44     {"CUSTOM_FILTER", ML_NNFW_TYPE_CUSTOM_FILTER},
45     {"EDGE_TPU", ML_NNFW_TYPE_EDGE_TPU},
46     {"MVNC", ML_NNFW_TYPE_MVNC},
47     {"NNFW", ML_NNFW_TYPE_NNFW},
48     {"NNTR_INF", ML_NNFW_TYPE_NNTR_INF},
49     {"OPEN_VINO", ML_NNFW_TYPE_OPENVINO},
50     {"PYTORCH", ML_NNFW_TYPE_PYTORCH},
51     {"SNAP", ML_NNFW_TYPE_SNAP},
52     {"SNPE", ML_NNFW_TYPE_SNPE},
53     {"TRIX_ENGINE", ML_NNFW_TYPE_TRIX_ENGINE},
54     {"TENSORFLOW", ML_NNFW_TYPE_TENSORFLOW},
55     {"TENSORFLOW_LITE", ML_NNFW_TYPE_TENSORFLOW_LITE},
56     {"VD_AIFW", ML_NNFW_TYPE_VD_AIFW},
57     {"VIVANTE", ML_NNFW_TYPE_VIVANTE}};
58
59 const PlatformEnum<ml_tensor_type_e> TensorTypeEnum{
60     {"INT8", ML_TENSOR_TYPE_INT8},       {"UINT8", ML_TENSOR_TYPE_UINT8},
61     {"INT16", ML_TENSOR_TYPE_INT16},     {"UINT16", ML_TENSOR_TYPE_UINT16},
62     {"FLOAT32", ML_TENSOR_TYPE_FLOAT32}, {"INT32", ML_TENSOR_TYPE_INT32},
63     {"UINT32", ML_TENSOR_TYPE_UINT32},   {"FLOAT64", ML_TENSOR_TYPE_FLOAT64},
64     {"INT64", ML_TENSOR_TYPE_INT64},     {"UINT64", ML_TENSOR_TYPE_UINT64},
65     {"UNKNOWN", ML_TENSOR_TYPE_UNKNOWN}};
66
67 const PlatformEnum<ml_train_optimizer_type_e> OptimizerTypeEnum{
68     {"OPTIMIZER_ADAM", ML_TRAIN_OPTIMIZER_TYPE_ADAM},
69     {"OPTIMIZER_SGD", ML_TRAIN_OPTIMIZER_TYPE_SGD},
70     {"OPTIMIZER_UNKNOWN", ML_TRAIN_OPTIMIZER_TYPE_UNKNOWN}};
71
72 const PlatformEnum<ml_train_layer_type_e> LayerTypeEnum{
73     {"LAYER_IN", ML_TRAIN_LAYER_TYPE_INPUT},
74     {"LAYER_FC", ML_TRAIN_LAYER_TYPE_FC},
75     {"LAYER_BN", ML_TRAIN_LAYER_TYPE_BN},
76     {"LAYER_CONV2D", ML_TRAIN_LAYER_TYPE_CONV2D},
77     {"LAYER_POOLING2D", ML_TRAIN_LAYER_TYPE_POOLING2D},
78     {"LAYER_FLATTEN", ML_TRAIN_LAYER_TYPE_FLATTEN},
79     {"LAYER_ACTIVATION", ML_TRAIN_LAYER_TYPE_ACTIVATION},
80     {"LAYER_ADDITION", ML_TRAIN_LAYER_TYPE_ADDITION},
81     {"LAYER_CONCAT", ML_TRAIN_LAYER_TYPE_CONCAT},
82     {"LAYER_MULTIOUT", ML_TRAIN_LAYER_TYPE_MULTIOUT},
83     {"LAYER_EMBEDDING", ML_TRAIN_LAYER_TYPE_EMBEDDING},
84     {"LAYER_RNN", ML_TRAIN_LAYER_TYPE_RNN},
85     {"LAYER_LOSS_MSE", ML_TRAIN_LAYER_TYPE_LOSS_MSE},
86     {"LAYER_LOSS_CROSS_ENTROPY_SIGMOID",
87      ML_TRAIN_LAYER_TYPE_LOSS_CROSS_ENTROPY_SIGMOID},
88     {"LAYER_LOSS_CROSS_ENTROPY_SOFTMAX",
89      ML_TRAIN_LAYER_TYPE_LOSS_CROSS_ENTROPY_SOFTMAX},
90     {"LAYER_BACKBONE_NNSTREAMER", ML_TRAIN_LAYER_TYPE_BACKBONE_NNSTREAMER},
91     {"LAYER_UNKNOWN", ML_TRAIN_LAYER_TYPE_UNKNOWN}};
92
93 const PlatformEnum<ml_train_summary_type_e> SummaryTypeEnum{
94     {"SUMMARY_MODEL", ML_TRAIN_SUMMARY_MODEL},
95     {"SUMMARY_LAYER", ML_TRAIN_SUMMARY_LAYER},
96     {"SUMMARY_TENSOR", ML_TRAIN_SUMMARY_TENSOR}};
97
98 const PlatformEnum<ml_train_model_format_e> ModelSaveFormatEnum{
99     {"FORMAT_BIN", ML_TRAIN_MODEL_FORMAT_BIN},
100     {"FORMAT_INI", ML_TRAIN_MODEL_FORMAT_INI},
101     {"FORMAT_INI_WITH_BIN", ML_TRAIN_MODEL_FORMAT_INI_WITH_BIN}};
102
103 const PlatformEnum<ml_train_dataset_mode_e> DatasetModeEnum{
104     {"MODE_TRAIN", ML_TRAIN_DATASET_MODE_TRAIN},
105     {"MODE_VALID", ML_TRAIN_DATASET_MODE_VALID},
106     {"MODE_TEST", ML_TRAIN_DATASET_MODE_TEST}};
107
108 }  // namespace types
109
110 namespace util {
111
112 PlatformResult ToPlatformResult(int ml_error_code,
113                                 const std::string& error_message_beginning) {
114   ScopeLogger("ml_error_code: [%d] (%s)", ml_error_code,
115               get_error_message(ml_error_code));
116
117   switch (ml_error_code) {
118     case ML_ERROR_NONE:
119       return PlatformResult{};
120     case ML_ERROR_INVALID_PARAMETER:
121       return PlatformResult{ErrorCode::INVALID_VALUES_ERR,
122                             error_message_beginning + ": invalid parameter"};
123     case ML_ERROR_PERMISSION_DENIED:
124       return PlatformResult{ErrorCode::SECURITY_ERR,
125                             error_message_beginning + ": permission denied"};
126     case ML_ERROR_TRY_AGAIN:
127       return PlatformResult{ErrorCode::INVALID_STATE_ERR,
128                             error_message_beginning + ": invalid state"};
129     case ML_ERROR_TIMED_OUT:
130       return PlatformResult{ErrorCode::TIMEOUT_ERR,
131                             error_message_beginning + ": timeout"};
132     case ML_ERROR_NOT_SUPPORTED:
133       return PlatformResult{ErrorCode::NOT_SUPPORTED_ERR,
134                             error_message_beginning + ": not supported"};
135     case ML_ERROR_STREAMS_PIPE:
136     case ML_ERROR_UNKNOWN:
137     case ML_ERROR_OUT_OF_MEMORY:
138     default:
139       return PlatformResult{
140           ErrorCode::ABORT_ERR,
141           error_message_beginning + ": an unknown error occurred"};
142   }
143 }
144
145 bool CheckNNFWAvailability(const std::string& nnfw, const std::string& hw,
146                            optional<std::string> customRequirement) {
147   ScopeLogger();
148   ml_nnfw_type_e nnfw_e = ML_NNFW_TYPE_ANY;
149   ml_nnfw_hw_e hw_e = ML_NNFW_HW_ANY;
150
151   PlatformResult result = types::NNFWTypeEnum.getValue(nnfw, &nnfw_e);
152   if (!result) {
153     LoggerE("NNFWTypeEnum.getValue() failed, error: %s",
154             result.message().c_str());
155     return false;
156   }
157   result = types::HWTypeEnum.getValue(hw, &hw_e);
158   if (!result) {
159     LoggerE("HWTypeEnum.getValue() failed, error: %s",
160             result.message().c_str());
161     return false;
162   }
163   const char* customRequirementPtr =
164       customRequirement ? customRequirement->c_str() : nullptr;
165   bool available = false;
166   int ret = ml_check_nnfw_availability_full(nnfw_e, hw_e, customRequirementPtr,
167                                             &available);
168
169   if (ML_ERROR_NONE != ret) {
170     LoggerE("ml_check_nnfw_availability_full failed: %d (%s)", ret,
171             get_error_message(ret));
172     return false;
173   }
174
175   LoggerD("ml_check_nnfw_availability_full: %s", available ? "true" : "false");
176   return available;
177 }
178
179 PlatformResult GetDimensionsFromJsonArray(
180     const picojson::array& dim, unsigned int dimensions[ML_TENSOR_RANK_LIMIT]) {
181   ScopeLogger();
182   bool foundValidValue = false;
183   unsigned int validDimensions[ML_TENSOR_RANK_LIMIT];
184   for (int i = 0; i < ML_TENSOR_RANK_LIMIT; i++) {
185     validDimensions[i] = 1;
186   }
187   int dimSize = ML_TENSOR_RANK_LIMIT;
188   if (dim.size() <= ML_TENSOR_RANK_LIMIT) {
189     dimSize = dim.size();
190   } else {
191     LoggerD("Provided dimensions array is bigger than supported");
192   }
193
194   for (int i = dimSize - 1; i >= 0; i--) {
195     auto& d = dim[i];
196     if (!d.is<double>()) {
197       LoggerE("dimensions array contains an invalid value: %s",
198               d.serialize().c_str());
199       return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
200                             "dimensions array contains an invalid value");
201     }
202
203     int v = static_cast<int>(d.get<double>());
204     if (v <= 0) {
205       // dimensions with zeros at the end are valid
206       // 0 after valid value is not accepted
207       if (foundValidValue || (v < 0)) {
208         LoggerE("dimensions array contains non-positive value: %d", v);
209         return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
210                               "dimensions array contains non-positive value");
211       }
212       continue;
213     }
214
215     foundValidValue = true;
216     validDimensions[i] = static_cast<unsigned int>(v);
217   }
218
219   if (!foundValidValue) {
220     LoggerE("No valid values found in dimensions array");
221     return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
222                           "dimensions array contains invalid values");
223   }
224
225   for (int i = 0; i < ML_TENSOR_RANK_LIMIT; i++) {
226     dimensions[i] = validDimensions[i];
227   }
228   return PlatformResult(ErrorCode::NO_ERROR);
229 }
230
231 PlatformResult GetLocationFromJsonArray(
232     const picojson::array& array, unsigned int location[ML_TENSOR_RANK_LIMIT]) {
233   if (array.size() > ML_TENSOR_RANK_LIMIT) {
234     LoggerD("Provided size array is bigger than supported");
235   }
236   int i = 0;
237   for (const auto& a : array) {
238     double num = -1;
239     if (a.is<double>()) {
240       num = a.get<double>();
241     }
242     if (num < 0) {
243       LoggerE("location array contains negative value: %s",
244               a.serialize().c_str());
245       return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
246                             "location array contains negative value");
247     }
248     location[i] = static_cast<unsigned int>(num);
249     i++;
250     if (i == ML_TENSOR_RANK_LIMIT) {
251       break;
252     }
253   }
254   return PlatformResult(ErrorCode::NO_ERROR);
255 }
256
257 PlatformResult GetSizeFromJsonArray(
258     const picojson::array& array, unsigned int location[ML_TENSOR_RANK_LIMIT],
259     unsigned int dimensions[ML_TENSOR_RANK_LIMIT],
260     unsigned int size[ML_TENSOR_RANK_LIMIT]) {
261   if (array.size() > ML_TENSOR_RANK_LIMIT) {
262     LoggerD("Provided size array is bigger than supported");
263   }
264   int i = 0;
265   for (const auto& a : array) {
266     double num = 0;
267     if (a.is<double>()) {
268       num = a.get<double>();
269     }
270     if (num == 0) {
271       LoggerE("size array contains zero value: %s", a.serialize().c_str());
272       return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
273                             "size array contains zero value");
274     } else if (num > 0) {
275       size[i] = static_cast<unsigned int>(num);
276     } else {
277       // in case of negative value, size becomes size from location to end of
278       // axis
279       size[i] = dimensions[i] - location[i];
280     }
281     i++;
282     if (i == ML_TENSOR_RANK_LIMIT) {
283       break;
284     }
285   }
286   for (; i < ML_TENSOR_RANK_LIMIT; i++) {
287     size[i] = dimensions[i] - location[i];
288   }
289   return PlatformResult(ErrorCode::NO_ERROR);
290 }
291
292 }  // namespace util
293 }  // namespace ml
294 }  // namespace extension