From 92c47cf8a7054d6d56442884f08e99a1307f9fff Mon Sep 17 00:00:00 2001 From: Jihoon Lee Date: Fri, 10 Jul 2020 16:17:44 +0900 Subject: [PATCH] Add setProperty for each property type Since Layer::setProperty is iterating through vectors, only part that needs overriding is setting each particular property. This PR add setProperty by type to relieve the issue. w.r.t #270, this patch enables layers to check if given property type is valid to user. **Self evaluation:** 1. Build test: [X]Passed [ ]Failed [ ]Skipped 2. Run test: [X]Passed [ ]Failed [ ]Skipped Signed-off-by: Jihoon Lee --- nntrainer/include/activation_layer.h | 8 --- nntrainer/include/bn_layer.h | 21 ++++--- nntrainer/include/conv2d_layer.h | 20 ++++--- nntrainer/include/fc_layer.h | 20 ++++--- nntrainer/include/flatten_layer.h | 20 ++++--- nntrainer/include/input_layer.h | 20 ++++--- nntrainer/include/layer.h | 13 ++++- nntrainer/include/loss_layer.h | 20 ++++--- nntrainer/include/pooling2d_layer.h | 20 ++++--- nntrainer/src/activation_layer.cpp | 10 ---- nntrainer/src/bn_layer.cpp | 29 ++++------ nntrainer/src/conv2d_layer.cpp | 76 ++++++++++++------------ nntrainer/src/fc_layer.cpp | 30 ++++------ nntrainer/src/flatten_layer.cpp | 7 ++- nntrainer/src/input_layer.cpp | 36 +++++------- nntrainer/src/layer.cpp | 90 +++++++++++++++++++---------- nntrainer/src/loss_layer.cpp | 5 +- nntrainer/src/pooling2d_layer.cpp | 62 ++++++++++---------- test/unittest/unittest_nntrainer_layers.cpp | 18 +++++- 19 files changed, 286 insertions(+), 239 deletions(-) diff --git a/nntrainer/include/activation_layer.h b/nntrainer/include/activation_layer.h index ae42696..300d55b 100644 --- a/nntrainer/include/activation_layer.h +++ b/nntrainer/include/activation_layer.h @@ -119,14 +119,6 @@ public: void setActivation(ActiType acti_type); /** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. - */ - int setProperty(std::vector values); - - /** * @brief get the base name for the layer * @retval base name of the layer */ diff --git a/nntrainer/include/bn_layer.h b/nntrainer/include/bn_layer.h index f6bf411..b8024cb 100644 --- a/nntrainer/include/bn_layer.h +++ b/nntrainer/include/bn_layer.h @@ -99,26 +99,31 @@ public: int initialize(bool last); /** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. - */ - int setProperty(std::vector values); - - /** * @brief get the base name for the layer * @retval base name of the layer */ std::string getBaseName() { return "BatchNormalization"; }; + using Layer::setProperty; + private: + /** + * @brief setProperty by PropertyType + * @note By passing empty string, this can validate if @a type is valid + * @param[in] type property type to be passed + * @param[in] value value to be passed, if empty string is passed, do nothing + * but throws error when @a type is invalid + * @exception std::invalid_argument invalid argument + */ + void setProperty(const PropertyType type, const std::string &value = ""); + Tensor cvar; /**< training varaince saved in bn_layer::forwarding and used in bn_layer::backwarding */ Tensor x_normalized; float epsilon; }; + } // namespace nntrainer #endif /* __cplusplus */ diff --git a/nntrainer/include/conv2d_layer.h b/nntrainer/include/conv2d_layer.h index 88ba623..0173da8 100644 --- a/nntrainer/include/conv2d_layer.h +++ b/nntrainer/include/conv2d_layer.h @@ -124,14 +124,6 @@ public: void setStandardization(bool enable) { this->standardization = enable; }; /** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. - */ - int setProperty(std::vector values); - - /** * @brief Optimizer Setter * @param[in] opt Optimizer * @retval #ML_ERROR_NONE Successful. @@ -168,7 +160,19 @@ public: */ std::string getBaseName() { return "Convolution2D"; }; + using Layer::setProperty; + private: + /** + * @brief setProperty by PropertyType + * @note By passing empty string, this can validate if @a type is valid + * @param[in] type property type to be passed + * @param[in] value value to be passed, if empty string is passed, do nothing + * but throws error when @a type is invalid + * @exception std::invalid_argument invalid argument + */ + void setProperty(const PropertyType type, const std::string &value = ""); + unsigned int filter_size; unsigned int kernel_size[CONV2D_DIM]; unsigned int stride[CONV2D_DIM]; diff --git a/nntrainer/include/fc_layer.h b/nntrainer/include/fc_layer.h index a4e3d91..bfe97ab 100644 --- a/nntrainer/include/fc_layer.h +++ b/nntrainer/include/fc_layer.h @@ -86,14 +86,6 @@ public: void setUnit(unsigned int u) { unit = u; }; /** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. - */ - int setProperty(std::vector values); - - /** * @brief Optimizer Setter * @param[in] opt Optimizer * @retval #ML_ERROR_NONE Successful. @@ -107,7 +99,19 @@ public: */ std::string getBaseName() { return "FullyConnected"; }; + using Layer::setProperty; + private: + /** + * @brief setProperty by PropertyType + * @note By passing empty string, this can validate if @a type is valid + * @param[in] type property type to be passed + * @param[in] value value to be passed, if empty string is passed, do nothing + * but throws error when @a type is invalid + * @exception std::invalid_argument invalid argument + */ + void setProperty(const PropertyType type, const std::string &value = ""); + unsigned int unit; }; } // namespace nntrainer diff --git a/nntrainer/include/flatten_layer.h b/nntrainer/include/flatten_layer.h index b9b86d2..f2896ba 100644 --- a/nntrainer/include/flatten_layer.h +++ b/nntrainer/include/flatten_layer.h @@ -87,13 +87,6 @@ public: Tensor backwarding(Tensor in, int iteration); /** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NOT_SUPPORTED Successful. - */ - int setProperty(std::vector values); - - /** * @brief copy layer * @param[in] l layer to copy */ @@ -104,6 +97,19 @@ public: * @retval base name of the layer */ std::string getBaseName() { return "Flatten"; }; + + using Layer::setProperty; + +private: + /** + * @brief setProperty by PropertyType + * @note By passing empty string, this can validate if @a type is valid + * @param[in] type property type to be passed + * @param[in] value value to be passed, if empty string is passed, do nothing + * but throws error when @a type is invalid + * @exception std::invalid_argument invalid argument + */ + void setProperty(const PropertyType type, const std::string &value = ""); }; } // namespace nntrainer diff --git a/nntrainer/include/input_layer.h b/nntrainer/include/input_layer.h index e8764ac..31d00cd 100644 --- a/nntrainer/include/input_layer.h +++ b/nntrainer/include/input_layer.h @@ -124,20 +124,24 @@ public: void setStandardization(bool enable) { this->standardization = enable; }; /** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. - */ - int setProperty(std::vector values); - - /** * @brief get the base name for the layer * @retval base name of the layer */ std::string getBaseName() { return "Input"; }; + using Layer::setProperty; + private: + /** + * @brief setProperty by PropertyType + * @note By passing empty string, this can validate if @a type is valid + * @param[in] type property type to be passed + * @param[in] value value to be passed, if empty string is passed, do nothing + * but throws error when @a type is invalid + * @exception std::invalid_argument invalid argument + */ + void setProperty(const PropertyType type, const std::string &value = ""); + bool normalization; bool standardization; }; diff --git a/nntrainer/include/layer.h b/nntrainer/include/layer.h index d9bfc93..bf1d5b0 100644 --- a/nntrainer/include/layer.h +++ b/nntrainer/include/layer.h @@ -183,7 +183,7 @@ public: * @retval #ML_ERROR_NONE Successful. * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. */ - virtual int setProperty(std::vector values); + int setProperty(std::vector values); /** * @brief Optimizer Setter @@ -514,6 +514,17 @@ protected: use setParamSize() to avoid setting parameters twice */ + /** + * @brief setProperty by PropertyType + * @note By passing empty string, this can validate if @a type is valid + * @param[in] type property type to be passed + * @param[in] value value to be passed, if empty string is passed, do nothing + * but throws error when @a type is invalid + * @exception std::invalid_argument invalid argument + */ + virtual void setProperty(const PropertyType type, + const std::string &value = ""); + private: /** * @brief Set containing all the names of layers diff --git a/nntrainer/include/loss_layer.h b/nntrainer/include/loss_layer.h index 47ccaa1..1f9ffa8 100644 --- a/nntrainer/include/loss_layer.h +++ b/nntrainer/include/loss_layer.h @@ -78,14 +78,6 @@ public: void save(std::ofstream &file) {} /** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. - */ - int setProperty(std::vector values); - - /** * @brief copy layer * @param[in] l layer to copy */ @@ -105,8 +97,20 @@ public: */ std::string getBaseName() { return "Loss"; }; + using Layer::setProperty; + private: /** + * @brief setProperty by PropertyType + * @note By passing empty string, this can validate if @a type is valid + * @param[in] type property type to be passed + * @param[in] value value to be passed, if empty string is passed, do nothing + * but throws error when @a type is invalid + * @exception std::invalid_argument invalid argument + */ + void setProperty(const PropertyType type, const std::string &value = ""); + + /** * @brief update loss * @param[in] l Tensor data to calculate */ diff --git a/nntrainer/include/pooling2d_layer.h b/nntrainer/include/pooling2d_layer.h index b87493c..c201bc5 100644 --- a/nntrainer/include/pooling2d_layer.h +++ b/nntrainer/include/pooling2d_layer.h @@ -109,14 +109,6 @@ public: void copy(std::shared_ptr l); /** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. - */ - int setProperty(std::vector values); - - /** * @brief set Pooling Type * @param[in] t pooling type */ @@ -145,7 +137,19 @@ public: */ std::string getBaseName() { return "Pooling2D"; }; + using Layer::setProperty; + private: + /** + * @brief setProperty by PropertyType + * @note By passing empty string, this can validate if @a type is valid + * @param[in] type property type to be passed + * @param[in] value value to be passed, if empty string is passed, do nothing + * but throws error when @a type is invalid + * @exception std::invalid_argument invalid argument + */ + void setProperty(const PropertyType type, const std::string &value); + unsigned int pooling_size[POOLING2D_DIM]; unsigned int stride[POOLING2D_DIM]; unsigned int padding[POOLING2D_DIM]; diff --git a/nntrainer/src/activation_layer.cpp b/nntrainer/src/activation_layer.cpp index 363a3be..8654579 100644 --- a/nntrainer/src/activation_layer.cpp +++ b/nntrainer/src/activation_layer.cpp @@ -128,14 +128,4 @@ void ActivationLayer::setActivation(ActiType acti_type) { this->activation_type = acti_type; } -/** - * @brief set Property of layer - * @param[in] values values of property - * @retval #ML_ERROR_NONE Successful. - * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter. - */ -int ActivationLayer::setProperty(std::vector values) { - return Layer::setProperty(values); -} - }; // namespace nntrainer diff --git a/nntrainer/src/bn_layer.cpp b/nntrainer/src/bn_layer.cpp index cf02ca2..7be9e17 100644 --- a/nntrainer/src/bn_layer.cpp +++ b/nntrainer/src/bn_layer.cpp @@ -68,28 +68,20 @@ int BatchNormalizationLayer::setOptimizer(Optimizer &opt) { return this->opt.initialize(dim, false); } -int BatchNormalizationLayer::setProperty(std::vector values) { +void BatchNormalizationLayer::setProperty(const PropertyType type, + const std::string &value) { int status = ML_ERROR_NONE; - - for (unsigned int i = 0; i < values.size(); ++i) { - std::string key; - std::string value; - status = getKeyValue(values[i], key, value); - NN_RETURN_STATUS(); - - unsigned int type = parseLayerProperty(key); - switch (static_cast(type)) { - case PropertyType::epsilon: + switch (type) { + case PropertyType::epsilon: + if (!value.empty()) { status = setFloat(epsilon, value); - NN_RETURN_STATUS(); - break; - default: - status = Layer::setProperty({values[i]}); - NN_RETURN_STATUS(); - break; + throw_status(status); } + break; + default: + Layer::setProperty(type, value); + break; } - return status; } Tensor BatchNormalizationLayer::forwarding(Tensor in, int &status) { @@ -180,4 +172,5 @@ void BatchNormalizationLayer::copy(std::shared_ptr l) { this->hidden.copy(from->hidden); this->cvar.copy(from->cvar); } + } /* namespace nntrainer */ diff --git a/nntrainer/src/conv2d_layer.cpp b/nntrainer/src/conv2d_layer.cpp index f2932a5..1792f36 100644 --- a/nntrainer/src/conv2d_layer.cpp +++ b/nntrainer/src/conv2d_layer.cpp @@ -287,60 +287,60 @@ int Conv2DLayer::setFilter(int f) { return status; } -int Conv2DLayer::setProperty(std::vector values) { +void Conv2DLayer::setProperty(const PropertyType type, + const std::string &value) { int status = ML_ERROR_NONE; - for (unsigned int i = 0; i < values.size(); ++i) { - std::string key; - std::string value; - - status = getKeyValue(values[i], key, value); - NN_RETURN_STATUS(); - - unsigned int t = parseLayerProperty(key); - - switch (static_cast(t)) { - case PropertyType::filter: { + switch (type) { + case PropertyType::filter: { + if (!value.empty()) { int size; status = setInt(size, value); - NN_RETURN_STATUS(); + throw_status(status); filter_size = size; - } break; - case PropertyType::kernel_size: + } + } break; + case PropertyType::kernel_size: + if (!value.empty()) { status = getValues(CONV2D_DIM, value, (int *)(kernel_size)); - NN_RETURN_STATUS(); + throw_status(status); if (kernel_size[0] == 0 || kernel_size[1] == 0) { - ml_loge("Error: kernel_size must be greater than 0"); - return ML_ERROR_INVALID_PARAMETER; + throw std::out_of_range( + "[Conv2DLayer] kernel_size must be greater than 0"); } - break; - case PropertyType::stride: + } + break; + case PropertyType::stride: + if (!value.empty()) { status = getValues(CONV2D_DIM, value, (int *)(stride)); - NN_RETURN_STATUS(); + throw_status(status); if (stride[0] == 0 || stride[1] == 0) { - ml_loge("Error: stride must be greater than 0"); - return ML_ERROR_INVALID_PARAMETER; + throw std::out_of_range("[Conv2DLayer] stride must be greater than 0"); } - break; - case PropertyType::padding: + } + break; + case PropertyType::padding: + if (!value.empty()) { status = getValues(CONV2D_DIM, value, (int *)(padding)); - NN_RETURN_STATUS(); - break; - case PropertyType::normalization: + throw_status(status); + } + break; + case PropertyType::normalization: + if (!value.empty()) { status = setBoolean(normalization, value); - NN_RETURN_STATUS(); - break; - case PropertyType::standardization: + throw_status(status); + } + break; + case PropertyType::standardization: + if (!value.empty()) { status = setBoolean(standardization, value); - NN_RETURN_STATUS(); - break; - default: - status = Layer::setProperty({values[i]}); - NN_RETURN_STATUS(); - break; + throw_status(status); } + break; + default: + Layer::setProperty(type, value); + break; } - return status; } int Conv2DLayer::conv2d(float *in, TensorDim indim, float *kernel, diff --git a/nntrainer/src/fc_layer.cpp b/nntrainer/src/fc_layer.cpp index 50d486d..f8a6403 100644 --- a/nntrainer/src/fc_layer.cpp +++ b/nntrainer/src/fc_layer.cpp @@ -62,33 +62,23 @@ int FullyConnectedLayer::initialize(bool last) { return status; } -int FullyConnectedLayer::setProperty(std::vector values) { +void FullyConnectedLayer::setProperty(const PropertyType type, + const std::string &value) { int status = ML_ERROR_NONE; - - for (unsigned int i = 0; i < values.size(); ++i) { - std::string key; - std::string value; - - status = getKeyValue(values[i], key, value); - NN_RETURN_STATUS(); - - unsigned int type = parseLayerProperty(key); - - switch (static_cast(type)) { - case PropertyType::unit: { + switch (type) { + case PropertyType::unit: { + if (!value.empty()) { int width; status = setInt(width, value); - NN_RETURN_STATUS(); + throw_status(status); unit = width; output_dim.width(unit); - } break; - default: - status = Layer::setProperty({values[i]}); - NN_RETURN_STATUS(); - break; } + } break; + default: + Layer::setProperty(type, value); + break; } - return status; } int FullyConnectedLayer::setOptimizer(Optimizer &opt) { diff --git a/nntrainer/src/flatten_layer.cpp b/nntrainer/src/flatten_layer.cpp index 31a5892..ec6f825 100644 --- a/nntrainer/src/flatten_layer.cpp +++ b/nntrainer/src/flatten_layer.cpp @@ -57,9 +57,10 @@ Tensor FlattenLayer::backwarding(Tensor in, int iteration) { return ret; } -int FlattenLayer::setProperty(std::vector values) { - return ML_ERROR_NOT_SUPPORTED; -}; +void FlattenLayer::setProperty(const PropertyType type, + const std::string &value) { + throw std::invalid_argument("[Flatten Layer] setProperty not supported"); +} void FlattenLayer::copy(std::shared_ptr l) { std::shared_ptr from = diff --git a/nntrainer/src/input_layer.cpp b/nntrainer/src/input_layer.cpp index 5365b41..9967d3d 100644 --- a/nntrainer/src/input_layer.cpp +++ b/nntrainer/src/input_layer.cpp @@ -35,33 +35,27 @@ int InputLayer::setOptimizer(Optimizer &opt) { return this->opt.initialize(dim, false); } -int InputLayer::setProperty(std::vector values) { +void InputLayer::setProperty(const PropertyType type, + const std::string &value) { int status = ML_ERROR_NONE; - for (unsigned int i = 0; i < values.size(); ++i) { - std::string key; - std::string value; - status = getKeyValue(values[i], key, value); - NN_RETURN_STATUS(); - - unsigned int type = parseLayerProperty(key.c_str()); - - switch (static_cast(type)) { - case PropertyType::normalization: + switch (type) { + case PropertyType::normalization: + if (!value.empty()) { status = setBoolean(normalization, value); - NN_RETURN_STATUS(); - break; - case PropertyType::standardization: + throw_status(status); + } + break; + case PropertyType::standardization: + if (!value.empty()) { status = setBoolean(standardization, value); - NN_RETURN_STATUS(); - break; - default: - status = Layer::setProperty({values[i]}); - NN_RETURN_STATUS(); - break; + throw_status(status); } + break; + default: + Layer::setProperty(type, value); + break; } - return status; } void InputLayer::copy(std::shared_ptr l) { diff --git a/nntrainer/src/layer.cpp b/nntrainer/src/layer.cpp index d28eabd..4c9fbd6 100644 --- a/nntrainer/src/layer.cpp +++ b/nntrainer/src/layer.cpp @@ -141,48 +141,78 @@ int Layer::setProperty(std::vector values) { unsigned int type = parseLayerProperty(key); - switch (static_cast(type)) { - case PropertyType::name: + if (value.empty()) { + return ML_ERROR_INVALID_PARAMETER; + } + + try { + /// @note this calls derived setProperty if available + setProperty(static_cast(type), value); + } catch (...) { + return ML_ERROR_INVALID_PARAMETER; + } + } + return status; +} + +void Layer::setProperty(const PropertyType type, const std::string &value) { + int status = ML_ERROR_NONE; + + switch (type) { + case PropertyType::name: + if (!value.empty()) { status = setName(value); - NN_RETURN_STATUS(); - break; - case PropertyType::input_shape: + } + throw_status(status); + break; + case PropertyType::input_shape: + if (!value.empty()) { status = input_dim.setTensorDim(value.c_str()); - NN_RETURN_STATUS(); - break; - case PropertyType::bias_init_zero: + } + throw_status(status); + break; + case PropertyType::bias_init_zero: + if (!value.empty()) { status = setBoolean(this->bias_init_zero, value); - NN_RETURN_STATUS(); - break; - case PropertyType::activation: + } + throw_status(status); + break; + case PropertyType::activation: + if (!value.empty()) { status = setActivation((ActiType)parseType(value, TOKEN_ACTI)); - NN_RETURN_STATUS(); - break; - case PropertyType::flatten: + } + throw_status(status); + break; + case PropertyType::flatten: + if (!value.empty()) { status = setBoolean(flatten, value); - NN_RETURN_STATUS(); - break; - case PropertyType::weight_decay: + } + throw_status(status); + break; + case PropertyType::weight_decay: + if (!value.empty()) { weight_decay.type = (WeightDecayType)parseType(value, TOKEN_WEIGHT_DECAY); if (weight_decay.type == WeightDecayType::unknown) { - ml_loge("Error: Unknown Weight Decay"); - return ML_ERROR_INVALID_PARAMETER; + throw std::invalid_argument("[Layer] Unknown Weight decay"); } - break; - case PropertyType::weight_decay_lambda: + } + break; + case PropertyType::weight_decay_lambda: + if (!value.empty()) { status = setFloat(weight_decay.lambda, value); - NN_RETURN_STATUS(); - break; - case PropertyType::weight_ini: + throw_status(status); + } + break; + case PropertyType::weight_ini: + if (!value.empty()) { weight_ini_type = (WeightIniType)parseType(value, TOKEN_WEIGHTINI); - break; - default: - ml_loge("Error: Unknown Layer Property Key : %s", key.c_str()); - status = ML_ERROR_INVALID_PARAMETER; - break; } + break; + default: + std::string msg = + "[Layer] Unknown Layer Property Key for value" + std::string(value); + throw std::invalid_argument(msg); } - return status; } int Layer::setName(std::string name) { diff --git a/nntrainer/src/loss_layer.cpp b/nntrainer/src/loss_layer.cpp index d05bc17..94eb327 100644 --- a/nntrainer/src/loss_layer.cpp +++ b/nntrainer/src/loss_layer.cpp @@ -156,7 +156,8 @@ Tensor LossLayer::forwarding(Tensor in, int &status) { return in; } -int LossLayer::setProperty(std::vector values) { - return ML_ERROR_NOT_SUPPORTED; +void LossLayer::setProperty(const PropertyType type, const std::string &value) { + throw std::invalid_argument("[Loss Layer] setProperty not supported"); } + } /* namespace nntrainer */ diff --git a/nntrainer/src/pooling2d_layer.cpp b/nntrainer/src/pooling2d_layer.cpp index 9bdce64..e59a4d0e 100644 --- a/nntrainer/src/pooling2d_layer.cpp +++ b/nntrainer/src/pooling2d_layer.cpp @@ -181,55 +181,53 @@ void Pooling2DLayer::copy(std::shared_ptr l) { this->last_layer = from->last_layer; } -int Pooling2DLayer::setProperty(std::vector values) { +void Pooling2DLayer::setProperty(const PropertyType type, + const std::string &value) { int status = ML_ERROR_NONE; - for (unsigned int i = 0; i < values.size(); ++i) { - std::string key; - std::string value; - - status = getKeyValue(values[i], key, value); - NN_RETURN_STATUS(); - unsigned int t = parseLayerProperty(key); - switch (static_cast(t)) { - case PropertyType::pooling: + switch (type) { + case PropertyType::pooling: + if (!value.empty()) { pooling_type = (PoolingType)parseType(value, TOKEN_POOLING); if (pooling_type == PoolingType::unknown) { - ml_loge("Error: Unknown pooling type"); - return ML_ERROR_INVALID_PARAMETER; + throw std::invalid_argument("[Pooling2d_layer]: Unknown pooling type"); } break; - case PropertyType::pooling_size: + } + case PropertyType::pooling_size: + if (!value.empty()) { status = getValues(POOLING2D_DIM, value, (int *)(pooling_size)); - NN_RETURN_STATUS(); + throw_status(status); if (pooling_size[0] == 0 || pooling_size[1] == 0) { - ml_loge("Error: pooling_size must be greater than 0"); - return ML_ERROR_INVALID_PARAMETER; + throw std::invalid_argument( + "[Pooling2d_layer] pooling_size must be greater than 0"); } - break; - case PropertyType::stride: + } + break; + case PropertyType::stride: + if (!value.empty()) { status = getValues(POOLING2D_DIM, value, (int *)(stride)); - NN_RETURN_STATUS(); + throw_status(status); if (stride[0] == 0 || stride[1] == 0) { - ml_loge("Error: stride must be greater than 0"); - return ML_ERROR_INVALID_PARAMETER; + throw std::invalid_argument( + "[Pooling2d_layer] stride must be greater than 0"); } - break; - case PropertyType::padding: + } + break; + case PropertyType::padding: + if (!value.empty()) { status = getValues(POOLING2D_DIM, value, (int *)(padding)); - NN_RETURN_STATUS(); + throw_status(status); if ((int)padding[0] < 0 || (int)padding[1] < 0) { - ml_loge("Error: padding must be greater than 0"); - return ML_ERROR_INVALID_PARAMETER; + throw std::invalid_argument( + "[Pooling2d_layer] padding must be greater than 0"); } - break; - default: - ml_loge("Error: Unknown Layer Property Key : %s", key.c_str()); - status = ML_ERROR_INVALID_PARAMETER; - break; } + break; + default: + Layer::setProperty(type, value); + break; } - return status; } Tensor Pooling2DLayer::pooling2d(unsigned int batch, Tensor in, int &status) { diff --git a/test/unittest/unittest_nntrainer_layers.cpp b/test/unittest/unittest_nntrainer_layers.cpp index 3204632..3a33510 100644 --- a/test/unittest/unittest_nntrainer_layers.cpp +++ b/test/unittest/unittest_nntrainer_layers.cpp @@ -706,11 +706,17 @@ protected: } }; -TEST_F(nntrainer_Pooling2DLayer, setPeoperty_01_p) { +TEST_F(nntrainer_Pooling2DLayer, setProperty_01_p) { setInputDim("2:3:5:5"); setProperty("pooling_size=2,2 | stride=1,1 | padding=0,0 | pooling=average"); } +TEST_F(nntrainer_Pooling2DLayer, setProperty_02_n) { + setInputDim("2:3:5:5"); + int status = layer.setProperty({"pooling_size="}); + EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER); +} + TEST_F(nntrainer_Pooling2DLayer, initialize_01_p) { reinitialize(); } TEST_F(nntrainer_Pooling2DLayer, forwarding_01_p) { @@ -972,6 +978,16 @@ TEST(nntrainer_LossLayer, setCost_02_n) { EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER); } +/** + * @brief Loss Layer + */ +TEST(nntrainer_LossLayer, setProperty_01_n) { + int status = ML_ERROR_NONE; + nntrainer::LossLayer layer; + status = layer.setProperty({"loss=cross"}); + EXPECT_EQ(status, ML_ERROR_INVALID_PARAMETER); +} + TEST(nntrainer_ActivationLayer, init_01_1) { int status = ML_ERROR_NONE; nntrainer::ActivationLayer layer; -- 2.7.4