mv_machine_learning: drop parsing dependency from image classification
authorVibhav Aggarwal <v.aggarwal@samsung.com>
Tue, 7 Nov 2023 10:01:57 +0000 (19:01 +0900)
committerInki Dae <inki.dae@samsung.com>
Tue, 14 Nov 2023 07:40:07 +0000 (16:40 +0900)
[Issue type] : code refactoring

Drop the configuration and meta file parsing dependency from ImageClassification
class.

Until now, the concrete class of each task group got the task group
configuration information from its own configuration file, and also
included a MetaParser class object to get the tensor information,
which is corresponding to a given model file.

However, these dependencies led code smell, divergent change[1] even though
the concrete class has no any dependency from parsing the configuration and
meta files - needed only information after parsed.

As a first refactoring work, this patch extracts parsing portion from
ImageClassification class and introduces as a new class, ImageClassificationConfig
class.

With this, adapter classes of the image classification task group will parse
the configuration and meta files before creating ImageClassification class.
And then it will create ImageClassification class with needed information.
As a result, we could manage the ImageClassification class without any
dependency on parsing work.

[1] https://refactoring.guru/smells/divergent-change

Change-Id: I421dcd6f796e6865dde3e5fed597ef83e7e5bc12
Signed-off-by: Vibhav Aggarwal <v.aggarwal@samsung.com>
mv_machine_learning/image_classification/include/image_classification.h
mv_machine_learning/image_classification/include/image_classification_adapter.h
mv_machine_learning/image_classification/include/image_classification_config.h [new file with mode: 0644]
mv_machine_learning/image_classification/include/image_classification_default.h
mv_machine_learning/image_classification/src/image_classification.cpp
mv_machine_learning/image_classification/src/image_classification_adapter.cpp
mv_machine_learning/image_classification/src/image_classification_config.cpp [new file with mode: 0644]
mv_machine_learning/image_classification/src/image_classification_default.cpp

index 306ee51..cdf2872 100644 (file)
@@ -25,7 +25,9 @@
 #include "inference_engine_common_impl.h"
 #include "Inference.h"
 #include "image_classification_type.h"
+#include "MetaParser.h"
 #include "ImageClassificationParser.h"
+#include "image_classification_config.h"
 #include "machine_learning_preprocess.h"
 #include "async_manager.h"
 
@@ -50,36 +52,28 @@ private:
 
 protected:
        std::unique_ptr<mediavision::inference::Inference> _inference;
-       std::unique_ptr<MediaVision::Common::EngineConfig> _config;
-       std::unique_ptr<MetaParser> _parser;
+       std::shared_ptr<ImageClassificationConfig> _config;
        Preprocess _preprocess;
-       std::string _modelFilePath;
-       std::string _modelMetaFilePath;
-       std::string _modelLabelFilePath;
        std::vector<std::string> _labels;
        std::vector<std::string> _valid_backends;
        std::vector<std::string> _valid_devices;
-       int _backendType {};
-       int _targetDeviceType {};
 
        void getOutputNames(std::vector<std::string> &names);
        void getOutpuTensor(std::string &target_name, std::vector<float> &tensor);
-       void parseMetaFile(const std::string &meta_file_name);
        template<typename T> void inference(std::vector<std::vector<T> > &inputVectors);
        virtual ImageClassificationResult &result() = 0;
 
 public:
-       ImageClassification();
+       explicit ImageClassification(std::shared_ptr<ImageClassificationConfig> config);
        virtual ~ImageClassification() = default;
 
        void preDestroy();
-       void setUserModel(std::string model_file, std::string meta_file, std::string label_file);
-       void setEngineInfo(std::string engine_type, std::string device_type);
+       void setEngineInfo(std::string engine_type_name, std::string device_type_name);
        void getNumberOfEngines(unsigned int *number_of_engines);
        void getEngineType(unsigned int engine_index, char **engine_type);
        void getNumberOfDevices(const char *engine_type, unsigned int *number_of_devices);
        void getDeviceType(const char *engine_type, const unsigned int device_index, char **device_type);
-       void configure(const std::string &configFile);
+       void configure();
        void prepare();
        void perform(mv_source_h &mv_src);
        void performAsync(ImageClassificationInput &input);
index 0066c8e..6766a1c 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "EngineConfig.h"
 #include "itask.h"
+#include "image_classification_config.h"
 #include "image_classification_default.h"
 
 namespace mediavision
@@ -31,7 +32,11 @@ template<typename T, typename V> class ImageClassificationAdapter : public media
 {
 private:
        std::unique_ptr<ImageClassification> _image_classification;
+       std::shared_ptr<ImageClassificationConfig> _config;
        T _source;
+       const std::string _config_file_name = "image_classification.json";
+
+       void create();
 
 public:
        ImageClassificationAdapter();
diff --git a/mv_machine_learning/image_classification/include/image_classification_config.h b/mv_machine_learning/image_classification/include/image_classification_config.h
new file mode 100644 (file)
index 0000000..dbab988
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 __IMAGE_CLASSIFICATION_CONFIG_H__
+#define __IMAGE_CLASSIFICATION_CONFIG_H__
+
+#include <mv_common.h>
+#include "mv_private.h"
+#include "EngineConfig.h"
+
+#include "MetaParser.h"
+#include "image_classification_type.h"
+
+namespace mediavision
+{
+namespace machine_learning
+{
+class ImageClassificationConfig
+{
+private:
+       std::unique_ptr<MetaParser> _parser;
+       std::string _modelFilePath;
+       std::string _modelMetaFilePath;
+       std::string _modelDefaultPath;
+       std::string _modelLabelFilePath;
+       int _backendType {};
+       int _targetDeviceType {};
+
+public:
+       ImageClassificationConfig();
+       virtual ~ImageClassificationConfig() = default;
+
+       void setUserModel(const std::string &model_file, const std::string &meta_file, const std::string &label_file);
+       void parseConfigFile(const std::string &configFilePath);
+       void parseMetaFile();
+       void setBackendType(int backend_type);
+       void setTargetDeviceType(int device_type);
+       const std::string &getModelFilePath() const;
+       const std::string &getLabelFilePath() const;
+       MetaMap &getInputMetaMap() const;
+       MetaMap &getOutputMetaMap() const;
+       int getBackendType() const;
+       int getTargetDeviceType() const;
+       void loadMetaFile();
+};
+
+} // machine_learning
+} // mediavision
+
+#endif
\ No newline at end of file
index 23e6bd5..981b15e 100644 (file)
@@ -35,7 +35,7 @@ private:
        ImageClassificationResult _result;
 
 public:
-       ImageClassificationDefault();
+       ImageClassificationDefault(std::shared_ptr<ImageClassificationConfig> config);
        ~ImageClassificationDefault();
 
        ImageClassificationResult &result() override;
index b5320c9..1fe19e2 100644 (file)
@@ -35,11 +35,10 @@ namespace mediavision
 {
 namespace machine_learning
 {
-ImageClassification::ImageClassification()
-               : _backendType(MV_INFERENCE_BACKEND_NONE), _targetDeviceType(MV_INFERENCE_TARGET_DEVICE_NONE)
+ImageClassification::ImageClassification(shared_ptr<ImageClassificationConfig> config) : _config(config)
 {
        _inference = make_unique<Inference>();
-       _parser = make_unique<ImageClassificationParser>();
+       loadLabel();
 }
 
 void ImageClassification::preDestroy()
@@ -50,29 +49,25 @@ void ImageClassification::preDestroy()
        _async_manager->stop();
 }
 
-void ImageClassification::configure(const string &configFile)
+void ImageClassification::configure()
 {
-       parseMetaFile(configFile);
-
-       int ret = _inference->bind(_backendType, _targetDeviceType);
+       int ret = _inference->bind(_config->getBackendType(), _config->getTargetDeviceType());
        if (ret != MEDIA_VISION_ERROR_NONE)
                throw InvalidOperation("Fail to bind a backend engine.");
 }
 
-static bool IsJsonFile(const string &fileName)
-{
-       return (!fileName.substr(fileName.find_last_of(".") + 1).compare("json"));
-}
-
 void ImageClassification::loadLabel()
 {
+       if (_config->getLabelFilePath().empty())
+               return;
+
        ifstream readFile;
 
        _labels.clear();
-       readFile.open(_modelLabelFilePath.c_str());
+       readFile.open(_config->getLabelFilePath().c_str());
 
        if (readFile.fail())
-               throw InvalidOperation("Fail to open " + _modelLabelFilePath + " file.");
+               throw InvalidOperation("Fail to open " + _config->getLabelFilePath() + " file.");
 
        string line;
 
@@ -102,30 +97,25 @@ void ImageClassification::getDeviceList(const char *engine_type)
        _valid_devices.push_back("gpu");
 }
 
-void ImageClassification::setUserModel(string model_file, string meta_file, string label_file)
-{
-       _modelFilePath = model_file;
-       _modelMetaFilePath = meta_file;
-       _modelLabelFilePath = label_file;
-}
-
-void ImageClassification::setEngineInfo(std::string engine_type, std::string device_type)
+void ImageClassification::setEngineInfo(std::string engine_type_name, std::string device_type_name)
 {
-       if (engine_type.empty() || device_type.empty())
+       if (engine_type_name.empty() || device_type_name.empty())
                throw InvalidParameter("Invalid engine info.");
 
-       transform(engine_type.begin(), engine_type.end(), engine_type.begin(), ::toupper);
-       transform(device_type.begin(), device_type.end(), device_type.begin(), ::toupper);
+       transform(engine_type_name.begin(), engine_type_name.end(), engine_type_name.begin(), ::toupper);
+       transform(device_type_name.begin(), device_type_name.end(), device_type_name.begin(), ::toupper);
 
-       _backendType = GetBackendType(engine_type);
-       _targetDeviceType = GetDeviceType(device_type);
+       int engine_type = GetBackendType(engine_type_name);
+       int device_type = GetDeviceType(device_type_name);
 
-       LOGI("Engine type : %s => %d, Device type : %s => %d", engine_type.c_str(), GetBackendType(engine_type),
-                device_type.c_str(), GetDeviceType(device_type));
-
-       if (_backendType == MEDIA_VISION_ERROR_INVALID_PARAMETER ||
-               _targetDeviceType == MEDIA_VISION_ERROR_INVALID_PARAMETER)
+       if (engine_type == MEDIA_VISION_ERROR_INVALID_PARAMETER || device_type == MEDIA_VISION_ERROR_INVALID_PARAMETER)
                throw InvalidParameter("backend or target device type not found.");
+
+       _config->setBackendType(engine_type);
+       _config->setTargetDeviceType(device_type);
+
+       LOGI("Engine type : %s => %d, Device type : %s => %d", engine_type_name.c_str(), engine_type,
+                device_type_name.c_str(), device_type);
 }
 
 void ImageClassification::getNumberOfEngines(unsigned int *number_of_engines)
@@ -186,81 +176,17 @@ void ImageClassification::getDeviceType(const char *engine_type, const unsigned
        *device_type = const_cast<char *>(_valid_devices[device_index].data());
 }
 
-void ImageClassification::parseMetaFile(const string &meta_file_name)
-{
-       int ret = MEDIA_VISION_ERROR_NONE;
-
-       _config = make_unique<EngineConfig>(string(MV_CONFIG_PATH) + meta_file_name);
-
-       if (_backendType == MV_INFERENCE_BACKEND_NONE) {
-               ret = _config->getIntegerAttribute(string(MV_IMAGE_CLASSIFICATION_BACKEND_TYPE), &_backendType);
-               if (ret != MEDIA_VISION_ERROR_NONE)
-                       throw InvalidOperation("Fail to get backend engine type.");
-       }
-
-       if (_targetDeviceType == MV_INFERENCE_TARGET_DEVICE_NONE) {
-               ret = _config->getIntegerAttribute(string(MV_IMAGE_CLASSIFICATION_TARGET_DEVICE_TYPE), &_targetDeviceType);
-               if (ret != MEDIA_VISION_ERROR_NONE)
-                       throw InvalidOperation("Fail to get target device type.");
-       }
-
-       string modelDefaultPath;
-
-       ret = _config->getStringAttribute(MV_IMAGE_CLASSIFICATION_MODEL_DEFAULT_PATH, &modelDefaultPath);
-       if (ret != MEDIA_VISION_ERROR_NONE)
-               throw InvalidOperation("Fail to get model default path");
-
-       if (_modelFilePath.empty()) {
-               ret = _config->getStringAttribute(MV_IMAGE_CLASSIFICATION_MODEL_FILE_NAME, &_modelFilePath);
-               if (ret != MEDIA_VISION_ERROR_NONE)
-                       throw InvalidOperation("Fail to get model file path");
-       }
-
-       _modelFilePath = modelDefaultPath + _modelFilePath;
-       LOGI("model file path = %s", _modelFilePath.c_str());
-
-       if (_modelMetaFilePath.empty()) {
-               ret = _config->getStringAttribute(MV_IMAGE_CLASSIFICATION_MODEL_META_FILE_NAME, &_modelMetaFilePath);
-               if (ret != MEDIA_VISION_ERROR_NONE)
-                       throw InvalidOperation("Fail to get model meta file path");
-
-               if (_modelMetaFilePath.empty())
-                       throw InvalidOperation("Model meta file doesn't exist.");
-
-               if (!IsJsonFile(_modelMetaFilePath))
-                       throw InvalidOperation("Model meta file should be json.");
-       }
-
-       _modelMetaFilePath = modelDefaultPath + _modelMetaFilePath;
-       LOGI("meta file path = %s", _modelMetaFilePath.c_str());
-
-       if (_modelLabelFilePath.empty()) {
-               ret = _config->getStringAttribute(MV_IMAGE_CLASSIFICATION_MODEL_LABEL_FILE_NAME, &_modelLabelFilePath);
-               if (ret != MEDIA_VISION_ERROR_NONE)
-                       throw InvalidOperation("Fail to get model label file path");
-
-               if (_modelLabelFilePath.empty())
-                       throw InvalidOperation("Model label file doesn't exist.");
-       }
-
-       _modelLabelFilePath = modelDefaultPath + _modelLabelFilePath;
-       LOGI("label file path = %s", _modelLabelFilePath.c_str());
-
-       loadLabel();
-       _parser->load(_modelMetaFilePath);
-}
-
 void ImageClassification::prepare()
 {
-       int ret = _inference->configureInputMetaInfo(_parser->getInputMetaMap());
+       int ret = _inference->configureInputMetaInfo(_config->getInputMetaMap());
        if (ret != MEDIA_VISION_ERROR_NONE)
                throw InvalidOperation("Fail to configure input tensor info from meta file.");
 
-       ret = _inference->configureOutputMetaInfo(_parser->getOutputMetaMap());
+       ret = _inference->configureOutputMetaInfo(_config->getOutputMetaMap());
        if (ret != MEDIA_VISION_ERROR_NONE)
                throw InvalidOperation("Fail to configure output tensor info from meta file.");
 
-       _inference->configureModelFiles("", _modelFilePath, "");
+       _inference->configureModelFiles("", _config->getModelFilePath(), "");
 
        // Request to load model files to a backend engine.
        ret = _inference->load();
@@ -280,7 +206,7 @@ shared_ptr<MetaInfo> ImageClassification::getInputMetaInfo()
        auto tensor_buffer_iter = tensor_info_map.begin();
 
        // Get the meta information corresponding to a given input tensor name.
-       return _parser->getInputMetaMap()[tensor_buffer_iter->first];
+       return _config->getInputMetaMap()[tensor_buffer_iter->first];
 }
 
 template<typename T>
index a15a950..7629e92 100644 (file)
@@ -31,7 +31,10 @@ namespace machine_learning
 {
 template<typename T, typename V> ImageClassificationAdapter<T, V>::ImageClassificationAdapter() : _source()
 {
-       _image_classification = make_unique<ImageClassificationDefault>();
+       _config = make_shared<ImageClassificationConfig>();
+       _config->parseConfigFile(_config_file_name);
+
+       create();
 }
 
 template<typename T, typename V> ImageClassificationAdapter<T, V>::~ImageClassificationAdapter()
@@ -39,11 +42,25 @@ template<typename T, typename V> ImageClassificationAdapter<T, V>::~ImageClassif
        _image_classification->preDestroy();
 }
 
+template<typename T, typename V> void ImageClassificationAdapter<T, V>::create()
+{
+       // reallocate the parser and load the meta file
+       _config->loadMetaFile();
+
+       _image_classification = make_unique<ImageClassificationDefault>(_config);
+}
+
 template<typename T, typename V>
 void ImageClassificationAdapter<T, V>::setModelInfo(const char *model_file, const char *meta_file,
                                                                                                        const char *label_file, const char *model_name)
 {
-       _image_classification->setUserModel(string(model_file), string(meta_file), string(label_file));
+       _config->setUserModel(model_file, meta_file, label_file);
+       create();
+
+       if (!model_file && !meta_file) {
+               LOGW("Given model info is invalid so default model info will be used instead.");
+               return;
+       }
 }
 
 template<typename T, typename V>
@@ -54,7 +71,7 @@ void ImageClassificationAdapter<T, V>::setEngineInfo(const char *engine_type, co
 
 template<typename T, typename V> void ImageClassificationAdapter<T, V>::configure()
 {
-       _image_classification->configure("image_classification.json");
+       _image_classification->configure();
 }
 
 template<typename T, typename V>
diff --git a/mv_machine_learning/image_classification/src/image_classification_config.cpp b/mv_machine_learning/image_classification/src/image_classification_config.cpp
new file mode 100644 (file)
index 0000000..2ed568a
--- /dev/null
@@ -0,0 +1,152 @@
+/**
+ * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 "machine_learning_exception.h"
+#include "mv_image_classification_config.h"
+#include "ImageClassificationParser.h"
+#include "image_classification_config.h"
+
+using namespace std;
+using namespace MediaVision::Common;
+using namespace mediavision::machine_learning;
+using namespace mediavision::machine_learning::exception;
+
+namespace mediavision
+{
+namespace machine_learning
+{
+ImageClassificationConfig::ImageClassificationConfig()
+{}
+
+void ImageClassificationConfig::setBackendType(int backend_type)
+{
+       _backendType = backend_type;
+}
+
+void ImageClassificationConfig::setTargetDeviceType(int device_type)
+{
+       _targetDeviceType = device_type;
+}
+
+const std::string &ImageClassificationConfig::getModelFilePath() const
+{
+       return _modelFilePath;
+}
+
+const std::string &ImageClassificationConfig::getLabelFilePath() const
+{
+       return _modelLabelFilePath;
+}
+
+MetaMap &ImageClassificationConfig::getInputMetaMap() const
+{
+       return _parser->getInputMetaMap();
+}
+
+MetaMap &ImageClassificationConfig::getOutputMetaMap() const
+{
+       return _parser->getOutputMetaMap();
+}
+
+int ImageClassificationConfig::getBackendType() const
+{
+       return _backendType;
+}
+
+int ImageClassificationConfig::getTargetDeviceType() const
+{
+       return _targetDeviceType;
+}
+
+void ImageClassificationConfig::setUserModel(const string &model_file, const string &meta_file,
+                                                                                        const string &label_file)
+{
+       if (!model_file.empty())
+               _modelFilePath = _modelDefaultPath + model_file;
+       if (!meta_file.empty())
+               _modelMetaFilePath = _modelDefaultPath + meta_file;
+       if (!label_file.empty())
+               _modelLabelFilePath = _modelDefaultPath + label_file;
+}
+
+static bool IsJsonFile(const string &fileName)
+{
+       return (!fileName.substr(fileName.find_last_of(".") + 1).compare("json"));
+}
+
+void ImageClassificationConfig::parseConfigFile(const std::string &configFilePath)
+{
+       auto config = make_unique<EngineConfig>(MV_CONFIG_PATH + configFilePath);
+
+       int ret = MEDIA_VISION_ERROR_NONE;
+
+       if (_backendType == MV_INFERENCE_BACKEND_NONE) {
+               ret = config->getIntegerAttribute(MV_IMAGE_CLASSIFICATION_BACKEND_TYPE, &_backendType);
+               if (ret != MEDIA_VISION_ERROR_NONE)
+                       throw InvalidOperation("Fail to get backend engine type.");
+       }
+
+       if (_targetDeviceType == MV_INFERENCE_TARGET_DEVICE_NONE) {
+               ret = config->getIntegerAttribute(MV_IMAGE_CLASSIFICATION_TARGET_DEVICE_TYPE, &_targetDeviceType);
+               if (ret != MEDIA_VISION_ERROR_NONE)
+                       throw InvalidOperation("Fail to get target device type.");
+       }
+
+       ret = config->getStringAttribute(MV_IMAGE_CLASSIFICATION_MODEL_DEFAULT_PATH, &_modelDefaultPath);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get model default path");
+
+       ret = config->getStringAttribute(MV_IMAGE_CLASSIFICATION_MODEL_FILE_NAME, &_modelFilePath);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get model file path");
+
+       _modelFilePath = _modelDefaultPath + _modelFilePath;
+       LOGI("model file path = %s", _modelFilePath.c_str());
+
+       ret = config->getStringAttribute(MV_IMAGE_CLASSIFICATION_MODEL_META_FILE_NAME, &_modelMetaFilePath);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get model meta file path");
+
+       if (_modelMetaFilePath.empty())
+               throw InvalidOperation("Model meta file doesn't exist.");
+
+       if (!IsJsonFile(_modelMetaFilePath))
+               throw InvalidOperation("Model meta file should be json");
+
+       _modelMetaFilePath = _modelDefaultPath + _modelMetaFilePath;
+       LOGI("meta file path = %s", _modelMetaFilePath.c_str());
+
+       ret = config->getStringAttribute(MV_IMAGE_CLASSIFICATION_MODEL_LABEL_FILE_NAME, &_modelLabelFilePath);
+       if (ret != MEDIA_VISION_ERROR_NONE)
+               throw InvalidOperation("Fail to get label file path");
+
+       if (_modelLabelFilePath.empty()) {
+               LOGW("Label doesn't exist.");
+               return;
+       }
+
+       _modelLabelFilePath = _modelDefaultPath + _modelLabelFilePath;
+       LOGI("label file path = %s", _modelLabelFilePath.c_str());
+}
+
+void ImageClassificationConfig::loadMetaFile()
+{
+       _parser = make_unique<ImageClassificationParser>();
+       _parser->load(_modelMetaFilePath);
+}
+
+}
+}
index c515b73..3b74c71 100644 (file)
@@ -30,7 +30,8 @@ namespace mediavision
 {
 namespace machine_learning
 {
-ImageClassificationDefault::ImageClassificationDefault() : _result()
+ImageClassificationDefault::ImageClassificationDefault(shared_ptr<ImageClassificationConfig> config)
+               : ImageClassification(config), _result()
 {}
 
 ImageClassificationDefault::~ImageClassificationDefault()
@@ -47,7 +48,7 @@ ImageClassificationResult &ImageClassificationDefault::result()
        // In case of image classification model, only one output tensor is used.
        ImageClassification::getOutpuTensor(names[0], output_vec);
 
-       auto metaInfo = _parser->getOutputMetaMap().at(names[0]);
+       auto metaInfo = _config->getOutputMetaMap().at(names[0]);
        auto decodingScore = static_pointer_cast<DecodingScore>(metaInfo->decodingTypeMap.at(DecodingType::SCORE));
 
        if (decodingScore->type == ScoreType::SIGMOID) {