diff --git a/CHANGELOG.md b/CHANGELOG.md index 54eb454..b34fba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Internal -- Refactor library ArffFile to limit the number of samples with a parameter. -- Refactor tests libraries location to test/lib +- Create library ShuffleArffFile to limit the number of samples with a parameter and shuffle them. +- Refactor catch2 library location to test/lib - Refactor loadDataset function in tests. - Remove conditionalEdgeWeights method in BayesMetrics. diff --git a/CMakeLists.txt b/CMakeLists.txt index fd130fe..2b4c6b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,8 +60,9 @@ endif (ENABLE_CLANG_TIDY) # External libraries - dependencies of BayesNet # --------------------------------------------- # include(FetchContent) -add_git_submodule("lib/mdlp") add_git_submodule("lib/json") +add_git_submodule("lib/mdlp") +add_subdirectory("lib/Files") # Subdirectories # -------------- @@ -73,7 +74,6 @@ add_subdirectory(bayesnet) if (ENABLE_TESTING) MESSAGE("Testing enabled") add_subdirectory(tests/lib/catch2) - add_subdirectory(tests/lib/Files) include(CTest) add_subdirectory(tests) endif (ENABLE_TESTING) diff --git a/boostAODE.log b/boostAODE.log new file mode 100644 index 0000000..faa0c63 --- /dev/null +++ b/boostAODE.log @@ -0,0 +1,35 @@ +File verbosity level: 9 +date time ( uptime ) [ thread name/id ] file:line v| +2024-04-30 20:24:40.507 ( 0.002s) [BoostAODE ] loguru.cpp:825 INFO| Logging to 'boostAODE.log', mode: 'w', verbosity: 9 +2024-04-30 20:24:40.517 ( 0.011s) [BoostAODE ] BoostAODE.cc:321 1| { counter=0 k=1 featureSelection.size: 4 +2024-04-30 20:24:40.531 ( 0.025s) [BoostAODE ] BoostAODE.cc:340 2| . { numItemsPack: 1 n_models: 1 featuresUsed: 1 +2024-04-30 20:24:40.531 ( 0.025s) [BoostAODE ] BoostAODE.cc:340 2| . } 0.000 s: numItemsPack: 1 n_models: 1 featuresUsed: 1 +2024-04-30 20:24:40.533 ( 0.028s) [BoostAODE ] BoostAODE.cc:357 3| . { * (improvement>=threshold) Reset. tolerance: 0 numItemsPack: 1 improvement: 1.000000 prior: 0.933333 current: 0.933333 +2024-04-30 20:24:40.533 ( 0.028s) [BoostAODE ] BoostAODE.cc:357 3| . } 0.000 s: * (improvement>=threshold) Reset. tolerance: 0 numItemsPack: 1 improvement: 1.000000 prior: 0.933333 current: 0.933333 +2024-04-30 20:24:40.533 ( 0.028s) [BoostAODE ] BoostAODE.cc:369 1| . { tolerance: 0 featuresUsed.size: 1 features.size: 4 +2024-04-30 20:24:40.533 ( 0.028s) [BoostAODE ] BoostAODE.cc:369 1| . } 0.000 s: tolerance: 0 featuresUsed.size: 1 features.size: 4 +2024-04-30 20:24:40.533 ( 0.028s) [BoostAODE ] BoostAODE.cc:321 1| } 0.016 s: counter=0 k=1 featureSelection.size: 4 +2024-04-30 20:24:40.534 ( 0.029s) [BoostAODE ] BoostAODE.cc:321 1| { counter=0 k=1 featureSelection.size: 3 +2024-04-30 20:24:40.546 ( 0.040s) [BoostAODE ] BoostAODE.cc:340 2| . { numItemsPack: 1 n_models: 2 featuresUsed: 2 +2024-04-30 20:24:40.546 ( 0.040s) [BoostAODE ] BoostAODE.cc:340 2| . } 0.000 s: numItemsPack: 1 n_models: 2 featuresUsed: 2 +2024-04-30 20:24:40.549 ( 0.044s) [BoostAODE ] BoostAODE.cc:357 3| . { * (improvement>=threshold) Reset. tolerance: 0 numItemsPack: 1 improvement: 0.033333 prior: 0.933333 current: 0.966667 +2024-04-30 20:24:40.549 ( 0.044s) [BoostAODE ] BoostAODE.cc:357 3| . } 0.000 s: * (improvement>=threshold) Reset. tolerance: 0 numItemsPack: 1 improvement: 0.033333 prior: 0.933333 current: 0.966667 +2024-04-30 20:24:40.549 ( 0.044s) [BoostAODE ] BoostAODE.cc:369 1| . { tolerance: 0 featuresUsed.size: 2 features.size: 4 +2024-04-30 20:24:40.549 ( 0.044s) [BoostAODE ] BoostAODE.cc:369 1| . } 0.000 s: tolerance: 0 featuresUsed.size: 2 features.size: 4 +2024-04-30 20:24:40.549 ( 0.044s) [BoostAODE ] BoostAODE.cc:321 1| } 0.015 s: counter=0 k=1 featureSelection.size: 3 +2024-04-30 20:24:40.551 ( 0.045s) [BoostAODE ] BoostAODE.cc:321 1| { counter=0 k=1 featureSelection.size: 2 +2024-04-30 20:24:40.563 ( 0.058s) [BoostAODE ] BoostAODE.cc:340 2| . { numItemsPack: 1 n_models: 3 featuresUsed: 3 +2024-04-30 20:24:40.563 ( 0.058s) [BoostAODE ] BoostAODE.cc:340 2| . } 0.000 s: numItemsPack: 1 n_models: 3 featuresUsed: 3 +2024-04-30 20:24:40.568 ( 0.063s) [BoostAODE ] BoostAODE.cc:354 3| . { (improvement Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::BaseClassifier::~BaseClassifier() - 1818 + 606 diff --git a/html/bayesnet/BaseClassifier.h.func.html b/html/bayesnet/BaseClassifier.h.func.html index 7422513..b912388 100644 --- a/html/bayesnet/BaseClassifier.h.func.html +++ b/html/bayesnet/BaseClassifier.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::BaseClassifier::~BaseClassifier() - 1818 + 606 diff --git a/html/bayesnet/BaseClassifier.h.gcov.html b/html/bayesnet/BaseClassifier.h.gcov.html index 9e358fd..464032e 100644 --- a/html/bayesnet/BaseClassifier.h.gcov.html +++ b/html/bayesnet/BaseClassifier.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -80,7 +80,7 @@ 18 : virtual BaseClassifier& fit(torch::Tensor& X, torch::Tensor& y, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) = 0; 19 : virtual BaseClassifier& fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) = 0; 20 : virtual BaseClassifier& fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states, const torch::Tensor& weights) = 0; - 21 1818 : virtual ~BaseClassifier() = default; + 21 606 : virtual ~BaseClassifier() = default; 22 : torch::Tensor virtual predict(torch::Tensor& X) = 0; 23 : std::vector<int> virtual predict(std::vector<std::vector<int >>& X) = 0; 24 : torch::Tensor virtual predict_proba(torch::Tensor& X) = 0; diff --git a/html/bayesnet/classifiers/Classifier.cc.func-c.html b/html/bayesnet/classifiers/Classifier.cc.func-c.html index 24f404d..b44b0a0 100644 --- a/html/bayesnet/classifiers/Classifier.cc.func-c.html +++ b/html/bayesnet/classifiers/Classifier.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,168 +65,168 @@ bayesnet::Classifier::dump_cpt[abi:cxx11]() const - 6 + 2 bayesnet::Classifier::topological_order[abi:cxx11]() - 6 + 2 bayesnet::Classifier::predict(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 24 + 8 bayesnet::Classifier::score(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<int, std::allocator<int> >&) - 24 + 8 bayesnet::Classifier::getNumberOfStates() const - 36 + 12 bayesnet::Classifier::show[abi:cxx11]() const - 36 + 12 bayesnet::Classifier::setHyperparameters(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) - 126 + 42 bayesnet::Classifier::score(at::Tensor&, at::Tensor&) - 168 + 56 bayesnet::Classifier::fit(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<int, std::allocator<int> >&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 180 + 60 bayesnet::Classifier::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 192 + 64 bayesnet::Classifier::getNumberOfEdges() const - 282 + 94 bayesnet::Classifier::getNumberOfNodes() const - 282 + 94 bayesnet::Classifier::predict_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 390 + 130 bayesnet::Classifier::buildDataset(at::Tensor&) - 486 + 162 bayesnet::Classifier::getClassNumStates() const - 510 + 170 bayesnet::Classifier::fit(at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 594 + 198 bayesnet::Classifier::fit(at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&, at::Tensor const&) - 990 + 330 bayesnet::Classifier::addNodes() - 1680 + 560 bayesnet::Classifier::trainModel(at::Tensor const&) - 1680 + 560 bayesnet::Classifier::build(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&, at::Tensor const&) - 1932 + 644 bayesnet::Classifier::checkFitParameters() - 1932 + 644 bayesnet::Classifier::predict_proba(at::Tensor&) - 2226 + 742 bayesnet::Classifier::predict(at::Tensor&) - 2550 + 850 bayesnet::Classifier::Classifier(bayesnet::Network) - 2658 + 886 diff --git a/html/bayesnet/classifiers/Classifier.cc.func.html b/html/bayesnet/classifiers/Classifier.cc.func.html index 566f3df..5103318 100644 --- a/html/bayesnet/classifiers/Classifier.cc.func.html +++ b/html/bayesnet/classifiers/Classifier.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,168 +65,168 @@ bayesnet::Classifier::Classifier(bayesnet::Network) - 2658 + 886 bayesnet::Classifier::addNodes() - 1680 + 560 bayesnet::Classifier::build(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&, at::Tensor const&) - 1932 + 644 bayesnet::Classifier::buildDataset(at::Tensor&) - 486 + 162 bayesnet::Classifier::checkFitParameters() - 1932 + 644 bayesnet::Classifier::dump_cpt[abi:cxx11]() const - 6 + 2 bayesnet::Classifier::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 192 + 64 bayesnet::Classifier::fit(at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 594 + 198 bayesnet::Classifier::fit(at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&, at::Tensor const&) - 990 + 330 bayesnet::Classifier::fit(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<int, std::allocator<int> >&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 180 + 60 bayesnet::Classifier::getClassNumStates() const - 510 + 170 bayesnet::Classifier::getNumberOfEdges() const - 282 + 94 bayesnet::Classifier::getNumberOfNodes() const - 282 + 94 bayesnet::Classifier::getNumberOfStates() const - 36 + 12 bayesnet::Classifier::predict(at::Tensor&) - 2550 + 850 bayesnet::Classifier::predict(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 24 + 8 bayesnet::Classifier::predict_proba(at::Tensor&) - 2226 + 742 bayesnet::Classifier::predict_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 390 + 130 bayesnet::Classifier::score(at::Tensor&, at::Tensor&) - 168 + 56 bayesnet::Classifier::score(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<int, std::allocator<int> >&) - 24 + 8 bayesnet::Classifier::setHyperparameters(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) - 126 + 42 bayesnet::Classifier::show[abi:cxx11]() const - 36 + 12 bayesnet::Classifier::topological_order[abi:cxx11]() - 6 + 2 bayesnet::Classifier::trainModel(at::Tensor const&) - 1680 + 560 diff --git a/html/bayesnet/classifiers/Classifier.cc.gcov.html b/html/bayesnet/classifiers/Classifier.cc.gcov.html index d95e638..88ca7e1 100644 --- a/html/bayesnet/classifiers/Classifier.cc.gcov.html +++ b/html/bayesnet/classifiers/Classifier.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -71,188 +71,188 @@ 9 : #include "Classifier.h" 10 : 11 : namespace bayesnet { - 12 2658 : Classifier::Classifier(Network model) : model(model), m(0), n(0), metrics(Metrics()), fitted(false) {} + 12 886 : Classifier::Classifier(Network model) : model(model), m(0), n(0), metrics(Metrics()), fitted(false) {} 13 : const std::string CLASSIFIER_NOT_FITTED = "Classifier has not been fitted"; - 14 1932 : Classifier& Classifier::build(const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states, const torch::Tensor& weights) + 14 644 : Classifier& Classifier::build(const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states, const torch::Tensor& weights) 15 : { - 16 1932 : this->features = features; - 17 1932 : this->className = className; - 18 1932 : this->states = states; - 19 1932 : m = dataset.size(1); - 20 1932 : n = features.size(); - 21 1932 : checkFitParameters(); - 22 1884 : auto n_classes = states.at(className).size(); - 23 1884 : metrics = Metrics(dataset, features, className, n_classes); - 24 1884 : model.initialize(); - 25 1884 : buildModel(weights); - 26 1884 : trainModel(weights); - 27 1860 : fitted = true; - 28 1860 : return *this; + 16 644 : this->features = features; + 17 644 : this->className = className; + 18 644 : this->states = states; + 19 644 : m = dataset.size(1); + 20 644 : n = features.size(); + 21 644 : checkFitParameters(); + 22 628 : auto n_classes = states.at(className).size(); + 23 628 : metrics = Metrics(dataset, features, className, n_classes); + 24 628 : model.initialize(); + 25 628 : buildModel(weights); + 26 628 : trainModel(weights); + 27 620 : fitted = true; + 28 620 : return *this; 29 : } - 30 486 : void Classifier::buildDataset(torch::Tensor& ytmp) + 30 162 : void Classifier::buildDataset(torch::Tensor& ytmp) 31 : { 32 : try { - 33 486 : auto yresized = torch::transpose(ytmp.view({ ytmp.size(0), 1 }), 0, 1); - 34 1506 : dataset = torch::cat({ dataset, yresized }, 0); - 35 486 : } - 36 24 : catch (const std::exception& e) { - 37 24 : std::stringstream oss; - 38 24 : oss << "* Error in X and y dimensions *\n"; - 39 24 : oss << "X dimensions: " << dataset.sizes() << "\n"; - 40 24 : oss << "y dimensions: " << ytmp.sizes(); - 41 24 : throw std::runtime_error(oss.str()); - 42 48 : } - 43 972 : } - 44 1680 : void Classifier::trainModel(const torch::Tensor& weights) + 33 162 : auto yresized = torch::transpose(ytmp.view({ ytmp.size(0), 1 }), 0, 1); + 34 502 : dataset = torch::cat({ dataset, yresized }, 0); + 35 162 : } + 36 8 : catch (const std::exception& e) { + 37 8 : std::stringstream oss; + 38 8 : oss << "* Error in X and y dimensions *\n"; + 39 8 : oss << "X dimensions: " << dataset.sizes() << "\n"; + 40 8 : oss << "y dimensions: " << ytmp.sizes(); + 41 8 : throw std::runtime_error(oss.str()); + 42 16 : } + 43 324 : } + 44 560 : void Classifier::trainModel(const torch::Tensor& weights) 45 : { - 46 1680 : model.fit(dataset, weights, features, className, states); - 47 1680 : } + 46 560 : model.fit(dataset, weights, features, className, states); + 47 560 : } 48 : // X is nxm where n is the number of features and m the number of samples - 49 192 : Classifier& Classifier::fit(torch::Tensor& X, torch::Tensor& y, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) + 49 64 : Classifier& Classifier::fit(torch::Tensor& X, torch::Tensor& y, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) 50 : { - 51 192 : dataset = X; - 52 192 : buildDataset(y); - 53 180 : const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble); - 54 312 : return build(features, className, states, weights); - 55 180 : } + 51 64 : dataset = X; + 52 64 : buildDataset(y); + 53 60 : const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble); + 54 104 : return build(features, className, states, weights); + 55 60 : } 56 : // X is nxm where n is the number of features and m the number of samples - 57 180 : Classifier& Classifier::fit(std::vector<std::vector<int>>& X, std::vector<int>& y, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) + 57 60 : Classifier& Classifier::fit(std::vector<std::vector<int>>& X, std::vector<int>& y, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) 58 : { - 59 180 : dataset = torch::zeros({ static_cast<int>(X.size()), static_cast<int>(X[0].size()) }, torch::kInt32); - 60 1254 : for (int i = 0; i < X.size(); ++i) { - 61 4296 : dataset.index_put_({ i, "..." }, torch::tensor(X[i], torch::kInt32)); + 59 60 : dataset = torch::zeros({ static_cast<int>(X.size()), static_cast<int>(X[0].size()) }, torch::kInt32); + 60 418 : for (int i = 0; i < X.size(); ++i) { + 61 1432 : dataset.index_put_({ i, "..." }, torch::tensor(X[i], torch::kInt32)); 62 : } - 63 180 : auto ytmp = torch::tensor(y, torch::kInt32); - 64 180 : buildDataset(ytmp); - 65 168 : const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble); - 66 312 : return build(features, className, states, weights); - 67 1278 : } - 68 594 : Classifier& Classifier::fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) + 63 60 : auto ytmp = torch::tensor(y, torch::kInt32); + 64 60 : buildDataset(ytmp); + 65 56 : const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble); + 66 104 : return build(features, className, states, weights); + 67 426 : } + 68 198 : Classifier& Classifier::fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) 69 : { - 70 594 : this->dataset = dataset; - 71 594 : const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble); - 72 1188 : return build(features, className, states, weights); - 73 594 : } - 74 990 : Classifier& Classifier::fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states, const torch::Tensor& weights) + 70 198 : this->dataset = dataset; + 71 198 : const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble); + 72 396 : return build(features, className, states, weights); + 73 198 : } + 74 330 : Classifier& Classifier::fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states, const torch::Tensor& weights) 75 : { - 76 990 : this->dataset = dataset; - 77 990 : return build(features, className, states, weights); + 76 330 : this->dataset = dataset; + 77 330 : return build(features, className, states, weights); 78 : } - 79 1932 : void Classifier::checkFitParameters() + 79 644 : void Classifier::checkFitParameters() 80 : { - 81 1932 : if (torch::is_floating_point(dataset)) { - 82 12 : throw std::invalid_argument("dataset (X, y) must be of type Integer"); + 81 644 : if (torch::is_floating_point(dataset)) { + 82 4 : throw std::invalid_argument("dataset (X, y) must be of type Integer"); 83 : } - 84 1920 : if (dataset.size(0) - 1 != features.size()) { - 85 12 : throw std::invalid_argument("Classifier: X " + std::to_string(dataset.size(0) - 1) + " and features " + std::to_string(features.size()) + " must have the same number of features"); + 84 640 : if (dataset.size(0) - 1 != features.size()) { + 85 4 : throw std::invalid_argument("Classifier: X " + std::to_string(dataset.size(0) - 1) + " and features " + std::to_string(features.size()) + " must have the same number of features"); 86 : } - 87 1908 : if (states.find(className) == states.end()) { - 88 12 : throw std::invalid_argument("class name not found in states"); + 87 636 : if (states.find(className) == states.end()) { + 88 4 : throw std::invalid_argument("class name not found in states"); 89 : } - 90 42624 : for (auto feature : features) { - 91 40740 : if (states.find(feature) == states.end()) { - 92 12 : throw std::invalid_argument("feature [" + feature + "] not found in states"); + 90 14208 : for (auto feature : features) { + 91 13580 : if (states.find(feature) == states.end()) { + 92 4 : throw std::invalid_argument("feature [" + feature + "] not found in states"); 93 : } - 94 40740 : } - 95 1884 : } - 96 2550 : torch::Tensor Classifier::predict(torch::Tensor& X) + 94 13580 : } + 95 628 : } + 96 850 : torch::Tensor Classifier::predict(torch::Tensor& X) 97 : { - 98 2550 : if (!fitted) { - 99 24 : throw std::logic_error(CLASSIFIER_NOT_FITTED); + 98 850 : if (!fitted) { + 99 8 : throw std::logic_error(CLASSIFIER_NOT_FITTED); 100 : } - 101 2526 : return model.predict(X); + 101 842 : return model.predict(X); 102 : } - 103 24 : std::vector<int> Classifier::predict(std::vector<std::vector<int>>& X) + 103 8 : std::vector<int> Classifier::predict(std::vector<std::vector<int>>& X) 104 : { - 105 24 : if (!fitted) { - 106 12 : throw std::logic_error(CLASSIFIER_NOT_FITTED); + 105 8 : if (!fitted) { + 106 4 : throw std::logic_error(CLASSIFIER_NOT_FITTED); 107 : } - 108 12 : auto m_ = X[0].size(); - 109 12 : auto n_ = X.size(); - 110 12 : std::vector<std::vector<int>> Xd(n_, std::vector<int>(m_, 0)); - 111 60 : for (auto i = 0; i < n_; i++) { - 112 96 : Xd[i] = std::vector<int>(X[i].begin(), X[i].end()); + 108 4 : auto m_ = X[0].size(); + 109 4 : auto n_ = X.size(); + 110 4 : std::vector<std::vector<int>> Xd(n_, std::vector<int>(m_, 0)); + 111 20 : for (auto i = 0; i < n_; i++) { + 112 32 : Xd[i] = std::vector<int>(X[i].begin(), X[i].end()); 113 : } - 114 12 : auto yp = model.predict(Xd); - 115 24 : return yp; - 116 12 : } - 117 2226 : torch::Tensor Classifier::predict_proba(torch::Tensor& X) + 114 4 : auto yp = model.predict(Xd); + 115 8 : return yp; + 116 4 : } + 117 742 : torch::Tensor Classifier::predict_proba(torch::Tensor& X) 118 : { - 119 2226 : if (!fitted) { - 120 12 : throw std::logic_error(CLASSIFIER_NOT_FITTED); + 119 742 : if (!fitted) { + 120 4 : throw std::logic_error(CLASSIFIER_NOT_FITTED); 121 : } - 122 2214 : return model.predict_proba(X); + 122 738 : return model.predict_proba(X); 123 : } - 124 390 : std::vector<std::vector<double>> Classifier::predict_proba(std::vector<std::vector<int>>& X) + 124 130 : std::vector<std::vector<double>> Classifier::predict_proba(std::vector<std::vector<int>>& X) 125 : { - 126 390 : if (!fitted) { - 127 12 : throw std::logic_error(CLASSIFIER_NOT_FITTED); + 126 130 : if (!fitted) { + 127 4 : throw std::logic_error(CLASSIFIER_NOT_FITTED); 128 : } - 129 378 : auto m_ = X[0].size(); - 130 378 : auto n_ = X.size(); - 131 378 : std::vector<std::vector<int>> Xd(n_, std::vector<int>(m_, 0)); + 129 126 : auto m_ = X[0].size(); + 130 126 : auto n_ = X.size(); + 131 126 : std::vector<std::vector<int>> Xd(n_, std::vector<int>(m_, 0)); 132 : // Convert to nxm vector - 133 3240 : for (auto i = 0; i < n_; i++) { - 134 5724 : Xd[i] = std::vector<int>(X[i].begin(), X[i].end()); + 133 1080 : for (auto i = 0; i < n_; i++) { + 134 1908 : Xd[i] = std::vector<int>(X[i].begin(), X[i].end()); 135 : } - 136 378 : auto yp = model.predict_proba(Xd); - 137 756 : return yp; - 138 378 : } - 139 168 : float Classifier::score(torch::Tensor& X, torch::Tensor& y) + 136 126 : auto yp = model.predict_proba(Xd); + 137 252 : return yp; + 138 126 : } + 139 56 : float Classifier::score(torch::Tensor& X, torch::Tensor& y) 140 : { - 141 168 : torch::Tensor y_pred = predict(X); - 142 312 : return (y_pred == y).sum().item<float>() / y.size(0); - 143 156 : } - 144 24 : float Classifier::score(std::vector<std::vector<int>>& X, std::vector<int>& y) + 141 56 : torch::Tensor y_pred = predict(X); + 142 104 : return (y_pred == y).sum().item<float>() / y.size(0); + 143 52 : } + 144 8 : float Classifier::score(std::vector<std::vector<int>>& X, std::vector<int>& y) 145 : { - 146 24 : if (!fitted) { - 147 12 : throw std::logic_error(CLASSIFIER_NOT_FITTED); + 146 8 : if (!fitted) { + 147 4 : throw std::logic_error(CLASSIFIER_NOT_FITTED); 148 : } - 149 12 : return model.score(X, y); + 149 4 : return model.score(X, y); 150 : } - 151 36 : std::vector<std::string> Classifier::show() const + 151 12 : std::vector<std::string> Classifier::show() const 152 : { - 153 36 : return model.show(); + 153 12 : return model.show(); 154 : } - 155 1680 : void Classifier::addNodes() + 155 560 : void Classifier::addNodes() 156 : { 157 : // Add all nodes to the network - 158 39648 : for (const auto& feature : features) { - 159 37968 : model.addNode(feature); + 158 13216 : for (const auto& feature : features) { + 159 12656 : model.addNode(feature); 160 : } - 161 1680 : model.addNode(className); - 162 1680 : } - 163 282 : int Classifier::getNumberOfNodes() const + 161 560 : model.addNode(className); + 162 560 : } + 163 94 : int Classifier::getNumberOfNodes() const 164 : { 165 : // Features does not include class - 166 282 : return fitted ? model.getFeatures().size() : 0; + 166 94 : return fitted ? model.getFeatures().size() : 0; 167 : } - 168 282 : int Classifier::getNumberOfEdges() const + 168 94 : int Classifier::getNumberOfEdges() const 169 : { - 170 282 : return fitted ? model.getNumEdges() : 0; + 170 94 : return fitted ? model.getNumEdges() : 0; 171 : } - 172 36 : int Classifier::getNumberOfStates() const + 172 12 : int Classifier::getNumberOfStates() const 173 : { - 174 36 : return fitted ? model.getStates() : 0; + 174 12 : return fitted ? model.getStates() : 0; 175 : } - 176 510 : int Classifier::getClassNumStates() const + 176 170 : int Classifier::getClassNumStates() const 177 : { - 178 510 : return fitted ? model.getClassNumStates() : 0; + 178 170 : return fitted ? model.getClassNumStates() : 0; 179 : } - 180 6 : std::vector<std::string> Classifier::topological_order() + 180 2 : std::vector<std::string> Classifier::topological_order() 181 : { - 182 6 : return model.topological_sort(); + 182 2 : return model.topological_sort(); 183 : } - 184 6 : std::string Classifier::dump_cpt() const + 184 2 : std::string Classifier::dump_cpt() const 185 : { - 186 6 : return model.dump_cpt(); + 186 2 : return model.dump_cpt(); 187 : } - 188 126 : void Classifier::setHyperparameters(const nlohmann::json& hyperparameters) + 188 42 : void Classifier::setHyperparameters(const nlohmann::json& hyperparameters) 189 : { - 190 126 : if (!hyperparameters.empty()) { - 191 12 : throw std::invalid_argument("Invalid hyperparameters" + hyperparameters.dump()); + 190 42 : if (!hyperparameters.empty()) { + 191 4 : throw std::invalid_argument("Invalid hyperparameters" + hyperparameters.dump()); 192 : } - 193 114 : } + 193 38 : } 194 : } diff --git a/html/bayesnet/classifiers/Classifier.h.func-c.html b/html/bayesnet/classifiers/Classifier.h.func-c.html index 4d88ce0..a477d42 100644 --- a/html/bayesnet/classifiers/Classifier.h.func-c.html +++ b/html/bayesnet/classifiers/Classifier.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::Classifier::getVersion[abi:cxx11]() - 48 + 16 bayesnet::Classifier::getNotes[abi:cxx11]() const - 114 + 38 bayesnet::Classifier::getStatus() const - 192 + 64 bayesnet::Classifier::~Classifier() - 1818 + 606 diff --git a/html/bayesnet/classifiers/Classifier.h.func.html b/html/bayesnet/classifiers/Classifier.h.func.html index 3578e8a..c7db78b 100644 --- a/html/bayesnet/classifiers/Classifier.h.func.html +++ b/html/bayesnet/classifiers/Classifier.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::Classifier::getNotes[abi:cxx11]() const - 114 + 38 bayesnet::Classifier::getStatus() const - 192 + 64 bayesnet::Classifier::getVersion[abi:cxx11]() - 48 + 16 bayesnet::Classifier::~Classifier() - 1818 + 606 diff --git a/html/bayesnet/classifiers/Classifier.h.gcov.html b/html/bayesnet/classifiers/Classifier.h.gcov.html index 9aa27a0..0e80991 100644 --- a/html/bayesnet/classifiers/Classifier.h.gcov.html +++ b/html/bayesnet/classifiers/Classifier.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -77,7 +77,7 @@ 15 : class Classifier : public BaseClassifier { 16 : public: 17 : Classifier(Network model); - 18 1818 : virtual ~Classifier() = default; + 18 606 : virtual ~Classifier() = default; 19 : Classifier& fit(std::vector<std::vector<int>>& X, std::vector<int>& y, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) override; 20 : Classifier& fit(torch::Tensor& X, torch::Tensor& y, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) override; 21 : Classifier& fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) override; @@ -91,13 +91,13 @@ 29 : std::vector<int> predict(std::vector<std::vector<int>>& X) override; 30 : torch::Tensor predict_proba(torch::Tensor& X) override; 31 : std::vector<std::vector<double>> predict_proba(std::vector<std::vector<int>>& X) override; - 32 192 : status_t getStatus() const override { return status; } - 33 144 : std::string getVersion() override { return { project_version.begin(), project_version.end() }; }; + 32 64 : status_t getStatus() const override { return status; } + 33 48 : std::string getVersion() override { return { project_version.begin(), project_version.end() }; }; 34 : float score(torch::Tensor& X, torch::Tensor& y) override; 35 : float score(std::vector<std::vector<int>>& X, std::vector<int>& y) override; 36 : std::vector<std::string> show() const override; 37 : std::vector<std::string> topological_order() override; - 38 114 : std::vector<std::string> getNotes() const override { return notes; } + 38 38 : std::vector<std::string> getNotes() const override { return notes; } 39 : std::string dump_cpt() const override; 40 : void setHyperparameters(const nlohmann::json& hyperparameters) override; //For classifiers that don't have hyperparameters 41 : protected: diff --git a/html/bayesnet/classifiers/KDB.cc.func-c.html b/html/bayesnet/classifiers/KDB.cc.func-c.html index a4db5e1..5d686ab 100644 --- a/html/bayesnet/classifiers/KDB.cc.func-c.html +++ b/html/bayesnet/classifiers/KDB.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,35 +65,35 @@ bayesnet::KDB::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 12 + 4 bayesnet::KDB::setHyperparameters(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) - 18 + 6 bayesnet::KDB::buildModel(at::Tensor const&) - 78 + 26 bayesnet::KDB::KDB(int, float) - 222 + 74 bayesnet::KDB::add_m_edges(int, std::vector<int, std::allocator<int> >&, at::Tensor&) - 516 + 172 diff --git a/html/bayesnet/classifiers/KDB.cc.func.html b/html/bayesnet/classifiers/KDB.cc.func.html index 31261b4..564e33e 100644 --- a/html/bayesnet/classifiers/KDB.cc.func.html +++ b/html/bayesnet/classifiers/KDB.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,35 +65,35 @@ bayesnet::KDB::KDB(int, float) - 222 + 74 bayesnet::KDB::add_m_edges(int, std::vector<int, std::allocator<int> >&, at::Tensor&) - 516 + 172 bayesnet::KDB::buildModel(at::Tensor const&) - 78 + 26 bayesnet::KDB::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 12 + 4 bayesnet::KDB::setHyperparameters(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) - 18 + 6 diff --git a/html/bayesnet/classifiers/KDB.cc.gcov.html b/html/bayesnet/classifiers/KDB.cc.gcov.html index b618d38..97c5736 100644 --- a/html/bayesnet/classifiers/KDB.cc.gcov.html +++ b/html/bayesnet/classifiers/KDB.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -69,25 +69,25 @@ 7 : #include "KDB.h" 8 : 9 : namespace bayesnet { - 10 222 : KDB::KDB(int k, float theta) : Classifier(Network()), k(k), theta(theta) + 10 74 : KDB::KDB(int k, float theta) : Classifier(Network()), k(k), theta(theta) 11 : { - 12 666 : validHyperparameters = { "k", "theta" }; + 12 222 : validHyperparameters = { "k", "theta" }; 13 : - 14 666 : } - 15 18 : void KDB::setHyperparameters(const nlohmann::json& hyperparameters_) + 14 222 : } + 15 6 : void KDB::setHyperparameters(const nlohmann::json& hyperparameters_) 16 : { - 17 18 : auto hyperparameters = hyperparameters_; - 18 18 : if (hyperparameters.contains("k")) { - 19 6 : k = hyperparameters["k"]; - 20 6 : hyperparameters.erase("k"); + 17 6 : auto hyperparameters = hyperparameters_; + 18 6 : if (hyperparameters.contains("k")) { + 19 2 : k = hyperparameters["k"]; + 20 2 : hyperparameters.erase("k"); 21 : } - 22 18 : if (hyperparameters.contains("theta")) { - 23 6 : theta = hyperparameters["theta"]; - 24 6 : hyperparameters.erase("theta"); + 22 6 : if (hyperparameters.contains("theta")) { + 23 2 : theta = hyperparameters["theta"]; + 24 2 : hyperparameters.erase("theta"); 25 : } - 26 18 : Classifier::setHyperparameters(hyperparameters); - 27 18 : } - 28 78 : void KDB::buildModel(const torch::Tensor& weights) + 26 6 : Classifier::setHyperparameters(hyperparameters); + 27 6 : } + 28 26 : void KDB::buildModel(const torch::Tensor& weights) 29 : { 30 : /* 31 : 1. For each feature Xi, compute mutual information, I(X;C), @@ -110,66 +110,66 @@ 48 : */ 49 : // 1. For each feature Xi, compute mutual information, I(X;C), 50 : // where C is the class. - 51 78 : addNodes(); - 52 234 : const torch::Tensor& y = dataset.index({ -1, "..." }); - 53 78 : std::vector<double> mi; - 54 594 : for (auto i = 0; i < features.size(); i++) { - 55 1548 : torch::Tensor firstFeature = dataset.index({ i, "..." }); - 56 516 : mi.push_back(metrics.mutualInformation(firstFeature, y, weights)); - 57 516 : } + 51 26 : addNodes(); + 52 78 : const torch::Tensor& y = dataset.index({ -1, "..." }); + 53 26 : std::vector<double> mi; + 54 198 : for (auto i = 0; i < features.size(); i++) { + 55 516 : torch::Tensor firstFeature = dataset.index({ i, "..." }); + 56 172 : mi.push_back(metrics.mutualInformation(firstFeature, y, weights)); + 57 172 : } 58 : // 2. Compute class conditional mutual information I(Xi;XjIC), f or each - 59 78 : auto conditionalEdgeWeights = metrics.conditionalEdge(weights); + 59 26 : auto conditionalEdgeWeights = metrics.conditionalEdge(weights); 60 : // 3. Let the used variable list, S, be empty. - 61 78 : std::vector<int> S; + 61 26 : std::vector<int> S; 62 : // 4. Let the DAG network being constructed, BN, begin with a single 63 : // class node, C. 64 : // 5. Repeat until S includes all domain features 65 : // 5.1. Select feature Xmax which is not in S and has the largest value 66 : // I(Xmax;C). - 67 78 : auto order = argsort(mi); - 68 594 : for (auto idx : order) { + 67 26 : auto order = argsort(mi); + 68 198 : for (auto idx : order) { 69 : // 5.2. Add a node to BN representing Xmax. 70 : // 5.3. Add an arc from C to Xmax in BN. - 71 516 : model.addEdge(className, features[idx]); + 71 172 : model.addEdge(className, features[idx]); 72 : // 5.4. Add m = min(lSl,/c) arcs from m distinct features Xj in S with 73 : // the highest value for I(Xmax;X,jC). - 74 516 : add_m_edges(idx, S, conditionalEdgeWeights); + 74 172 : add_m_edges(idx, S, conditionalEdgeWeights); 75 : // 5.5. Add Xmax to S. - 76 516 : S.push_back(idx); + 76 172 : S.push_back(idx); 77 : } - 78 672 : } - 79 516 : void KDB::add_m_edges(int idx, std::vector<int>& S, torch::Tensor& weights) + 78 224 : } + 79 172 : void KDB::add_m_edges(int idx, std::vector<int>& S, torch::Tensor& weights) 80 : { - 81 516 : auto n_edges = std::min(k, static_cast<int>(S.size())); - 82 516 : auto cond_w = clone(weights); - 83 516 : bool exit_cond = k == 0; - 84 516 : int num = 0; - 85 1506 : while (!exit_cond) { - 86 3960 : auto max_minfo = argmax(cond_w.index({ idx, "..." })).item<int>(); - 87 990 : auto belongs = find(S.begin(), S.end(), max_minfo) != S.end(); - 88 2646 : if (belongs && cond_w.index({ idx, max_minfo }).item<float>() > theta) { + 81 172 : auto n_edges = std::min(k, static_cast<int>(S.size())); + 82 172 : auto cond_w = clone(weights); + 83 172 : bool exit_cond = k == 0; + 84 172 : int num = 0; + 85 502 : while (!exit_cond) { + 86 1320 : auto max_minfo = argmax(cond_w.index({ idx, "..." })).item<int>(); + 87 330 : auto belongs = find(S.begin(), S.end(), max_minfo) != S.end(); + 88 882 : if (belongs && cond_w.index({ idx, max_minfo }).item<float>() > theta) { 89 : try { - 90 480 : model.addEdge(features[max_minfo], features[idx]); - 91 480 : num++; + 90 160 : model.addEdge(features[max_minfo], features[idx]); + 91 160 : num++; 92 : } 93 0 : catch (const std::invalid_argument& e) { 94 : // Loops are not allowed 95 0 : } 96 : } - 97 3960 : cond_w.index_put_({ idx, max_minfo }, -1); - 98 2970 : auto candidates_mask = cond_w.index({ idx, "..." }).gt(theta); - 99 990 : auto candidates = candidates_mask.nonzero(); - 100 990 : exit_cond = num == n_edges || candidates.size(0) == 0; - 101 990 : } - 102 4038 : } - 103 12 : std::vector<std::string> KDB::graph(const std::string& title) const + 97 1320 : cond_w.index_put_({ idx, max_minfo }, -1); + 98 990 : auto candidates_mask = cond_w.index({ idx, "..." }).gt(theta); + 99 330 : auto candidates = candidates_mask.nonzero(); + 100 330 : exit_cond = num == n_edges || candidates.size(0) == 0; + 101 330 : } + 102 1346 : } + 103 4 : std::vector<std::string> KDB::graph(const std::string& title) const 104 : { - 105 12 : std::string header{ title }; - 106 12 : if (title == "KDB") { - 107 12 : header += " (k=" + std::to_string(k) + ", theta=" + std::to_string(theta) + ")"; + 105 4 : std::string header{ title }; + 106 4 : if (title == "KDB") { + 107 4 : header += " (k=" + std::to_string(k) + ", theta=" + std::to_string(theta) + ")"; 108 : } - 109 24 : return model.graph(header); - 110 12 : } + 109 8 : return model.graph(header); + 110 4 : } 111 : } diff --git a/html/bayesnet/classifiers/KDB.h.func-c.html b/html/bayesnet/classifiers/KDB.h.func-c.html index 8cf47d3..fc6e29f 100644 --- a/html/bayesnet/classifiers/KDB.h.func-c.html +++ b/html/bayesnet/classifiers/KDB.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::KDB::~KDB() - 66 + 22 diff --git a/html/bayesnet/classifiers/KDB.h.func.html b/html/bayesnet/classifiers/KDB.h.func.html index d85d7ff..6df69ae 100644 --- a/html/bayesnet/classifiers/KDB.h.func.html +++ b/html/bayesnet/classifiers/KDB.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::KDB::~KDB() - 66 + 22 diff --git a/html/bayesnet/classifiers/KDB.h.gcov.html b/html/bayesnet/classifiers/KDB.h.gcov.html index b915154..8d793ca 100644 --- a/html/bayesnet/classifiers/KDB.h.gcov.html +++ b/html/bayesnet/classifiers/KDB.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -81,7 +81,7 @@ 19 : void buildModel(const torch::Tensor& weights) override; 20 : public: 21 : explicit KDB(int k, float theta = 0.03); - 22 66 : virtual ~KDB() = default; + 22 22 : virtual ~KDB() = default; 23 : void setHyperparameters(const nlohmann::json& hyperparameters_) override; 24 : std::vector<std::string> graph(const std::string& name = "KDB") const override; 25 : }; diff --git a/html/bayesnet/classifiers/KDBLd.cc.func-c.html b/html/bayesnet/classifiers/KDBLd.cc.func-c.html index f7c7fd8..c572061 100644 --- a/html/bayesnet/classifiers/KDBLd.cc.func-c.html +++ b/html/bayesnet/classifiers/KDBLd.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::KDBLd::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::KDBLd::predict(at::Tensor&) - 24 + 8 bayesnet::KDBLd::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 30 + 10 bayesnet::KDBLd::KDBLd(int) - 102 + 34 diff --git a/html/bayesnet/classifiers/KDBLd.cc.func.html b/html/bayesnet/classifiers/KDBLd.cc.func.html index 7009cb5..8447f2c 100644 --- a/html/bayesnet/classifiers/KDBLd.cc.func.html +++ b/html/bayesnet/classifiers/KDBLd.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::KDBLd::KDBLd(int) - 102 + 34 bayesnet::KDBLd::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 30 + 10 bayesnet::KDBLd::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::KDBLd::predict(at::Tensor&) - 24 + 8 diff --git a/html/bayesnet/classifiers/KDBLd.cc.gcov.html b/html/bayesnet/classifiers/KDBLd.cc.gcov.html index e234a92..60ad8e2 100644 --- a/html/bayesnet/classifiers/KDBLd.cc.gcov.html +++ b/html/bayesnet/classifiers/KDBLd.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -69,30 +69,30 @@ 7 : #include "KDBLd.h" 8 : 9 : namespace bayesnet { - 10 102 : KDBLd::KDBLd(int k) : KDB(k), Proposal(dataset, features, className) {} - 11 30 : KDBLd& KDBLd::fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) + 10 34 : KDBLd::KDBLd(int k) : KDB(k), Proposal(dataset, features, className) {} + 11 10 : KDBLd& KDBLd::fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) 12 : { - 13 30 : checkInput(X_, y_); - 14 30 : features = features_; - 15 30 : className = className_; - 16 30 : Xf = X_; - 17 30 : y = y_; + 13 10 : checkInput(X_, y_); + 14 10 : features = features_; + 15 10 : className = className_; + 16 10 : Xf = X_; + 17 10 : y = y_; 18 : // Fills std::vectors Xv & yv with the data from tensors X_ (discretized) & y - 19 30 : states = fit_local_discretization(y); + 19 10 : states = fit_local_discretization(y); 20 : // We have discretized the input data 21 : // 1st we need to fit the model to build the normal KDB structure, KDB::fit initializes the base Bayesian network - 22 30 : KDB::fit(dataset, features, className, states); - 23 30 : states = localDiscretizationProposal(states, model); - 24 30 : return *this; + 22 10 : KDB::fit(dataset, features, className, states); + 23 10 : states = localDiscretizationProposal(states, model); + 24 10 : return *this; 25 : } - 26 24 : torch::Tensor KDBLd::predict(torch::Tensor& X) + 26 8 : torch::Tensor KDBLd::predict(torch::Tensor& X) 27 : { - 28 24 : auto Xt = prepareX(X); - 29 48 : return KDB::predict(Xt); - 30 24 : } - 31 6 : std::vector<std::string> KDBLd::graph(const std::string& name) const + 28 8 : auto Xt = prepareX(X); + 29 16 : return KDB::predict(Xt); + 30 8 : } + 31 2 : std::vector<std::string> KDBLd::graph(const std::string& name) const 32 : { - 33 6 : return KDB::graph(name); + 33 2 : return KDB::graph(name); 34 : } 35 : } diff --git a/html/bayesnet/classifiers/KDBLd.h.func-c.html b/html/bayesnet/classifiers/KDBLd.h.func-c.html index c2ba0fd..c3699bc 100644 --- a/html/bayesnet/classifiers/KDBLd.h.func-c.html +++ b/html/bayesnet/classifiers/KDBLd.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::KDBLd::~KDBLd() - 30 + 10 diff --git a/html/bayesnet/classifiers/KDBLd.h.func.html b/html/bayesnet/classifiers/KDBLd.h.func.html index a26434f..40758e9 100644 --- a/html/bayesnet/classifiers/KDBLd.h.func.html +++ b/html/bayesnet/classifiers/KDBLd.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::KDBLd::~KDBLd() - 30 + 10 diff --git a/html/bayesnet/classifiers/KDBLd.h.gcov.html b/html/bayesnet/classifiers/KDBLd.h.gcov.html index 2a701ea..0d39c7b 100644 --- a/html/bayesnet/classifiers/KDBLd.h.gcov.html +++ b/html/bayesnet/classifiers/KDBLd.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -76,7 +76,7 @@ 14 : private: 15 : public: 16 : explicit KDBLd(int k); - 17 30 : virtual ~KDBLd() = default; + 17 10 : virtual ~KDBLd() = default; 18 : KDBLd& fit(torch::Tensor& X, torch::Tensor& y, const std::vector<std::string>& features, const std::string& className, map<std::string, std::vector<int>>& states) override; 19 : std::vector<std::string> graph(const std::string& name = "KDB") const override; 20 : torch::Tensor predict(torch::Tensor& X) override; diff --git a/html/bayesnet/classifiers/Proposal.cc.func-c.html b/html/bayesnet/classifiers/Proposal.cc.func-c.html index cb28703..af841f7 100644 --- a/html/bayesnet/classifiers/Proposal.cc.func-c.html +++ b/html/bayesnet/classifiers/Proposal.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,56 +65,56 @@ bayesnet::Proposal::prepareX(at::Tensor&) - 252 + 84 bayesnet::Proposal::~Proposal() - 300 + 100 bayesnet::Proposal::localDiscretizationProposal(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > > const&, bayesnet::Network&) - 318 + 106 bayesnet::Proposal::checkInput(at::Tensor const&, at::Tensor const&) - 342 + 114 bayesnet::Proposal::fit_local_discretization[abi:cxx11](at::Tensor const&) - 348 + 116 bayesnet::Proposal::Proposal(at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) - 636 + 212 auto bayesnet::Proposal::localDiscretizationProposal(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > > const&, bayesnet::Network&)::{lambda(auto:1 const&)#2}::operator()<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 2058 + 686 auto bayesnet::Proposal::localDiscretizationProposal(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > > const&, bayesnet::Network&)::{lambda(auto:1 const&)#1}::operator()<bayesnet::Node*>(bayesnet::Node* const&) const - 4044 + 1348 diff --git a/html/bayesnet/classifiers/Proposal.cc.func.html b/html/bayesnet/classifiers/Proposal.cc.func.html index 7238199..b0f2625 100644 --- a/html/bayesnet/classifiers/Proposal.cc.func.html +++ b/html/bayesnet/classifiers/Proposal.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,56 +65,56 @@ auto bayesnet::Proposal::localDiscretizationProposal(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > > const&, bayesnet::Network&)::{lambda(auto:1 const&)#1}::operator()<bayesnet::Node*>(bayesnet::Node* const&) const - 4044 + 1348 auto bayesnet::Proposal::localDiscretizationProposal(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > > const&, bayesnet::Network&)::{lambda(auto:1 const&)#2}::operator()<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 2058 + 686 bayesnet::Proposal::Proposal(at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) - 636 + 212 bayesnet::Proposal::checkInput(at::Tensor const&, at::Tensor const&) - 342 + 114 bayesnet::Proposal::fit_local_discretization[abi:cxx11](at::Tensor const&) - 348 + 116 bayesnet::Proposal::localDiscretizationProposal(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > > const&, bayesnet::Network&) - 318 + 106 bayesnet::Proposal::prepareX(at::Tensor&) - 252 + 84 bayesnet::Proposal::~Proposal() - 300 + 100 diff --git a/html/bayesnet/classifiers/Proposal.cc.gcov.html b/html/bayesnet/classifiers/Proposal.cc.gcov.html index df175ac..cac4c28 100644 --- a/html/bayesnet/classifiers/Proposal.cc.gcov.html +++ b/html/bayesnet/classifiers/Proposal.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,111 +70,111 @@ 8 : #include "Proposal.h" 9 : 10 : namespace bayesnet { - 11 636 : Proposal::Proposal(torch::Tensor& dataset_, std::vector<std::string>& features_, std::string& className_) : pDataset(dataset_), pFeatures(features_), pClassName(className_) {} - 12 300 : Proposal::~Proposal() + 11 212 : Proposal::Proposal(torch::Tensor& dataset_, std::vector<std::string>& features_, std::string& className_) : pDataset(dataset_), pFeatures(features_), pClassName(className_) {} + 12 100 : Proposal::~Proposal() 13 : { - 14 2844 : for (auto& [key, value] : discretizers) { - 15 2544 : delete value; + 14 948 : for (auto& [key, value] : discretizers) { + 15 848 : delete value; 16 : } - 17 300 : } - 18 342 : void Proposal::checkInput(const torch::Tensor& X, const torch::Tensor& y) + 17 100 : } + 18 114 : void Proposal::checkInput(const torch::Tensor& X, const torch::Tensor& y) 19 : { - 20 342 : if (!torch::is_floating_point(X)) { + 20 114 : if (!torch::is_floating_point(X)) { 21 0 : throw std::invalid_argument("X must be a floating point tensor"); 22 : } - 23 342 : if (torch::is_floating_point(y)) { + 23 114 : if (torch::is_floating_point(y)) { 24 0 : throw std::invalid_argument("y must be an integer tensor"); 25 : } - 26 342 : } - 27 318 : map<std::string, std::vector<int>> Proposal::localDiscretizationProposal(const map<std::string, std::vector<int>>& oldStates, Network& model) + 26 114 : } + 27 106 : map<std::string, std::vector<int>> Proposal::localDiscretizationProposal(const map<std::string, std::vector<int>>& oldStates, Network& model) 28 : { 29 : // order of local discretization is important. no good 0, 1, 2... 30 : // although we rediscretize features after the local discretization of every feature - 31 318 : auto order = model.topological_sort(); - 32 318 : auto& nodes = model.getNodes(); - 33 318 : map<std::string, std::vector<int>> states = oldStates; - 34 318 : std::vector<int> indicesToReDiscretize; - 35 318 : bool upgrade = false; // Flag to check if we need to upgrade the model - 36 2664 : for (auto feature : order) { - 37 2346 : auto nodeParents = nodes[feature]->getParents(); - 38 2346 : if (nodeParents.size() < 2) continue; // Only has class as parent - 39 1986 : upgrade = true; - 40 1986 : int index = find(pFeatures.begin(), pFeatures.end(), feature) - pFeatures.begin(); - 41 1986 : indicesToReDiscretize.push_back(index); // We need to re-discretize this feature - 42 1986 : std::vector<std::string> parents; - 43 6030 : transform(nodeParents.begin(), nodeParents.end(), back_inserter(parents), [](const auto& p) { return p->getName(); }); + 31 106 : auto order = model.topological_sort(); + 32 106 : auto& nodes = model.getNodes(); + 33 106 : map<std::string, std::vector<int>> states = oldStates; + 34 106 : std::vector<int> indicesToReDiscretize; + 35 106 : bool upgrade = false; // Flag to check if we need to upgrade the model + 36 888 : for (auto feature : order) { + 37 782 : auto nodeParents = nodes[feature]->getParents(); + 38 782 : if (nodeParents.size() < 2) continue; // Only has class as parent + 39 662 : upgrade = true; + 40 662 : int index = find(pFeatures.begin(), pFeatures.end(), feature) - pFeatures.begin(); + 41 662 : indicesToReDiscretize.push_back(index); // We need to re-discretize this feature + 42 662 : std::vector<std::string> parents; + 43 2010 : transform(nodeParents.begin(), nodeParents.end(), back_inserter(parents), [](const auto& p) { return p->getName(); }); 44 : // Remove class as parent as it will be added later - 45 1986 : parents.erase(remove(parents.begin(), parents.end(), pClassName), parents.end()); + 45 662 : parents.erase(remove(parents.begin(), parents.end(), pClassName), parents.end()); 46 : // Get the indices of the parents - 47 1986 : std::vector<int> indices; - 48 1986 : indices.push_back(-1); // Add class index - 49 4044 : transform(parents.begin(), parents.end(), back_inserter(indices), [&](const auto& p) {return find(pFeatures.begin(), pFeatures.end(), p) - pFeatures.begin(); }); + 47 662 : std::vector<int> indices; + 48 662 : indices.push_back(-1); // Add class index + 49 1348 : transform(parents.begin(), parents.end(), back_inserter(indices), [&](const auto& p) {return find(pFeatures.begin(), pFeatures.end(), p) - pFeatures.begin(); }); 50 : // Now we fit the discretizer of the feature, conditioned on its parents and the class i.e. discretizer.fit(X[index], X[indices] + y) - 51 1986 : std::vector<std::string> yJoinParents(Xf.size(1)); - 52 6030 : for (auto idx : indices) { - 53 1437960 : for (int i = 0; i < Xf.size(1); ++i) { - 54 4301748 : yJoinParents[i] += to_string(pDataset.index({ idx, i }).item<int>()); + 51 662 : std::vector<std::string> yJoinParents(Xf.size(1)); + 52 2010 : for (auto idx : indices) { + 53 479320 : for (int i = 0; i < Xf.size(1); ++i) { + 54 1433916 : yJoinParents[i] += to_string(pDataset.index({ idx, i }).item<int>()); 55 : } 56 : } - 57 1986 : auto arff = ArffFiles(); - 58 1986 : auto yxv = arff.factorize(yJoinParents); - 59 3972 : auto xvf_ptr = Xf.index({ index }).data_ptr<float>(); - 60 1986 : auto xvf = std::vector<mdlp::precision_t>(xvf_ptr, xvf_ptr + Xf.size(1)); - 61 1986 : discretizers[feature]->fit(xvf, yxv); - 62 2706 : } - 63 318 : if (upgrade) { + 57 662 : auto arff = ArffFiles(); + 58 662 : auto yxv = arff.factorize(yJoinParents); + 59 1324 : auto xvf_ptr = Xf.index({ index }).data_ptr<float>(); + 60 662 : auto xvf = std::vector<mdlp::precision_t>(xvf_ptr, xvf_ptr + Xf.size(1)); + 61 662 : discretizers[feature]->fit(xvf, yxv); + 62 902 : } + 63 106 : if (upgrade) { 64 : // Discretize again X (only the affected indices) with the new fitted discretizers - 65 2304 : for (auto index : indicesToReDiscretize) { - 66 3972 : auto Xt_ptr = Xf.index({ index }).data_ptr<float>(); - 67 1986 : auto Xt = std::vector<float>(Xt_ptr, Xt_ptr + Xf.size(1)); - 68 7944 : pDataset.index_put_({ index, "..." }, torch::tensor(discretizers[pFeatures[index]]->transform(Xt))); - 69 1986 : auto xStates = std::vector<int>(discretizers[pFeatures[index]]->getCutPoints().size() + 1); - 70 1986 : iota(xStates.begin(), xStates.end(), 0); + 65 768 : for (auto index : indicesToReDiscretize) { + 66 1324 : auto Xt_ptr = Xf.index({ index }).data_ptr<float>(); + 67 662 : auto Xt = std::vector<float>(Xt_ptr, Xt_ptr + Xf.size(1)); + 68 2648 : pDataset.index_put_({ index, "..." }, torch::tensor(discretizers[pFeatures[index]]->transform(Xt))); + 69 662 : auto xStates = std::vector<int>(discretizers[pFeatures[index]]->getCutPoints().size() + 1); + 70 662 : iota(xStates.begin(), xStates.end(), 0); 71 : //Update new states of the feature/node - 72 1986 : states[pFeatures[index]] = xStates; - 73 1986 : } - 74 318 : const torch::Tensor weights = torch::full({ pDataset.size(1) }, 1.0 / pDataset.size(1), torch::kDouble); - 75 318 : model.fit(pDataset, weights, pFeatures, pClassName, states); - 76 318 : } - 77 636 : return states; - 78 1440192 : } - 79 348 : map<std::string, std::vector<int>> Proposal::fit_local_discretization(const torch::Tensor& y) + 72 662 : states[pFeatures[index]] = xStates; + 73 662 : } + 74 106 : const torch::Tensor weights = torch::full({ pDataset.size(1) }, 1.0 / pDataset.size(1), torch::kDouble); + 75 106 : model.fit(pDataset, weights, pFeatures, pClassName, states); + 76 106 : } + 77 212 : return states; + 78 480064 : } + 79 116 : map<std::string, std::vector<int>> Proposal::fit_local_discretization(const torch::Tensor& y) 80 : { 81 : // Discretize the continuous input data and build pDataset (Classifier::dataset) - 82 348 : int m = Xf.size(1); - 83 348 : int n = Xf.size(0); - 84 348 : map<std::string, std::vector<int>> states; - 85 348 : pDataset = torch::zeros({ n + 1, m }, torch::kInt32); - 86 348 : auto yv = std::vector<int>(y.data_ptr<int>(), y.data_ptr<int>() + y.size(0)); + 82 116 : int m = Xf.size(1); + 83 116 : int n = Xf.size(0); + 84 116 : map<std::string, std::vector<int>> states; + 85 116 : pDataset = torch::zeros({ n + 1, m }, torch::kInt32); + 86 116 : auto yv = std::vector<int>(y.data_ptr<int>(), y.data_ptr<int>() + y.size(0)); 87 : // discretize input data by feature(row) - 88 2916 : for (auto i = 0; i < pFeatures.size(); ++i) { - 89 2568 : auto* discretizer = new mdlp::CPPFImdlp(); - 90 5136 : auto Xt_ptr = Xf.index({ i }).data_ptr<float>(); - 91 2568 : auto Xt = std::vector<float>(Xt_ptr, Xt_ptr + Xf.size(1)); - 92 2568 : discretizer->fit(Xt, yv); - 93 10272 : pDataset.index_put_({ i, "..." }, torch::tensor(discretizer->transform(Xt))); - 94 2568 : auto xStates = std::vector<int>(discretizer->getCutPoints().size() + 1); - 95 2568 : iota(xStates.begin(), xStates.end(), 0); - 96 2568 : states[pFeatures[i]] = xStates; - 97 2568 : discretizers[pFeatures[i]] = discretizer; - 98 2568 : } - 99 348 : int n_classes = torch::max(y).item<int>() + 1; - 100 348 : auto yStates = std::vector<int>(n_classes); - 101 348 : iota(yStates.begin(), yStates.end(), 0); - 102 348 : states[pClassName] = yStates; - 103 1044 : pDataset.index_put_({ n, "..." }, y); - 104 696 : return states; - 105 5832 : } - 106 252 : torch::Tensor Proposal::prepareX(torch::Tensor& X) + 88 972 : for (auto i = 0; i < pFeatures.size(); ++i) { + 89 856 : auto* discretizer = new mdlp::CPPFImdlp(); + 90 1712 : auto Xt_ptr = Xf.index({ i }).data_ptr<float>(); + 91 856 : auto Xt = std::vector<float>(Xt_ptr, Xt_ptr + Xf.size(1)); + 92 856 : discretizer->fit(Xt, yv); + 93 3424 : pDataset.index_put_({ i, "..." }, torch::tensor(discretizer->transform(Xt))); + 94 856 : auto xStates = std::vector<int>(discretizer->getCutPoints().size() + 1); + 95 856 : iota(xStates.begin(), xStates.end(), 0); + 96 856 : states[pFeatures[i]] = xStates; + 97 856 : discretizers[pFeatures[i]] = discretizer; + 98 856 : } + 99 116 : int n_classes = torch::max(y).item<int>() + 1; + 100 116 : auto yStates = std::vector<int>(n_classes); + 101 116 : iota(yStates.begin(), yStates.end(), 0); + 102 116 : states[pClassName] = yStates; + 103 348 : pDataset.index_put_({ n, "..." }, y); + 104 232 : return states; + 105 1944 : } + 106 84 : torch::Tensor Proposal::prepareX(torch::Tensor& X) 107 : { - 108 252 : auto Xtd = torch::zeros_like(X, torch::kInt32); - 109 2064 : for (int i = 0; i < X.size(0); ++i) { - 110 1812 : auto Xt = std::vector<float>(X[i].data_ptr<float>(), X[i].data_ptr<float>() + X.size(1)); - 111 1812 : auto Xd = discretizers[pFeatures[i]]->transform(Xt); - 112 5436 : Xtd.index_put_({ i }, torch::tensor(Xd, torch::kInt32)); - 113 1812 : } - 114 252 : return Xtd; - 115 1812 : } + 108 84 : auto Xtd = torch::zeros_like(X, torch::kInt32); + 109 688 : for (int i = 0; i < X.size(0); ++i) { + 110 604 : auto Xt = std::vector<float>(X[i].data_ptr<float>(), X[i].data_ptr<float>() + X.size(1)); + 111 604 : auto Xd = discretizers[pFeatures[i]]->transform(Xt); + 112 1812 : Xtd.index_put_({ i }, torch::tensor(Xd, torch::kInt32)); + 113 604 : } + 114 84 : return Xtd; + 115 604 : } 116 : } diff --git a/html/bayesnet/classifiers/SPODE.cc.func-c.html b/html/bayesnet/classifiers/SPODE.cc.func-c.html index 4cbce73..71c9781 100644 --- a/html/bayesnet/classifiers/SPODE.cc.func-c.html +++ b/html/bayesnet/classifiers/SPODE.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,21 +65,21 @@ bayesnet::SPODE::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 102 + 34 bayesnet::SPODE::buildModel(at::Tensor const&) - 1524 + 508 bayesnet::SPODE::SPODE(int) - 1686 + 562 diff --git a/html/bayesnet/classifiers/SPODE.cc.func.html b/html/bayesnet/classifiers/SPODE.cc.func.html index c5a40dd..1928244 100644 --- a/html/bayesnet/classifiers/SPODE.cc.func.html +++ b/html/bayesnet/classifiers/SPODE.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,21 +65,21 @@ bayesnet::SPODE::SPODE(int) - 1686 + 562 bayesnet::SPODE::buildModel(at::Tensor const&) - 1524 + 508 bayesnet::SPODE::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 102 + 34 diff --git a/html/bayesnet/classifiers/SPODE.cc.gcov.html b/html/bayesnet/classifiers/SPODE.cc.gcov.html index 9d66059..fca8969 100644 --- a/html/bayesnet/classifiers/SPODE.cc.gcov.html +++ b/html/bayesnet/classifiers/SPODE.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,24 +70,24 @@ 8 : 9 : namespace bayesnet { 10 : - 11 1686 : SPODE::SPODE(int root) : Classifier(Network()), root(root) {} + 11 562 : SPODE::SPODE(int root) : Classifier(Network()), root(root) {} 12 : - 13 1524 : void SPODE::buildModel(const torch::Tensor& weights) + 13 508 : void SPODE::buildModel(const torch::Tensor& weights) 14 : { 15 : // 0. Add all nodes to the model - 16 1524 : addNodes(); + 16 508 : addNodes(); 17 : // 1. Add edges from the class node to all other nodes 18 : // 2. Add edges from the root node to all other nodes - 19 38520 : for (int i = 0; i < static_cast<int>(features.size()); ++i) { - 20 36996 : model.addEdge(className, features[i]); - 21 36996 : if (i != root) { - 22 35472 : model.addEdge(features[root], features[i]); + 19 12840 : for (int i = 0; i < static_cast<int>(features.size()); ++i) { + 20 12332 : model.addEdge(className, features[i]); + 21 12332 : if (i != root) { + 22 11824 : model.addEdge(features[root], features[i]); 23 : } 24 : } - 25 1524 : } - 26 102 : std::vector<std::string> SPODE::graph(const std::string& name) const + 25 508 : } + 26 34 : std::vector<std::string> SPODE::graph(const std::string& name) const 27 : { - 28 102 : return model.graph(name); + 28 34 : return model.graph(name); 29 : } 30 : 31 : } diff --git a/html/bayesnet/classifiers/SPODE.h.func-c.html b/html/bayesnet/classifiers/SPODE.h.func-c.html index 4b12504..c9ff1d9 100644 --- a/html/bayesnet/classifiers/SPODE.h.func-c.html +++ b/html/bayesnet/classifiers/SPODE.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::SPODE::~SPODE() - 2754 + 918 diff --git a/html/bayesnet/classifiers/SPODE.h.func.html b/html/bayesnet/classifiers/SPODE.h.func.html index 938cc3f..0fab3ab 100644 --- a/html/bayesnet/classifiers/SPODE.h.func.html +++ b/html/bayesnet/classifiers/SPODE.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::SPODE::~SPODE() - 2754 + 918 diff --git a/html/bayesnet/classifiers/SPODE.h.gcov.html b/html/bayesnet/classifiers/SPODE.h.gcov.html index 8197394..31f8d87 100644 --- a/html/bayesnet/classifiers/SPODE.h.gcov.html +++ b/html/bayesnet/classifiers/SPODE.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -78,7 +78,7 @@ 16 : void buildModel(const torch::Tensor& weights) override; 17 : public: 18 : explicit SPODE(int root); - 19 2754 : virtual ~SPODE() = default; + 19 918 : virtual ~SPODE() = default; 20 : std::vector<std::string> graph(const std::string& name = "SPODE") const override; 21 : }; 22 : } diff --git a/html/bayesnet/classifiers/SPODELd.cc.func-c.html b/html/bayesnet/classifiers/SPODELd.cc.func-c.html index a8d929a..cbbb3a7 100644 --- a/html/bayesnet/classifiers/SPODELd.cc.func-c.html +++ b/html/bayesnet/classifiers/SPODELd.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,42 +65,42 @@ bayesnet::SPODELd::fit(at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 12 + 4 bayesnet::SPODELd::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 54 + 18 bayesnet::SPODELd::predict(at::Tensor&) - 204 + 68 bayesnet::SPODELd::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 252 + 84 bayesnet::SPODELd::commonFit(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 258 + 86 bayesnet::SPODELd::SPODELd(int) - 330 + 110 diff --git a/html/bayesnet/classifiers/SPODELd.cc.func.html b/html/bayesnet/classifiers/SPODELd.cc.func.html index f9c1bbe..367a3a8 100644 --- a/html/bayesnet/classifiers/SPODELd.cc.func.html +++ b/html/bayesnet/classifiers/SPODELd.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,42 +65,42 @@ bayesnet::SPODELd::SPODELd(int) - 330 + 110 bayesnet::SPODELd::commonFit(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 258 + 86 bayesnet::SPODELd::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 252 + 84 bayesnet::SPODELd::fit(at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 12 + 4 bayesnet::SPODELd::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 54 + 18 bayesnet::SPODELd::predict(at::Tensor&) - 204 + 68 diff --git a/html/bayesnet/classifiers/SPODELd.cc.gcov.html b/html/bayesnet/classifiers/SPODELd.cc.gcov.html index 3e6880a..c98352a 100644 --- a/html/bayesnet/classifiers/SPODELd.cc.gcov.html +++ b/html/bayesnet/classifiers/SPODELd.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -69,45 +69,45 @@ 7 : #include "SPODELd.h" 8 : 9 : namespace bayesnet { - 10 330 : SPODELd::SPODELd(int root) : SPODE(root), Proposal(dataset, features, className) {} - 11 252 : SPODELd& SPODELd::fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) + 10 110 : SPODELd::SPODELd(int root) : SPODE(root), Proposal(dataset, features, className) {} + 11 84 : SPODELd& SPODELd::fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) 12 : { - 13 252 : checkInput(X_, y_); - 14 252 : Xf = X_; - 15 252 : y = y_; - 16 252 : return commonFit(features_, className_, states_); + 13 84 : checkInput(X_, y_); + 14 84 : Xf = X_; + 15 84 : y = y_; + 16 84 : return commonFit(features_, className_, states_); 17 : } 18 : - 19 12 : SPODELd& SPODELd::fit(torch::Tensor& dataset, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) + 19 4 : SPODELd& SPODELd::fit(torch::Tensor& dataset, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) 20 : { - 21 12 : if (!torch::is_floating_point(dataset)) { - 22 6 : throw std::runtime_error("Dataset must be a floating point tensor"); + 21 4 : if (!torch::is_floating_point(dataset)) { + 22 2 : throw std::runtime_error("Dataset must be a floating point tensor"); 23 : } - 24 24 : Xf = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), "..." }).clone(); - 25 18 : y = dataset.index({ -1, "..." }).clone().to(torch::kInt32); - 26 6 : return commonFit(features_, className_, states_); - 27 18 : } + 24 8 : Xf = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), "..." }).clone(); + 25 6 : y = dataset.index({ -1, "..." }).clone().to(torch::kInt32); + 26 2 : return commonFit(features_, className_, states_); + 27 6 : } 28 : - 29 258 : SPODELd& SPODELd::commonFit(const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) + 29 86 : SPODELd& SPODELd::commonFit(const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) 30 : { - 31 258 : features = features_; - 32 258 : className = className_; + 31 86 : features = features_; + 32 86 : className = className_; 33 : // Fills std::vectors Xv & yv with the data from tensors X_ (discretized) & y - 34 258 : states = fit_local_discretization(y); + 34 86 : states = fit_local_discretization(y); 35 : // We have discretized the input data 36 : // 1st we need to fit the model to build the normal SPODE structure, SPODE::fit initializes the base Bayesian network - 37 258 : SPODE::fit(dataset, features, className, states); - 38 258 : states = localDiscretizationProposal(states, model); - 39 258 : return *this; + 37 86 : SPODE::fit(dataset, features, className, states); + 38 86 : states = localDiscretizationProposal(states, model); + 39 86 : return *this; 40 : } - 41 204 : torch::Tensor SPODELd::predict(torch::Tensor& X) + 41 68 : torch::Tensor SPODELd::predict(torch::Tensor& X) 42 : { - 43 204 : auto Xt = prepareX(X); - 44 408 : return SPODE::predict(Xt); - 45 204 : } - 46 54 : std::vector<std::string> SPODELd::graph(const std::string& name) const + 43 68 : auto Xt = prepareX(X); + 44 136 : return SPODE::predict(Xt); + 45 68 : } + 46 18 : std::vector<std::string> SPODELd::graph(const std::string& name) const 47 : { - 48 54 : return SPODE::graph(name); + 48 18 : return SPODE::graph(name); 49 : } 50 : } diff --git a/html/bayesnet/classifiers/SPODELd.h.func-c.html b/html/bayesnet/classifiers/SPODELd.h.func-c.html index c53596c..f056ad9 100644 --- a/html/bayesnet/classifiers/SPODELd.h.func-c.html +++ b/html/bayesnet/classifiers/SPODELd.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::SPODELd::~SPODELd() - 480 + 160 diff --git a/html/bayesnet/classifiers/SPODELd.h.func.html b/html/bayesnet/classifiers/SPODELd.h.func.html index 56e1380..9090865 100644 --- a/html/bayesnet/classifiers/SPODELd.h.func.html +++ b/html/bayesnet/classifiers/SPODELd.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::SPODELd::~SPODELd() - 480 + 160 diff --git a/html/bayesnet/classifiers/SPODELd.h.gcov.html b/html/bayesnet/classifiers/SPODELd.h.gcov.html index 374d8f2..89bb892 100644 --- a/html/bayesnet/classifiers/SPODELd.h.gcov.html +++ b/html/bayesnet/classifiers/SPODELd.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -75,7 +75,7 @@ 13 : class SPODELd : public SPODE, public Proposal { 14 : public: 15 : explicit SPODELd(int root); - 16 480 : virtual ~SPODELd() = default; + 16 160 : virtual ~SPODELd() = default; 17 : SPODELd& fit(torch::Tensor& X, torch::Tensor& y, const std::vector<std::string>& features, const std::string& className, map<std::string, std::vector<int>>& states) override; 18 : SPODELd& fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, map<std::string, std::vector<int>>& states) override; 19 : SPODELd& commonFit(const std::vector<std::string>& features, const std::string& className, map<std::string, std::vector<int>>& states); diff --git a/html/bayesnet/classifiers/TAN.cc.func-c.html b/html/bayesnet/classifiers/TAN.cc.func-c.html index d5f40ff..38881a0 100644 --- a/html/bayesnet/classifiers/TAN.cc.func-c.html +++ b/html/bayesnet/classifiers/TAN.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::TAN::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 12 + 4 bayesnet::TAN::buildModel(at::Tensor const&) - 78 + 26 bayesnet::TAN::TAN() - 282 + 94 auto bayesnet::TAN::buildModel(at::Tensor const&)::{lambda(auto:1 const&, auto:2 const&)#1}::operator()<std::pair<int, float>, std::pair<int, float> >(std::pair<int, float> const&, std::pair<int, float> const&) const - 972 + 324 diff --git a/html/bayesnet/classifiers/TAN.cc.func.html b/html/bayesnet/classifiers/TAN.cc.func.html index 6be64fd..da81af9 100644 --- a/html/bayesnet/classifiers/TAN.cc.func.html +++ b/html/bayesnet/classifiers/TAN.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ auto bayesnet::TAN::buildModel(at::Tensor const&)::{lambda(auto:1 const&, auto:2 const&)#1}::operator()<std::pair<int, float>, std::pair<int, float> >(std::pair<int, float> const&, std::pair<int, float> const&) const - 972 + 324 bayesnet::TAN::TAN() - 282 + 94 bayesnet::TAN::buildModel(at::Tensor const&) - 78 + 26 bayesnet::TAN::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 12 + 4 diff --git a/html/bayesnet/classifiers/TAN.cc.gcov.html b/html/bayesnet/classifiers/TAN.cc.gcov.html index db66a1f..84d892c 100644 --- a/html/bayesnet/classifiers/TAN.cc.gcov.html +++ b/html/bayesnet/classifiers/TAN.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -69,40 +69,40 @@ 7 : #include "TAN.h" 8 : 9 : namespace bayesnet { - 10 282 : TAN::TAN() : Classifier(Network()) {} + 10 94 : TAN::TAN() : Classifier(Network()) {} 11 : - 12 78 : void TAN::buildModel(const torch::Tensor& weights) + 12 26 : void TAN::buildModel(const torch::Tensor& weights) 13 : { 14 : // 0. Add all nodes to the model - 15 78 : addNodes(); + 15 26 : addNodes(); 16 : // 1. Compute mutual information between each feature and the class and set the root node 17 : // as the highest mutual information with the class - 18 78 : auto mi = std::vector <std::pair<int, float >>(); - 19 234 : torch::Tensor class_dataset = dataset.index({ -1, "..." }); - 20 534 : for (int i = 0; i < static_cast<int>(features.size()); ++i) { - 21 1368 : torch::Tensor feature_dataset = dataset.index({ i, "..." }); - 22 456 : auto mi_value = metrics.mutualInformation(class_dataset, feature_dataset, weights); - 23 456 : mi.push_back({ i, mi_value }); - 24 456 : } - 25 1050 : sort(mi.begin(), mi.end(), [](const auto& left, const auto& right) {return left.second < right.second;}); - 26 78 : auto root = mi[mi.size() - 1].first; + 18 26 : auto mi = std::vector <std::pair<int, float >>(); + 19 78 : torch::Tensor class_dataset = dataset.index({ -1, "..." }); + 20 178 : for (int i = 0; i < static_cast<int>(features.size()); ++i) { + 21 456 : torch::Tensor feature_dataset = dataset.index({ i, "..." }); + 22 152 : auto mi_value = metrics.mutualInformation(class_dataset, feature_dataset, weights); + 23 152 : mi.push_back({ i, mi_value }); + 24 152 : } + 25 350 : sort(mi.begin(), mi.end(), [](const auto& left, const auto& right) {return left.second < right.second;}); + 26 26 : auto root = mi[mi.size() - 1].first; 27 : // 2. Compute mutual information between each feature and the class - 28 78 : auto weights_matrix = metrics.conditionalEdge(weights); + 28 26 : auto weights_matrix = metrics.conditionalEdge(weights); 29 : // 3. Compute the maximum spanning tree - 30 78 : auto mst = metrics.maximumSpanningTree(features, weights_matrix, root); + 30 26 : auto mst = metrics.maximumSpanningTree(features, weights_matrix, root); 31 : // 4. Add edges from the maximum spanning tree to the model - 32 456 : for (auto i = 0; i < mst.size(); ++i) { - 33 378 : auto [from, to] = mst[i]; - 34 378 : model.addEdge(features[from], features[to]); + 32 152 : for (auto i = 0; i < mst.size(); ++i) { + 33 126 : auto [from, to] = mst[i]; + 34 126 : model.addEdge(features[from], features[to]); 35 : } 36 : // 5. Add edges from the class to all features - 37 534 : for (auto feature : features) { - 38 456 : model.addEdge(className, feature); - 39 456 : } - 40 612 : } - 41 12 : std::vector<std::string> TAN::graph(const std::string& title) const + 37 178 : for (auto feature : features) { + 38 152 : model.addEdge(className, feature); + 39 152 : } + 40 204 : } + 41 4 : std::vector<std::string> TAN::graph(const std::string& title) const 42 : { - 43 12 : return model.graph(title); + 43 4 : return model.graph(title); 44 : } 45 : } diff --git a/html/bayesnet/classifiers/TAN.h.func-c.html b/html/bayesnet/classifiers/TAN.h.func-c.html index ce4e4d3..d644491 100644 --- a/html/bayesnet/classifiers/TAN.h.func-c.html +++ b/html/bayesnet/classifiers/TAN.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::TAN::~TAN() - 114 + 38 diff --git a/html/bayesnet/classifiers/TAN.h.func.html b/html/bayesnet/classifiers/TAN.h.func.html index 9fe8d8e..fcc7c76 100644 --- a/html/bayesnet/classifiers/TAN.h.func.html +++ b/html/bayesnet/classifiers/TAN.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::TAN::~TAN() - 114 + 38 diff --git a/html/bayesnet/classifiers/TAN.h.gcov.html b/html/bayesnet/classifiers/TAN.h.gcov.html index 44c18f2..49e8a11 100644 --- a/html/bayesnet/classifiers/TAN.h.gcov.html +++ b/html/bayesnet/classifiers/TAN.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -76,7 +76,7 @@ 14 : void buildModel(const torch::Tensor& weights) override; 15 : public: 16 : TAN(); - 17 114 : virtual ~TAN() = default; + 17 38 : virtual ~TAN() = default; 18 : std::vector<std::string> graph(const std::string& name = "TAN") const override; 19 : }; 20 : } diff --git a/html/bayesnet/classifiers/TANLd.cc.func-c.html b/html/bayesnet/classifiers/TANLd.cc.func-c.html index 7b582d2..32150cd 100644 --- a/html/bayesnet/classifiers/TANLd.cc.func-c.html +++ b/html/bayesnet/classifiers/TANLd.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::TANLd::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::TANLd::predict(at::Tensor&) - 24 + 8 bayesnet::TANLd::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 30 + 10 bayesnet::TANLd::TANLd() - 102 + 34 diff --git a/html/bayesnet/classifiers/TANLd.cc.func.html b/html/bayesnet/classifiers/TANLd.cc.func.html index 8802055..d3a6d76 100644 --- a/html/bayesnet/classifiers/TANLd.cc.func.html +++ b/html/bayesnet/classifiers/TANLd.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::TANLd::TANLd() - 102 + 34 bayesnet::TANLd::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 30 + 10 bayesnet::TANLd::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::TANLd::predict(at::Tensor&) - 24 + 8 diff --git a/html/bayesnet/classifiers/TANLd.cc.gcov.html b/html/bayesnet/classifiers/TANLd.cc.gcov.html index 38e17cd..86dd6ad 100644 --- a/html/bayesnet/classifiers/TANLd.cc.gcov.html +++ b/html/bayesnet/classifiers/TANLd.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -69,31 +69,31 @@ 7 : #include "TANLd.h" 8 : 9 : namespace bayesnet { - 10 102 : TANLd::TANLd() : TAN(), Proposal(dataset, features, className) {} - 11 30 : TANLd& TANLd::fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) + 10 34 : TANLd::TANLd() : TAN(), Proposal(dataset, features, className) {} + 11 10 : TANLd& TANLd::fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) 12 : { - 13 30 : checkInput(X_, y_); - 14 30 : features = features_; - 15 30 : className = className_; - 16 30 : Xf = X_; - 17 30 : y = y_; + 13 10 : checkInput(X_, y_); + 14 10 : features = features_; + 15 10 : className = className_; + 16 10 : Xf = X_; + 17 10 : y = y_; 18 : // Fills std::vectors Xv & yv with the data from tensors X_ (discretized) & y - 19 30 : states = fit_local_discretization(y); + 19 10 : states = fit_local_discretization(y); 20 : // We have discretized the input data 21 : // 1st we need to fit the model to build the normal TAN structure, TAN::fit initializes the base Bayesian network - 22 30 : TAN::fit(dataset, features, className, states); - 23 30 : states = localDiscretizationProposal(states, model); - 24 30 : return *this; + 22 10 : TAN::fit(dataset, features, className, states); + 23 10 : states = localDiscretizationProposal(states, model); + 24 10 : return *this; 25 : 26 : } - 27 24 : torch::Tensor TANLd::predict(torch::Tensor& X) + 27 8 : torch::Tensor TANLd::predict(torch::Tensor& X) 28 : { - 29 24 : auto Xt = prepareX(X); - 30 48 : return TAN::predict(Xt); - 31 24 : } - 32 6 : std::vector<std::string> TANLd::graph(const std::string& name) const + 29 8 : auto Xt = prepareX(X); + 30 16 : return TAN::predict(Xt); + 31 8 : } + 32 2 : std::vector<std::string> TANLd::graph(const std::string& name) const 33 : { - 34 6 : return TAN::graph(name); + 34 2 : return TAN::graph(name); 35 : } 36 : } diff --git a/html/bayesnet/classifiers/TANLd.h.func-c.html b/html/bayesnet/classifiers/TANLd.h.func-c.html index 758edec..51d5365 100644 --- a/html/bayesnet/classifiers/TANLd.h.func-c.html +++ b/html/bayesnet/classifiers/TANLd.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::TANLd::~TANLd() - 30 + 10 diff --git a/html/bayesnet/classifiers/TANLd.h.func.html b/html/bayesnet/classifiers/TANLd.h.func.html index 9b25a6b..ccfa7de 100644 --- a/html/bayesnet/classifiers/TANLd.h.func.html +++ b/html/bayesnet/classifiers/TANLd.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::TANLd::~TANLd() - 30 + 10 diff --git a/html/bayesnet/classifiers/TANLd.h.gcov.html b/html/bayesnet/classifiers/TANLd.h.gcov.html index 3df6d33..0612f1a 100644 --- a/html/bayesnet/classifiers/TANLd.h.gcov.html +++ b/html/bayesnet/classifiers/TANLd.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -76,7 +76,7 @@ 14 : private: 15 : public: 16 : TANLd(); - 17 30 : virtual ~TANLd() = default; + 17 10 : virtual ~TANLd() = default; 18 : TANLd& fit(torch::Tensor& X, torch::Tensor& y, const std::vector<std::string>& features, const std::string& className, map<std::string, std::vector<int>>& states) override; 19 : std::vector<std::string> graph(const std::string& name = "TAN") const override; 20 : torch::Tensor predict(torch::Tensor& X) override; diff --git a/html/bayesnet/classifiers/index-sort-f.html b/html/bayesnet/classifiers/index-sort-f.html index 7e89943..a08b0b4 100644 --- a/html/bayesnet/classifiers/index-sort-f.html +++ b/html/bayesnet/classifiers/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/classifiers/index-sort-l.html b/html/bayesnet/classifiers/index-sort-l.html index 8bd35a4..973b548 100644 --- a/html/bayesnet/classifiers/index-sort-l.html +++ b/html/bayesnet/classifiers/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/classifiers/index.html b/html/bayesnet/classifiers/index.html index df7e8bd..39c1b8f 100644 --- a/html/bayesnet/classifiers/index.html +++ b/html/bayesnet/classifiers/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/ensembles/AODE.cc.func-c.html b/html/bayesnet/ensembles/AODE.cc.func-c.html index 331299c..9861061 100644 --- a/html/bayesnet/ensembles/AODE.cc.func-c.html +++ b/html/bayesnet/ensembles/AODE.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::AODE::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::AODE::setHyperparameters(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) - 6 + 2 bayesnet::AODE::buildModel(at::Tensor const&) - 36 + 12 bayesnet::AODE::AODE(bool) - 114 + 38 diff --git a/html/bayesnet/ensembles/AODE.cc.func.html b/html/bayesnet/ensembles/AODE.cc.func.html index d8abd06..830584d 100644 --- a/html/bayesnet/ensembles/AODE.cc.func.html +++ b/html/bayesnet/ensembles/AODE.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::AODE::AODE(bool) - 114 + 38 bayesnet::AODE::buildModel(at::Tensor const&) - 36 + 12 bayesnet::AODE::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::AODE::setHyperparameters(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) - 6 + 2 diff --git a/html/bayesnet/ensembles/AODE.cc.gcov.html b/html/bayesnet/ensembles/AODE.cc.gcov.html index 4c88a0b..42fd601 100644 --- a/html/bayesnet/ensembles/AODE.cc.gcov.html +++ b/html/bayesnet/ensembles/AODE.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -69,33 +69,33 @@ 7 : #include "AODE.h" 8 : 9 : namespace bayesnet { - 10 114 : AODE::AODE(bool predict_voting) : Ensemble(predict_voting) + 10 38 : AODE::AODE(bool predict_voting) : Ensemble(predict_voting) 11 : { - 12 228 : validHyperparameters = { "predict_voting" }; + 12 76 : validHyperparameters = { "predict_voting" }; 13 : - 14 342 : } - 15 6 : void AODE::setHyperparameters(const nlohmann::json& hyperparameters_) + 14 114 : } + 15 2 : void AODE::setHyperparameters(const nlohmann::json& hyperparameters_) 16 : { - 17 6 : auto hyperparameters = hyperparameters_; - 18 6 : if (hyperparameters.contains("predict_voting")) { - 19 6 : predict_voting = hyperparameters["predict_voting"]; - 20 6 : hyperparameters.erase("predict_voting"); + 17 2 : auto hyperparameters = hyperparameters_; + 18 2 : if (hyperparameters.contains("predict_voting")) { + 19 2 : predict_voting = hyperparameters["predict_voting"]; + 20 2 : hyperparameters.erase("predict_voting"); 21 : } - 22 6 : Classifier::setHyperparameters(hyperparameters); - 23 6 : } - 24 36 : void AODE::buildModel(const torch::Tensor& weights) + 22 2 : Classifier::setHyperparameters(hyperparameters); + 23 2 : } + 24 12 : void AODE::buildModel(const torch::Tensor& weights) 25 : { - 26 36 : models.clear(); - 27 36 : significanceModels.clear(); - 28 282 : for (int i = 0; i < features.size(); ++i) { - 29 246 : models.push_back(std::make_unique<SPODE>(i)); + 26 12 : models.clear(); + 27 12 : significanceModels.clear(); + 28 94 : for (int i = 0; i < features.size(); ++i) { + 29 82 : models.push_back(std::make_unique<SPODE>(i)); 30 : } - 31 36 : n_models = models.size(); - 32 36 : significanceModels = std::vector<double>(n_models, 1.0); - 33 36 : } - 34 6 : std::vector<std::string> AODE::graph(const std::string& title) const + 31 12 : n_models = models.size(); + 32 12 : significanceModels = std::vector<double>(n_models, 1.0); + 33 12 : } + 34 2 : std::vector<std::string> AODE::graph(const std::string& title) const 35 : { - 36 6 : return Ensemble::graph(title); + 36 2 : return Ensemble::graph(title); 37 : } 38 : } diff --git a/html/bayesnet/ensembles/AODE.h.func-c.html b/html/bayesnet/ensembles/AODE.h.func-c.html index 7c7ad97..e0e5598 100644 --- a/html/bayesnet/ensembles/AODE.h.func-c.html +++ b/html/bayesnet/ensembles/AODE.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::AODE::~AODE() - 42 + 14 diff --git a/html/bayesnet/ensembles/AODE.h.func.html b/html/bayesnet/ensembles/AODE.h.func.html index 67f9a5d..8de836d 100644 --- a/html/bayesnet/ensembles/AODE.h.func.html +++ b/html/bayesnet/ensembles/AODE.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::AODE::~AODE() - 42 + 14 diff --git a/html/bayesnet/ensembles/AODE.h.gcov.html b/html/bayesnet/ensembles/AODE.h.gcov.html index 85fdb70..86bcdd8 100644 --- a/html/bayesnet/ensembles/AODE.h.gcov.html +++ b/html/bayesnet/ensembles/AODE.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -74,7 +74,7 @@ 12 : class AODE : public Ensemble { 13 : public: 14 : AODE(bool predict_voting = false); - 15 42 : virtual ~AODE() {}; + 15 14 : virtual ~AODE() {}; 16 : void setHyperparameters(const nlohmann::json& hyperparameters) override; 17 : std::vector<std::string> graph(const std::string& title = "AODE") const override; 18 : protected: diff --git a/html/bayesnet/ensembles/AODELd.cc.func-c.html b/html/bayesnet/ensembles/AODELd.cc.func-c.html index 7d662a5..8e9b118 100644 --- a/html/bayesnet/ensembles/AODELd.cc.func-c.html +++ b/html/bayesnet/ensembles/AODELd.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,35 +65,35 @@ bayesnet::AODELd::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::AODELd::buildModel(at::Tensor const&) - 30 + 10 bayesnet::AODELd::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 30 + 10 bayesnet::AODELd::trainModel(at::Tensor const&) - 30 + 10 bayesnet::AODELd::AODELd(bool) - 102 + 34 diff --git a/html/bayesnet/ensembles/AODELd.cc.func.html b/html/bayesnet/ensembles/AODELd.cc.func.html index edc64f1..3ebad49 100644 --- a/html/bayesnet/ensembles/AODELd.cc.func.html +++ b/html/bayesnet/ensembles/AODELd.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,35 +65,35 @@ bayesnet::AODELd::AODELd(bool) - 102 + 34 bayesnet::AODELd::buildModel(at::Tensor const&) - 30 + 10 bayesnet::AODELd::fit(at::Tensor&, at::Tensor&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<int, std::allocator<int> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::vector<int, std::allocator<int> > > > >&) - 30 + 10 bayesnet::AODELd::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::AODELd::trainModel(at::Tensor const&) - 30 + 10 diff --git a/html/bayesnet/ensembles/AODELd.cc.gcov.html b/html/bayesnet/ensembles/AODELd.cc.gcov.html index 086f2d9..3c7834e 100644 --- a/html/bayesnet/ensembles/AODELd.cc.gcov.html +++ b/html/bayesnet/ensembles/AODELd.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -69,42 +69,42 @@ 7 : #include "AODELd.h" 8 : 9 : namespace bayesnet { - 10 102 : AODELd::AODELd(bool predict_voting) : Ensemble(predict_voting), Proposal(dataset, features, className) + 10 34 : AODELd::AODELd(bool predict_voting) : Ensemble(predict_voting), Proposal(dataset, features, className) 11 : { - 12 102 : } - 13 30 : AODELd& AODELd::fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) + 12 34 : } + 13 10 : AODELd& AODELd::fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) 14 : { - 15 30 : checkInput(X_, y_); - 16 30 : features = features_; - 17 30 : className = className_; - 18 30 : Xf = X_; - 19 30 : y = y_; + 15 10 : checkInput(X_, y_); + 16 10 : features = features_; + 17 10 : className = className_; + 18 10 : Xf = X_; + 19 10 : y = y_; 20 : // Fills std::vectors Xv & yv with the data from tensors X_ (discretized) & y - 21 30 : states = fit_local_discretization(y); + 21 10 : states = fit_local_discretization(y); 22 : // We have discretized the input data 23 : // 1st we need to fit the model to build the normal TAN structure, TAN::fit initializes the base Bayesian network - 24 30 : Ensemble::fit(dataset, features, className, states); - 25 30 : return *this; + 24 10 : Ensemble::fit(dataset, features, className, states); + 25 10 : return *this; 26 : 27 : } - 28 30 : void AODELd::buildModel(const torch::Tensor& weights) + 28 10 : void AODELd::buildModel(const torch::Tensor& weights) 29 : { - 30 30 : models.clear(); - 31 252 : for (int i = 0; i < features.size(); ++i) { - 32 222 : models.push_back(std::make_unique<SPODELd>(i)); + 30 10 : models.clear(); + 31 84 : for (int i = 0; i < features.size(); ++i) { + 32 74 : models.push_back(std::make_unique<SPODELd>(i)); 33 : } - 34 30 : n_models = models.size(); - 35 30 : significanceModels = std::vector<double>(n_models, 1.0); - 36 30 : } - 37 30 : void AODELd::trainModel(const torch::Tensor& weights) + 34 10 : n_models = models.size(); + 35 10 : significanceModels = std::vector<double>(n_models, 1.0); + 36 10 : } + 37 10 : void AODELd::trainModel(const torch::Tensor& weights) 38 : { - 39 252 : for (const auto& model : models) { - 40 222 : model->fit(Xf, y, features, className, states); + 39 84 : for (const auto& model : models) { + 40 74 : model->fit(Xf, y, features, className, states); 41 : } - 42 30 : } - 43 6 : std::vector<std::string> AODELd::graph(const std::string& name) const + 42 10 : } + 43 2 : std::vector<std::string> AODELd::graph(const std::string& name) const 44 : { - 45 6 : return Ensemble::graph(name); + 45 2 : return Ensemble::graph(name); 46 : } 47 : } diff --git a/html/bayesnet/ensembles/AODELd.h.func-c.html b/html/bayesnet/ensembles/AODELd.h.func-c.html index 1a18cb1..0c9b50b 100644 --- a/html/bayesnet/ensembles/AODELd.h.func-c.html +++ b/html/bayesnet/ensembles/AODELd.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::AODELd::~AODELd() - 30 + 10 diff --git a/html/bayesnet/ensembles/AODELd.h.func.html b/html/bayesnet/ensembles/AODELd.h.func.html index 0e16adf..4349a9f 100644 --- a/html/bayesnet/ensembles/AODELd.h.func.html +++ b/html/bayesnet/ensembles/AODELd.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::AODELd::~AODELd() - 30 + 10 diff --git a/html/bayesnet/ensembles/AODELd.h.gcov.html b/html/bayesnet/ensembles/AODELd.h.gcov.html index ac086cf..715814e 100644 --- a/html/bayesnet/ensembles/AODELd.h.gcov.html +++ b/html/bayesnet/ensembles/AODELd.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -76,7 +76,7 @@ 14 : class AODELd : public Ensemble, public Proposal { 15 : public: 16 : AODELd(bool predict_voting = true); - 17 30 : virtual ~AODELd() = default; + 17 10 : virtual ~AODELd() = default; 18 : AODELd& fit(torch::Tensor& X_, torch::Tensor& y_, const std::vector<std::string>& features_, const std::string& className_, map<std::string, std::vector<int>>& states_) override; 19 : std::vector<std::string> graph(const std::string& name = "AODELd") const override; 20 : protected: diff --git a/html/bayesnet/ensembles/BoostAODE.cc.func-c.html b/html/bayesnet/ensembles/BoostAODE.cc.func-c.html index 842a417..ae48b4a 100644 --- a/html/bayesnet/ensembles/BoostAODE.cc.func-c.html +++ b/html/bayesnet/ensembles/BoostAODE.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,63 +65,63 @@ bayesnet::BoostAODE::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::BoostAODE::update_weights_block(int, at::Tensor&, at::Tensor&) - 42 + 14 bayesnet::BoostAODE::initializeModels() - 48 + 16 bayesnet::BoostAODE::setHyperparameters(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) - 132 + 44 bayesnet::BoostAODE::buildModel(at::Tensor const&) - 138 + 46 bayesnet::BoostAODE::trainModel(at::Tensor const&) - 138 + 46 bayesnet::BoostAODE::BoostAODE(bool) - 252 + 84 bayesnet::update_weights(at::Tensor&, at::Tensor&, at::Tensor&) - 816 + 272 auto bayesnet::BoostAODE::trainModel(at::Tensor const&)::{lambda(auto:1)#1}::operator()<int>(int) const - 14550 + 4850 diff --git a/html/bayesnet/ensembles/BoostAODE.cc.func.html b/html/bayesnet/ensembles/BoostAODE.cc.func.html index dc86eba..c449231 100644 --- a/html/bayesnet/ensembles/BoostAODE.cc.func.html +++ b/html/bayesnet/ensembles/BoostAODE.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,63 +65,63 @@ auto bayesnet::BoostAODE::trainModel(at::Tensor const&)::{lambda(auto:1)#1}::operator()<int>(int) const - 14550 + 4850 bayesnet::BoostAODE::BoostAODE(bool) - 252 + 84 bayesnet::BoostAODE::buildModel(at::Tensor const&) - 138 + 46 bayesnet::BoostAODE::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 6 + 2 bayesnet::BoostAODE::initializeModels() - 48 + 16 bayesnet::BoostAODE::setHyperparameters(nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> const&) - 132 + 44 bayesnet::BoostAODE::trainModel(at::Tensor const&) - 138 + 46 bayesnet::BoostAODE::update_weights_block(int, at::Tensor&, at::Tensor&) - 42 + 14 bayesnet::update_weights(at::Tensor&, at::Tensor&, at::Tensor&) - 816 + 272 diff --git a/html/bayesnet/ensembles/BoostAODE.cc.gcov.html b/html/bayesnet/ensembles/BoostAODE.cc.gcov.html index 92f401e..73d7274 100644 --- a/html/bayesnet/ensembles/BoostAODE.cc.gcov.html +++ b/html/bayesnet/ensembles/BoostAODE.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -79,126 +79,126 @@ 17 : 18 : namespace bayesnet { 19 : - 20 252 : BoostAODE::BoostAODE(bool predict_voting) : Ensemble(predict_voting) + 20 84 : BoostAODE::BoostAODE(bool predict_voting) : Ensemble(predict_voting) 21 : { - 22 2772 : validHyperparameters = { + 22 924 : validHyperparameters = { 23 : "maxModels", "bisection", "order", "convergence", "convergence_best", "threshold", 24 : "select_features", "maxTolerance", "predict_voting", "block_update" - 25 2772 : }; + 25 924 : }; 26 : - 27 756 : } - 28 138 : void BoostAODE::buildModel(const torch::Tensor& weights) + 27 252 : } + 28 46 : void BoostAODE::buildModel(const torch::Tensor& weights) 29 : { 30 : // Models shall be built in trainModel - 31 138 : models.clear(); - 32 138 : significanceModels.clear(); - 33 138 : n_models = 0; + 31 46 : models.clear(); + 32 46 : significanceModels.clear(); + 33 46 : n_models = 0; 34 : // Prepare the validation dataset - 35 414 : auto y_ = dataset.index({ -1, "..." }); - 36 138 : if (convergence) { + 35 138 : auto y_ = dataset.index({ -1, "..." }); + 36 46 : if (convergence) { 37 : // Prepare train & validation sets from train data - 38 114 : auto fold = folding::StratifiedKFold(5, y_, 271); - 39 114 : auto [train, test] = fold.getFold(0); - 40 114 : auto train_t = torch::tensor(train); - 41 114 : auto test_t = torch::tensor(test); + 38 38 : auto fold = folding::StratifiedKFold(5, y_, 271); + 39 38 : auto [train, test] = fold.getFold(0); + 40 38 : auto train_t = torch::tensor(train); + 41 38 : auto test_t = torch::tensor(test); 42 : // Get train and validation sets - 43 570 : X_train = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), train_t }); - 44 342 : y_train = dataset.index({ -1, train_t }); - 45 570 : X_test = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), test_t }); - 46 342 : y_test = dataset.index({ -1, test_t }); - 47 114 : dataset = X_train; - 48 114 : m = X_train.size(1); - 49 114 : auto n_classes = states.at(className).size(); + 43 190 : X_train = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), train_t }); + 44 114 : y_train = dataset.index({ -1, train_t }); + 45 190 : X_test = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), test_t }); + 46 114 : y_test = dataset.index({ -1, test_t }); + 47 38 : dataset = X_train; + 48 38 : m = X_train.size(1); + 49 38 : auto n_classes = states.at(className).size(); 50 : // Build dataset with train data - 51 114 : buildDataset(y_train); - 52 114 : metrics = Metrics(dataset, features, className, n_classes); - 53 114 : } else { + 51 38 : buildDataset(y_train); + 52 38 : metrics = Metrics(dataset, features, className, n_classes); + 53 38 : } else { 54 : // Use all data to train - 55 96 : X_train = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), "..." }); - 56 24 : y_train = y_; + 55 32 : X_train = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), "..." }); + 56 8 : y_train = y_; 57 : } - 58 1350 : } - 59 132 : void BoostAODE::setHyperparameters(const nlohmann::json& hyperparameters_) + 58 450 : } + 59 44 : void BoostAODE::setHyperparameters(const nlohmann::json& hyperparameters_) 60 : { - 61 132 : auto hyperparameters = hyperparameters_; - 62 132 : if (hyperparameters.contains("order")) { - 63 150 : std::vector<std::string> algos = { Orders.ASC, Orders.DESC, Orders.RAND }; - 64 30 : order_algorithm = hyperparameters["order"]; - 65 30 : if (std::find(algos.begin(), algos.end(), order_algorithm) == algos.end()) { - 66 6 : throw std::invalid_argument("Invalid order algorithm, valid values [" + Orders.ASC + ", " + Orders.DESC + ", " + Orders.RAND + "]"); + 61 44 : auto hyperparameters = hyperparameters_; + 62 44 : if (hyperparameters.contains("order")) { + 63 50 : std::vector<std::string> algos = { Orders.ASC, Orders.DESC, Orders.RAND }; + 64 10 : order_algorithm = hyperparameters["order"]; + 65 10 : if (std::find(algos.begin(), algos.end(), order_algorithm) == algos.end()) { + 66 2 : throw std::invalid_argument("Invalid order algorithm, valid values [" + Orders.ASC + ", " + Orders.DESC + ", " + Orders.RAND + "]"); 67 : } - 68 24 : hyperparameters.erase("order"); - 69 30 : } - 70 126 : if (hyperparameters.contains("convergence")) { - 71 54 : convergence = hyperparameters["convergence"]; - 72 54 : hyperparameters.erase("convergence"); + 68 8 : hyperparameters.erase("order"); + 69 10 : } + 70 42 : if (hyperparameters.contains("convergence")) { + 71 18 : convergence = hyperparameters["convergence"]; + 72 18 : hyperparameters.erase("convergence"); 73 : } - 74 126 : if (hyperparameters.contains("convergence_best")) { - 75 18 : convergence_best = hyperparameters["convergence_best"]; - 76 18 : hyperparameters.erase("convergence_best"); + 74 42 : if (hyperparameters.contains("convergence_best")) { + 75 6 : convergence_best = hyperparameters["convergence_best"]; + 76 6 : hyperparameters.erase("convergence_best"); 77 : } - 78 126 : if (hyperparameters.contains("bisection")) { - 79 48 : bisection = hyperparameters["bisection"]; - 80 48 : hyperparameters.erase("bisection"); + 78 42 : if (hyperparameters.contains("bisection")) { + 79 16 : bisection = hyperparameters["bisection"]; + 80 16 : hyperparameters.erase("bisection"); 81 : } - 82 126 : if (hyperparameters.contains("threshold")) { - 83 36 : threshold = hyperparameters["threshold"]; - 84 36 : hyperparameters.erase("threshold"); + 82 42 : if (hyperparameters.contains("threshold")) { + 83 12 : threshold = hyperparameters["threshold"]; + 84 12 : hyperparameters.erase("threshold"); 85 : } - 86 126 : if (hyperparameters.contains("maxTolerance")) { - 87 66 : maxTolerance = hyperparameters["maxTolerance"]; - 88 66 : if (maxTolerance < 1 || maxTolerance > 4) - 89 18 : throw std::invalid_argument("Invalid maxTolerance value, must be greater in [1, 4]"); - 90 48 : hyperparameters.erase("maxTolerance"); + 86 42 : if (hyperparameters.contains("maxTolerance")) { + 87 22 : maxTolerance = hyperparameters["maxTolerance"]; + 88 22 : if (maxTolerance < 1 || maxTolerance > 4) + 89 6 : throw std::invalid_argument("Invalid maxTolerance value, must be greater in [1, 4]"); + 90 16 : hyperparameters.erase("maxTolerance"); 91 : } - 92 108 : if (hyperparameters.contains("predict_voting")) { - 93 6 : predict_voting = hyperparameters["predict_voting"]; - 94 6 : hyperparameters.erase("predict_voting"); + 92 36 : if (hyperparameters.contains("predict_voting")) { + 93 2 : predict_voting = hyperparameters["predict_voting"]; + 94 2 : hyperparameters.erase("predict_voting"); 95 : } - 96 108 : if (hyperparameters.contains("select_features")) { - 97 54 : auto selectedAlgorithm = hyperparameters["select_features"]; - 98 270 : std::vector<std::string> algos = { SelectFeatures.IWSS, SelectFeatures.CFS, SelectFeatures.FCBF }; - 99 54 : selectFeatures = true; - 100 54 : select_features_algorithm = selectedAlgorithm; - 101 54 : if (std::find(algos.begin(), algos.end(), selectedAlgorithm) == algos.end()) { - 102 6 : throw std::invalid_argument("Invalid selectFeatures value, valid values [" + SelectFeatures.IWSS + ", " + SelectFeatures.CFS + ", " + SelectFeatures.FCBF + "]"); + 96 36 : if (hyperparameters.contains("select_features")) { + 97 18 : auto selectedAlgorithm = hyperparameters["select_features"]; + 98 90 : std::vector<std::string> algos = { SelectFeatures.IWSS, SelectFeatures.CFS, SelectFeatures.FCBF }; + 99 18 : selectFeatures = true; + 100 18 : select_features_algorithm = selectedAlgorithm; + 101 18 : if (std::find(algos.begin(), algos.end(), selectedAlgorithm) == algos.end()) { + 102 2 : throw std::invalid_argument("Invalid selectFeatures value, valid values [" + SelectFeatures.IWSS + ", " + SelectFeatures.CFS + ", " + SelectFeatures.FCBF + "]"); 103 : } - 104 48 : hyperparameters.erase("select_features"); - 105 60 : } - 106 102 : if (hyperparameters.contains("block_update")) { - 107 12 : block_update = hyperparameters["block_update"]; - 108 12 : hyperparameters.erase("block_update"); + 104 16 : hyperparameters.erase("select_features"); + 105 20 : } + 106 34 : if (hyperparameters.contains("block_update")) { + 107 4 : block_update = hyperparameters["block_update"]; + 108 4 : hyperparameters.erase("block_update"); 109 : } - 110 102 : Classifier::setHyperparameters(hyperparameters); - 111 216 : } - 112 816 : std::tuple<torch::Tensor&, double, bool> update_weights(torch::Tensor& ytrain, torch::Tensor& ypred, torch::Tensor& weights) + 110 34 : Classifier::setHyperparameters(hyperparameters); + 111 72 : } + 112 272 : std::tuple<torch::Tensor&, double, bool> update_weights(torch::Tensor& ytrain, torch::Tensor& ypred, torch::Tensor& weights) 113 : { - 114 816 : bool terminate = false; - 115 816 : double alpha_t = 0; - 116 816 : auto mask_wrong = ypred != ytrain; - 117 816 : auto mask_right = ypred == ytrain; - 118 816 : auto masked_weights = weights * mask_wrong.to(weights.dtype()); - 119 816 : double epsilon_t = masked_weights.sum().item<double>(); - 120 816 : if (epsilon_t > 0.5) { + 114 272 : bool terminate = false; + 115 272 : double alpha_t = 0; + 116 272 : auto mask_wrong = ypred != ytrain; + 117 272 : auto mask_right = ypred == ytrain; + 118 272 : auto masked_weights = weights * mask_wrong.to(weights.dtype()); + 119 272 : double epsilon_t = masked_weights.sum().item<double>(); + 120 272 : if (epsilon_t > 0.5) { 121 : // Inverse the weights policy (plot ln(wt)) 122 : // "In each round of AdaBoost, there is a sanity check to ensure that the current base 123 : // learner is better than random guess" (Zhi-Hua Zhou, 2012) - 124 24 : terminate = true; + 124 8 : terminate = true; 125 : } else { - 126 792 : double wt = (1 - epsilon_t) / epsilon_t; - 127 792 : alpha_t = epsilon_t == 0 ? 1 : 0.5 * log(wt); + 126 264 : double wt = (1 - epsilon_t) / epsilon_t; + 127 264 : alpha_t = epsilon_t == 0 ? 1 : 0.5 * log(wt); 128 : // Step 3.2: Update weights for next classifier 129 : // Step 3.2.1: Update weights of wrong samples - 130 792 : weights += mask_wrong.to(weights.dtype()) * exp(alpha_t) * weights; + 130 264 : weights += mask_wrong.to(weights.dtype()) * exp(alpha_t) * weights; 131 : // Step 3.2.2: Update weights of right samples - 132 792 : weights += mask_right.to(weights.dtype()) * exp(-alpha_t) * weights; + 132 264 : weights += mask_right.to(weights.dtype()) * exp(-alpha_t) * weights; 133 : // Step 3.3: Normalise the weights - 134 792 : double totalWeights = torch::sum(weights).item<double>(); - 135 792 : weights = weights / totalWeights; + 134 264 : double totalWeights = torch::sum(weights).item<double>(); + 135 264 : weights = weights / totalWeights; 136 : } - 137 1632 : return { weights, alpha_t, terminate }; - 138 816 : } - 139 42 : std::tuple<torch::Tensor&, double, bool> BoostAODE::update_weights_block(int k, torch::Tensor& ytrain, torch::Tensor& weights) + 137 544 : return { weights, alpha_t, terminate }; + 138 272 : } + 139 14 : std::tuple<torch::Tensor&, double, bool> BoostAODE::update_weights_block(int k, torch::Tensor& ytrain, torch::Tensor& weights) 140 : { 141 : /* Update Block algorithm 142 : k = # of models in block @@ -242,218 +242,218 @@ 180 : // 181 : // Make predict with only the last k models 182 : // - 183 42 : std::unique_ptr<Classifier> model; - 184 42 : std::vector<std::unique_ptr<Classifier>> models_bak; + 183 14 : std::unique_ptr<Classifier> model; + 184 14 : std::vector<std::unique_ptr<Classifier>> models_bak; 185 : // 1. n_models_bak <- n_models 2. significances_bak <- significances - 186 42 : auto significance_bak = significanceModels; - 187 42 : auto n_models_bak = n_models; + 186 14 : auto significance_bak = significanceModels; + 187 14 : auto n_models_bak = n_models; 188 : // 3. significances = vector(k, 1) - 189 42 : significanceModels = std::vector<double>(k, 1.0); + 189 14 : significanceModels = std::vector<double>(k, 1.0); 190 : // 4. Move first n classifiers to models_bak 191 : // backup the first n_models - k models (if n_models == k, don't backup any) - 192 222 : for (int i = 0; i < n_models - k; ++i) { - 193 180 : model = std::move(models[0]); - 194 180 : models.erase(models.begin()); - 195 180 : models_bak.push_back(std::move(model)); + 192 74 : for (int i = 0; i < n_models - k; ++i) { + 193 60 : model = std::move(models[0]); + 194 60 : models.erase(models.begin()); + 195 60 : models_bak.push_back(std::move(model)); 196 : } - 197 42 : assert(models.size() == k); + 197 14 : assert(models.size() == k); 198 : // 5. n_models <- k - 199 42 : n_models = k; + 199 14 : n_models = k; 200 : // 6. Make prediction, compute alpha, update weights - 201 42 : auto ypred = predict(X_train); + 201 14 : auto ypred = predict(X_train); 202 : // 203 : // Update weights 204 : // 205 : double alpha_t; 206 : bool terminate; - 207 42 : std::tie(weights, alpha_t, terminate) = update_weights(y_train, ypred, weights); + 207 14 : std::tie(weights, alpha_t, terminate) = update_weights(y_train, ypred, weights); 208 : // 209 : // Restore the models if needed 210 : // 211 : // 7. Insert classifiers in models_bak to be the first n models 212 : // if n_models_bak == k, don't restore any, because none of them were moved - 213 42 : if (k != n_models_bak) { + 213 14 : if (k != n_models_bak) { 214 : // Insert in the same order as they were extracted - 215 36 : int bak_size = models_bak.size(); - 216 216 : for (int i = 0; i < bak_size; ++i) { - 217 180 : model = std::move(models_bak[bak_size - 1 - i]); - 218 180 : models_bak.erase(models_bak.end() - 1); - 219 180 : models.insert(models.begin(), std::move(model)); + 215 12 : int bak_size = models_bak.size(); + 216 72 : for (int i = 0; i < bak_size; ++i) { + 217 60 : model = std::move(models_bak[bak_size - 1 - i]); + 218 60 : models_bak.erase(models_bak.end() - 1); + 219 60 : models.insert(models.begin(), std::move(model)); 220 : } 221 : } 222 : // 8. significances <- significances_bak - 223 42 : significanceModels = significance_bak; + 223 14 : significanceModels = significance_bak; 224 : // 225 : // Update the significance of the last k models 226 : // 227 : // 9. Update last k significances - 228 156 : for (int i = 0; i < k; ++i) { - 229 114 : significanceModels[n_models_bak - k + i] = alpha_t; + 228 52 : for (int i = 0; i < k; ++i) { + 229 38 : significanceModels[n_models_bak - k + i] = alpha_t; 230 : } 231 : // 10. n_models <- n_models_bak - 232 42 : n_models = n_models_bak; - 233 84 : return { weights, alpha_t, terminate }; - 234 42 : } - 235 48 : std::vector<int> BoostAODE::initializeModels() + 232 14 : n_models = n_models_bak; + 233 28 : return { weights, alpha_t, terminate }; + 234 14 : } + 235 16 : std::vector<int> BoostAODE::initializeModels() 236 : { - 237 48 : std::vector<int> featuresUsed; - 238 48 : torch::Tensor weights_ = torch::full({ m }, 1.0 / m, torch::kFloat64); - 239 48 : int maxFeatures = 0; - 240 48 : if (select_features_algorithm == SelectFeatures.CFS) { - 241 12 : featureSelector = new CFS(dataset, features, className, maxFeatures, states.at(className).size(), weights_); - 242 36 : } else if (select_features_algorithm == SelectFeatures.IWSS) { - 243 18 : if (threshold < 0 || threshold >0.5) { - 244 12 : throw std::invalid_argument("Invalid threshold value for " + SelectFeatures.IWSS + " [0, 0.5]"); + 237 16 : std::vector<int> featuresUsed; + 238 16 : torch::Tensor weights_ = torch::full({ m }, 1.0 / m, torch::kFloat64); + 239 16 : int maxFeatures = 0; + 240 16 : if (select_features_algorithm == SelectFeatures.CFS) { + 241 4 : featureSelector = new CFS(dataset, features, className, maxFeatures, states.at(className).size(), weights_); + 242 12 : } else if (select_features_algorithm == SelectFeatures.IWSS) { + 243 6 : if (threshold < 0 || threshold >0.5) { + 244 4 : throw std::invalid_argument("Invalid threshold value for " + SelectFeatures.IWSS + " [0, 0.5]"); 245 : } - 246 6 : featureSelector = new IWSS(dataset, features, className, maxFeatures, states.at(className).size(), weights_, threshold); - 247 18 : } else if (select_features_algorithm == SelectFeatures.FCBF) { - 248 18 : if (threshold < 1e-7 || threshold > 1) { - 249 12 : throw std::invalid_argument("Invalid threshold value for " + SelectFeatures.FCBF + " [1e-7, 1]"); + 246 2 : featureSelector = new IWSS(dataset, features, className, maxFeatures, states.at(className).size(), weights_, threshold); + 247 6 : } else if (select_features_algorithm == SelectFeatures.FCBF) { + 248 6 : if (threshold < 1e-7 || threshold > 1) { + 249 4 : throw std::invalid_argument("Invalid threshold value for " + SelectFeatures.FCBF + " [1e-7, 1]"); 250 : } - 251 6 : featureSelector = new FCBF(dataset, features, className, maxFeatures, states.at(className).size(), weights_, threshold); + 251 2 : featureSelector = new FCBF(dataset, features, className, maxFeatures, states.at(className).size(), weights_, threshold); 252 : } - 253 24 : featureSelector->fit(); - 254 24 : auto cfsFeatures = featureSelector->getFeatures(); - 255 24 : auto scores = featureSelector->getScores(); - 256 150 : for (const int& feature : cfsFeatures) { - 257 126 : featuresUsed.push_back(feature); - 258 126 : std::unique_ptr<Classifier> model = std::make_unique<SPODE>(feature); - 259 126 : model->fit(dataset, features, className, states, weights_); - 260 126 : models.push_back(std::move(model)); - 261 126 : significanceModels.push_back(1.0); // They will be updated later in trainModel - 262 126 : n_models++; - 263 126 : } - 264 24 : notes.push_back("Used features in initialization: " + std::to_string(featuresUsed.size()) + " of " + std::to_string(features.size()) + " with " + select_features_algorithm); - 265 24 : delete featureSelector; - 266 48 : return featuresUsed; - 267 72 : } - 268 138 : void BoostAODE::trainModel(const torch::Tensor& weights) + 253 8 : featureSelector->fit(); + 254 8 : auto cfsFeatures = featureSelector->getFeatures(); + 255 8 : auto scores = featureSelector->getScores(); + 256 50 : for (const int& feature : cfsFeatures) { + 257 42 : featuresUsed.push_back(feature); + 258 42 : std::unique_ptr<Classifier> model = std::make_unique<SPODE>(feature); + 259 42 : model->fit(dataset, features, className, states, weights_); + 260 42 : models.push_back(std::move(model)); + 261 42 : significanceModels.push_back(1.0); // They will be updated later in trainModel + 262 42 : n_models++; + 263 42 : } + 264 8 : notes.push_back("Used features in initialization: " + std::to_string(featuresUsed.size()) + " of " + std::to_string(features.size()) + " with " + select_features_algorithm); + 265 8 : delete featureSelector; + 266 16 : return featuresUsed; + 267 24 : } + 268 46 : void BoostAODE::trainModel(const torch::Tensor& weights) 269 : { 270 : // 271 : // Logging setup 272 : // - 273 138 : loguru::set_thread_name("BoostAODE"); - 274 138 : loguru::g_stderr_verbosity = loguru::Verbosity_OFF; - 275 138 : loguru::add_file("boostAODE.log", loguru::Truncate, loguru::Verbosity_MAX); + 273 46 : loguru::set_thread_name("BoostAODE"); + 274 46 : loguru::g_stderr_verbosity = loguru::Verbosity_OFF; + 275 46 : loguru::add_file("boostAODE.log", loguru::Truncate, loguru::Verbosity_MAX); 276 : 277 : // Algorithm based on the adaboost algorithm for classification 278 : // as explained in Ensemble methods (Zhi-Hua Zhou, 2012) - 279 138 : fitted = true; - 280 138 : double alpha_t = 0; - 281 138 : torch::Tensor weights_ = torch::full({ m }, 1.0 / m, torch::kFloat64); - 282 138 : bool finished = false; - 283 138 : std::vector<int> featuresUsed; - 284 138 : if (selectFeatures) { - 285 48 : featuresUsed = initializeModels(); - 286 24 : auto ypred = predict(X_train); - 287 24 : std::tie(weights_, alpha_t, finished) = update_weights(y_train, ypred, weights_); + 279 46 : fitted = true; + 280 46 : double alpha_t = 0; + 281 46 : torch::Tensor weights_ = torch::full({ m }, 1.0 / m, torch::kFloat64); + 282 46 : bool finished = false; + 283 46 : std::vector<int> featuresUsed; + 284 46 : if (selectFeatures) { + 285 16 : featuresUsed = initializeModels(); + 286 8 : auto ypred = predict(X_train); + 287 8 : std::tie(weights_, alpha_t, finished) = update_weights(y_train, ypred, weights_); 288 : // Update significance of the models - 289 150 : for (int i = 0; i < n_models; ++i) { - 290 126 : significanceModels[i] = alpha_t; + 289 50 : for (int i = 0; i < n_models; ++i) { + 290 42 : significanceModels[i] = alpha_t; 291 : } - 292 24 : if (finished) { + 292 8 : if (finished) { 293 0 : return; 294 : } - 295 24 : } - 296 114 : int numItemsPack = 0; // The counter of the models inserted in the current pack + 295 8 : } + 296 38 : int numItemsPack = 0; // The counter of the models inserted in the current pack 297 : // Variables to control the accuracy finish condition - 298 114 : double priorAccuracy = 0.0; - 299 114 : double improvement = 1.0; - 300 114 : double convergence_threshold = 1e-4; - 301 114 : int tolerance = 0; // number of times the accuracy is lower than the convergence_threshold + 298 38 : double priorAccuracy = 0.0; + 299 38 : double improvement = 1.0; + 300 38 : double convergence_threshold = 1e-4; + 301 38 : int tolerance = 0; // number of times the accuracy is lower than the convergence_threshold 302 : // Step 0: Set the finish condition 303 : // epsilon sub t > 0.5 => inverse the weights policy 304 : // validation error is not decreasing 305 : // run out of features - 306 114 : bool ascending = order_algorithm == Orders.ASC; - 307 114 : std::mt19937 g{ 173 }; - 308 756 : while (!finished) { + 306 38 : bool ascending = order_algorithm == Orders.ASC; + 307 38 : std::mt19937 g{ 173 }; + 308 252 : while (!finished) { 309 : // Step 1: Build ranking with mutual information - 310 642 : auto featureSelection = metrics.SelectKBestWeighted(weights_, ascending, n); // Get all the features sorted - 311 642 : if (order_algorithm == Orders.RAND) { - 312 54 : std::shuffle(featureSelection.begin(), featureSelection.end(), g); + 310 214 : auto featureSelection = metrics.SelectKBestWeighted(weights_, ascending, n); // Get all the features sorted + 311 214 : if (order_algorithm == Orders.RAND) { + 312 18 : std::shuffle(featureSelection.begin(), featureSelection.end(), g); 313 : } 314 : // Remove used features - 315 1284 : featureSelection.erase(remove_if(begin(featureSelection), end(featureSelection), [&](auto x) - 316 58200 : { return std::find(begin(featuresUsed), end(featuresUsed), x) != end(featuresUsed);}), - 317 642 : end(featureSelection) + 315 428 : featureSelection.erase(remove_if(begin(featureSelection), end(featureSelection), [&](auto x) + 316 19400 : { return std::find(begin(featuresUsed), end(featuresUsed), x) != end(featuresUsed);}), + 317 214 : end(featureSelection) 318 : ); - 319 642 : int k = bisection ? pow(2, tolerance) : 1; - 320 642 : int counter = 0; // The model counter of the current pack - 321 642 : VLOG_SCOPE_F(1, "counter=%d k=%d featureSelection.size: %zu", counter, k, featureSelection.size()); - 322 1506 : while (counter++ < k && featureSelection.size() > 0) { - 323 864 : auto feature = featureSelection[0]; - 324 864 : featureSelection.erase(featureSelection.begin()); - 325 864 : std::unique_ptr<Classifier> model; - 326 864 : model = std::make_unique<SPODE>(feature); - 327 864 : model->fit(dataset, features, className, states, weights_); - 328 864 : alpha_t = 0.0; - 329 864 : if (!block_update) { - 330 750 : auto ypred = model->predict(X_train); + 319 214 : int k = bisection ? pow(2, tolerance) : 1; + 320 214 : int counter = 0; // The model counter of the current pack + 321 214 : VLOG_SCOPE_F(1, "counter=%d k=%d featureSelection.size: %zu", counter, k, featureSelection.size()); + 322 502 : while (counter++ < k && featureSelection.size() > 0) { + 323 288 : auto feature = featureSelection[0]; + 324 288 : featureSelection.erase(featureSelection.begin()); + 325 288 : std::unique_ptr<Classifier> model; + 326 288 : model = std::make_unique<SPODE>(feature); + 327 288 : model->fit(dataset, features, className, states, weights_); + 328 288 : alpha_t = 0.0; + 329 288 : if (!block_update) { + 330 250 : auto ypred = model->predict(X_train); 331 : // Step 3.1: Compute the classifier amout of say - 332 750 : std::tie(weights_, alpha_t, finished) = update_weights(y_train, ypred, weights_); - 333 750 : } + 332 250 : std::tie(weights_, alpha_t, finished) = update_weights(y_train, ypred, weights_); + 333 250 : } 334 : // Step 3.4: Store classifier and its accuracy to weigh its future vote - 335 864 : numItemsPack++; - 336 864 : featuresUsed.push_back(feature); - 337 864 : models.push_back(std::move(model)); - 338 864 : significanceModels.push_back(alpha_t); - 339 864 : n_models++; - 340 864 : VLOG_SCOPE_F(2, "numItemsPack: %d n_models: %d featuresUsed: %zu", numItemsPack, n_models, featuresUsed.size()); - 341 864 : } - 342 642 : if (block_update) { - 343 42 : std::tie(weights_, alpha_t, finished) = update_weights_block(k, y_train, weights_); + 335 288 : numItemsPack++; + 336 288 : featuresUsed.push_back(feature); + 337 288 : models.push_back(std::move(model)); + 338 288 : significanceModels.push_back(alpha_t); + 339 288 : n_models++; + 340 288 : VLOG_SCOPE_F(2, "numItemsPack: %d n_models: %d featuresUsed: %zu", numItemsPack, n_models, featuresUsed.size()); + 341 288 : } + 342 214 : if (block_update) { + 343 14 : std::tie(weights_, alpha_t, finished) = update_weights_block(k, y_train, weights_); 344 : } - 345 642 : if (convergence && !finished) { - 346 444 : auto y_val_predict = predict(X_test); - 347 444 : double accuracy = (y_val_predict == y_test).sum().item<double>() / (double)y_test.size(0); - 348 444 : if (priorAccuracy == 0) { - 349 90 : priorAccuracy = accuracy; + 345 214 : if (convergence && !finished) { + 346 148 : auto y_val_predict = predict(X_test); + 347 148 : double accuracy = (y_val_predict == y_test).sum().item<double>() / (double)y_test.size(0); + 348 148 : if (priorAccuracy == 0) { + 349 30 : priorAccuracy = accuracy; 350 : } else { - 351 354 : improvement = accuracy - priorAccuracy; + 351 118 : improvement = accuracy - priorAccuracy; 352 : } - 353 444 : if (improvement < convergence_threshold) { - 354 264 : VLOG_SCOPE_F(3, " (improvement<threshold) tolerance: %d numItemsPack: %d improvement: %f prior: %f current: %f", tolerance, numItemsPack, improvement, priorAccuracy, accuracy); - 355 264 : tolerance++; - 356 264 : } else { - 357 180 : VLOG_SCOPE_F(3, "* (improvement>=threshold) Reset. tolerance: %d numItemsPack: %d improvement: %f prior: %f current: %f", tolerance, numItemsPack, improvement, priorAccuracy, accuracy); - 358 180 : tolerance = 0; // Reset the counter if the model performs better - 359 180 : numItemsPack = 0; - 360 180 : } - 361 444 : if (convergence_best) { + 353 148 : if (improvement < convergence_threshold) { + 354 88 : VLOG_SCOPE_F(3, " (improvement<threshold) tolerance: %d numItemsPack: %d improvement: %f prior: %f current: %f", tolerance, numItemsPack, improvement, priorAccuracy, accuracy); + 355 88 : tolerance++; + 356 88 : } else { + 357 60 : VLOG_SCOPE_F(3, "* (improvement>=threshold) Reset. tolerance: %d numItemsPack: %d improvement: %f prior: %f current: %f", tolerance, numItemsPack, improvement, priorAccuracy, accuracy); + 358 60 : tolerance = 0; // Reset the counter if the model performs better + 359 60 : numItemsPack = 0; + 360 60 : } + 361 148 : if (convergence_best) { 362 : // Keep the best accuracy until now as the prior accuracy - 363 48 : priorAccuracy = std::max(accuracy, priorAccuracy); + 363 16 : priorAccuracy = std::max(accuracy, priorAccuracy); 364 : } else { 365 : // Keep the last accuray obtained as the prior accuracy - 366 396 : priorAccuracy = accuracy; + 366 132 : priorAccuracy = accuracy; 367 : } - 368 444 : } - 369 642 : VLOG_SCOPE_F(1, "tolerance: %d featuresUsed.size: %zu features.size: %zu", tolerance, featuresUsed.size(), features.size()); - 370 642 : finished = finished || tolerance > maxTolerance || featuresUsed.size() == features.size(); - 371 642 : } - 372 114 : if (tolerance > maxTolerance) { - 373 12 : if (numItemsPack < n_models) { - 374 12 : notes.push_back("Convergence threshold reached & " + std::to_string(numItemsPack) + " models eliminated"); - 375 12 : VLOG_SCOPE_F(4, "Convergence threshold reached & %d models eliminated of %d", numItemsPack, n_models); - 376 156 : for (int i = 0; i < numItemsPack; ++i) { - 377 144 : significanceModels.pop_back(); - 378 144 : models.pop_back(); - 379 144 : n_models--; + 368 148 : } + 369 214 : VLOG_SCOPE_F(1, "tolerance: %d featuresUsed.size: %zu features.size: %zu", tolerance, featuresUsed.size(), features.size()); + 370 214 : finished = finished || tolerance > maxTolerance || featuresUsed.size() == features.size(); + 371 214 : } + 372 38 : if (tolerance > maxTolerance) { + 373 4 : if (numItemsPack < n_models) { + 374 4 : notes.push_back("Convergence threshold reached & " + std::to_string(numItemsPack) + " models eliminated"); + 375 4 : VLOG_SCOPE_F(4, "Convergence threshold reached & %d models eliminated of %d", numItemsPack, n_models); + 376 52 : for (int i = 0; i < numItemsPack; ++i) { + 377 48 : significanceModels.pop_back(); + 378 48 : models.pop_back(); + 379 48 : n_models--; 380 : } - 381 12 : } else { + 381 4 : } else { 382 0 : notes.push_back("Convergence threshold reached & 0 models eliminated"); 383 0 : VLOG_SCOPE_F(4, "Convergence threshold reached & 0 models eliminated n_models=%d numItemsPack=%d", n_models, numItemsPack); 384 0 : } 385 : } - 386 114 : if (featuresUsed.size() != features.size()) { - 387 6 : notes.push_back("Used features in train: " + std::to_string(featuresUsed.size()) + " of " + std::to_string(features.size())); - 388 6 : status = WARNING; + 386 38 : if (featuresUsed.size() != features.size()) { + 387 2 : notes.push_back("Used features in train: " + std::to_string(featuresUsed.size()) + " of " + std::to_string(features.size())); + 388 2 : status = WARNING; 389 : } - 390 114 : notes.push_back("Number of models: " + std::to_string(n_models)); - 391 162 : } - 392 6 : std::vector<std::string> BoostAODE::graph(const std::string& title) const + 390 38 : notes.push_back("Number of models: " + std::to_string(n_models)); + 391 54 : } + 392 2 : std::vector<std::string> BoostAODE::graph(const std::string& title) const 393 : { - 394 6 : return Ensemble::graph(title); + 394 2 : return Ensemble::graph(title); 395 : } 396 : } diff --git a/html/bayesnet/ensembles/BoostAODE.h.func-c.html b/html/bayesnet/ensembles/BoostAODE.h.func-c.html index 6e01432..5a4360d 100644 --- a/html/bayesnet/ensembles/BoostAODE.h.func-c.html +++ b/html/bayesnet/ensembles/BoostAODE.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::BoostAODE::~BoostAODE() - 132 + 44 diff --git a/html/bayesnet/ensembles/BoostAODE.h.func.html b/html/bayesnet/ensembles/BoostAODE.h.func.html index 0d68fd8..9fecf46 100644 --- a/html/bayesnet/ensembles/BoostAODE.h.func.html +++ b/html/bayesnet/ensembles/BoostAODE.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::BoostAODE::~BoostAODE() - 132 + 44 diff --git a/html/bayesnet/ensembles/BoostAODE.h.gcov.html b/html/bayesnet/ensembles/BoostAODE.h.gcov.html index d3076ce..18d0951 100644 --- a/html/bayesnet/ensembles/BoostAODE.h.gcov.html +++ b/html/bayesnet/ensembles/BoostAODE.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -86,7 +86,7 @@ 24 : class BoostAODE : public Ensemble { 25 : public: 26 : explicit BoostAODE(bool predict_voting = false); - 27 132 : virtual ~BoostAODE() = default; + 27 44 : virtual ~BoostAODE() = default; 28 : std::vector<std::string> graph(const std::string& title = "BoostAODE") const override; 29 : void setHyperparameters(const nlohmann::json& hyperparameters_) override; 30 : protected: diff --git a/html/bayesnet/ensembles/Ensemble.cc.func-c.html b/html/bayesnet/ensembles/Ensemble.cc.func-c.html index 1601831..a74772e 100644 --- a/html/bayesnet/ensembles/Ensemble.cc.func-c.html +++ b/html/bayesnet/ensembles/Ensemble.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,175 +65,175 @@ bayesnet::Ensemble::getNumberOfStates() const - 6 + 2 bayesnet::Ensemble::show[abi:cxx11]() const - 6 + 2 bayesnet::Ensemble::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 18 + 6 bayesnet::Ensemble::getNumberOfEdges() const - 36 + 12 bayesnet::Ensemble::getNumberOfNodes() const - 36 + 12 bayesnet::Ensemble::trainModel(at::Tensor const&) - 36 + 12 bayesnet::Ensemble::predict_average_voting(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 42 + 14 bayesnet::Ensemble::predict_average_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 54 + 18 bayesnet::Ensemble::score(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<int, std::allocator<int> >&) - 60 + 20 bayesnet::Ensemble::compute_arg_max(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&) - 66 + 22 bayesnet::Ensemble::predict(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 84 + 28 bayesnet::Ensemble::score(at::Tensor&, at::Tensor&) - 120 + 40 bayesnet::Ensemble::predict_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 132 + 44 bayesnet::Ensemble::predict_average_voting(at::Tensor&) - 240 + 80 bayesnet::Ensemble::voting(at::Tensor&) - 240 + 80 bayesnet::Ensemble::predict_average_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&)::{lambda()#1}::operator()() const - 366 + 122 bayesnet::Ensemble::predict_average_proba(at::Tensor&) - 444 + 148 bayesnet::Ensemble::Ensemble(bool) - 468 + 156 bayesnet::Ensemble::compute_arg_max(at::Tensor&) - 636 + 212 bayesnet::Ensemble::predict(at::Tensor&) - 654 + 218 bayesnet::Ensemble::predict_proba(at::Tensor&) - 678 + 226 bayesnet::Ensemble::predict_average_voting(at::Tensor&)::{lambda()#1}::operator()() const - 1608 + 536 bayesnet::Ensemble::predict_average_proba(at::Tensor&)::{lambda()#1}::operator()() const - 2202 + 734 bayesnet::Ensemble::predict_average_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&)::{lambda(double)#1}::operator()(double) const - 49320 + 16440 bayesnet::Ensemble::predict_average_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&)::{lambda()#1}::operator()() const::{lambda(double, double)#1}::operator()(double, double) const - 389880 + 129960 diff --git a/html/bayesnet/ensembles/Ensemble.cc.func.html b/html/bayesnet/ensembles/Ensemble.cc.func.html index 2aaba50..681dbd5 100644 --- a/html/bayesnet/ensembles/Ensemble.cc.func.html +++ b/html/bayesnet/ensembles/Ensemble.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,175 +65,175 @@ bayesnet::Ensemble::Ensemble(bool) - 468 + 156 bayesnet::Ensemble::compute_arg_max(at::Tensor&) - 636 + 212 bayesnet::Ensemble::compute_arg_max(std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&) - 66 + 22 bayesnet::Ensemble::getNumberOfEdges() const - 36 + 12 bayesnet::Ensemble::getNumberOfNodes() const - 36 + 12 bayesnet::Ensemble::getNumberOfStates() const - 6 + 2 bayesnet::Ensemble::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const - 18 + 6 bayesnet::Ensemble::predict(at::Tensor&) - 654 + 218 bayesnet::Ensemble::predict(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 84 + 28 bayesnet::Ensemble::predict_average_proba(at::Tensor&) - 444 + 148 bayesnet::Ensemble::predict_average_proba(at::Tensor&)::{lambda()#1}::operator()() const - 2202 + 734 bayesnet::Ensemble::predict_average_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 54 + 18 bayesnet::Ensemble::predict_average_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&)::{lambda()#1}::operator()() const - 366 + 122 bayesnet::Ensemble::predict_average_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&)::{lambda()#1}::operator()() const::{lambda(double, double)#1}::operator()(double, double) const - 389880 + 129960 bayesnet::Ensemble::predict_average_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&)::{lambda(double)#1}::operator()(double) const - 49320 + 16440 bayesnet::Ensemble::predict_average_voting(at::Tensor&) - 240 + 80 bayesnet::Ensemble::predict_average_voting(at::Tensor&)::{lambda()#1}::operator()() const - 1608 + 536 bayesnet::Ensemble::predict_average_voting(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 42 + 14 bayesnet::Ensemble::predict_proba(at::Tensor&) - 678 + 226 bayesnet::Ensemble::predict_proba(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&) - 132 + 44 bayesnet::Ensemble::score(at::Tensor&, at::Tensor&) - 120 + 40 bayesnet::Ensemble::score(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<int, std::allocator<int> >&) - 60 + 20 bayesnet::Ensemble::show[abi:cxx11]() const - 6 + 2 bayesnet::Ensemble::trainModel(at::Tensor const&) - 36 + 12 bayesnet::Ensemble::voting(at::Tensor&) - 240 + 80 diff --git a/html/bayesnet/ensembles/Ensemble.cc.gcov.html b/html/bayesnet/ensembles/Ensemble.cc.gcov.html index 43af0ae..bf6079a 100644 --- a/html/bayesnet/ensembles/Ensemble.cc.gcov.html +++ b/html/bayesnet/ensembles/Ensemble.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,216 +70,216 @@ 8 : 9 : namespace bayesnet { 10 : - 11 468 : Ensemble::Ensemble(bool predict_voting) : Classifier(Network()), n_models(0), predict_voting(predict_voting) + 11 156 : Ensemble::Ensemble(bool predict_voting) : Classifier(Network()), n_models(0), predict_voting(predict_voting) 12 : { 13 : - 14 468 : }; + 14 156 : }; 15 : const std::string ENSEMBLE_NOT_FITTED = "Ensemble has not been fitted"; - 16 36 : void Ensemble::trainModel(const torch::Tensor& weights) + 16 12 : void Ensemble::trainModel(const torch::Tensor& weights) 17 : { - 18 36 : n_models = models.size(); - 19 282 : for (auto i = 0; i < n_models; ++i) { + 18 12 : n_models = models.size(); + 19 94 : for (auto i = 0; i < n_models; ++i) { 20 : // fit with std::vectors - 21 246 : models[i]->fit(dataset, features, className, states); + 21 82 : models[i]->fit(dataset, features, className, states); 22 : } - 23 36 : } - 24 66 : std::vector<int> Ensemble::compute_arg_max(std::vector<std::vector<double>>& X) + 23 12 : } + 24 22 : std::vector<int> Ensemble::compute_arg_max(std::vector<std::vector<double>>& X) 25 : { - 26 66 : std::vector<int> y_pred; - 27 14730 : for (auto i = 0; i < X.size(); ++i) { - 28 14664 : auto max = std::max_element(X[i].begin(), X[i].end()); - 29 29328 : y_pred.push_back(std::distance(X[i].begin(), max)); + 26 22 : std::vector<int> y_pred; + 27 4910 : for (auto i = 0; i < X.size(); ++i) { + 28 4888 : auto max = std::max_element(X[i].begin(), X[i].end()); + 29 9776 : y_pred.push_back(std::distance(X[i].begin(), max)); 30 : } - 31 66 : return y_pred; + 31 22 : return y_pred; 32 0 : } - 33 636 : torch::Tensor Ensemble::compute_arg_max(torch::Tensor& X) + 33 212 : torch::Tensor Ensemble::compute_arg_max(torch::Tensor& X) 34 : { - 35 636 : auto y_pred = torch::argmax(X, 1); - 36 636 : return y_pred; + 35 212 : auto y_pred = torch::argmax(X, 1); + 36 212 : return y_pred; 37 : } - 38 240 : torch::Tensor Ensemble::voting(torch::Tensor& votes) + 38 80 : torch::Tensor Ensemble::voting(torch::Tensor& votes) 39 : { 40 : // Convert m x n_models tensor to a m x n_class_states with voting probabilities - 41 240 : auto y_pred_ = votes.accessor<int, 2>(); - 42 240 : std::vector<int> y_pred_final; - 43 240 : int numClasses = states.at(className).size(); + 41 80 : auto y_pred_ = votes.accessor<int, 2>(); + 42 80 : std::vector<int> y_pred_final; + 43 80 : int numClasses = states.at(className).size(); 44 : // votes is m x n_models with the prediction of every model for each sample - 45 240 : auto result = torch::zeros({ votes.size(0), numClasses }, torch::kFloat32); - 46 240 : auto sum = std::reduce(significanceModels.begin(), significanceModels.end()); - 47 61836 : for (int i = 0; i < votes.size(0); ++i) { + 45 80 : auto result = torch::zeros({ votes.size(0), numClasses }, torch::kFloat32); + 46 80 : auto sum = std::reduce(significanceModels.begin(), significanceModels.end()); + 47 20612 : for (int i = 0; i < votes.size(0); ++i) { 48 : // n_votes store in each index (value of class) the significance added by each model 49 : // i.e. n_votes[0] contains how much value has the value 0 of class. That value is generated by the models predictions - 50 61596 : std::vector<double> n_votes(numClasses, 0.0); - 51 515400 : for (int j = 0; j < n_models; ++j) { - 52 453804 : n_votes[y_pred_[i][j]] += significanceModels.at(j); + 50 20532 : std::vector<double> n_votes(numClasses, 0.0); + 51 171800 : for (int j = 0; j < n_models; ++j) { + 52 151268 : n_votes[y_pred_[i][j]] += significanceModels.at(j); 53 : } - 54 61596 : result[i] = torch::tensor(n_votes); - 55 61596 : } + 54 20532 : result[i] = torch::tensor(n_votes); + 55 20532 : } 56 : // To only do one division and gain precision - 57 240 : result /= sum; - 58 480 : return result; - 59 240 : } - 60 132 : std::vector<std::vector<double>> Ensemble::predict_proba(std::vector<std::vector<int>>& X) + 57 80 : result /= sum; + 58 160 : return result; + 59 80 : } + 60 44 : std::vector<std::vector<double>> Ensemble::predict_proba(std::vector<std::vector<int>>& X) 61 : { - 62 132 : if (!fitted) { - 63 36 : throw std::logic_error(ENSEMBLE_NOT_FITTED); + 62 44 : if (!fitted) { + 63 12 : throw std::logic_error(ENSEMBLE_NOT_FITTED); 64 : } - 65 96 : return predict_voting ? predict_average_voting(X) : predict_average_proba(X); + 65 32 : return predict_voting ? predict_average_voting(X) : predict_average_proba(X); 66 : } - 67 678 : torch::Tensor Ensemble::predict_proba(torch::Tensor& X) + 67 226 : torch::Tensor Ensemble::predict_proba(torch::Tensor& X) 68 : { - 69 678 : if (!fitted) { - 70 36 : throw std::logic_error(ENSEMBLE_NOT_FITTED); + 69 226 : if (!fitted) { + 70 12 : throw std::logic_error(ENSEMBLE_NOT_FITTED); 71 : } - 72 642 : return predict_voting ? predict_average_voting(X) : predict_average_proba(X); + 72 214 : return predict_voting ? predict_average_voting(X) : predict_average_proba(X); 73 : } - 74 84 : std::vector<int> Ensemble::predict(std::vector<std::vector<int>>& X) + 74 28 : std::vector<int> Ensemble::predict(std::vector<std::vector<int>>& X) 75 : { - 76 84 : auto res = predict_proba(X); - 77 120 : return compute_arg_max(res); - 78 60 : } - 79 654 : torch::Tensor Ensemble::predict(torch::Tensor& X) + 76 28 : auto res = predict_proba(X); + 77 40 : return compute_arg_max(res); + 78 20 : } + 79 218 : torch::Tensor Ensemble::predict(torch::Tensor& X) 80 : { - 81 654 : auto res = predict_proba(X); - 82 1260 : return compute_arg_max(res); - 83 630 : } - 84 444 : torch::Tensor Ensemble::predict_average_proba(torch::Tensor& X) + 81 218 : auto res = predict_proba(X); + 82 420 : return compute_arg_max(res); + 83 210 : } + 84 148 : torch::Tensor Ensemble::predict_average_proba(torch::Tensor& X) 85 : { - 86 444 : auto n_states = models[0]->getClassNumStates(); - 87 444 : torch::Tensor y_pred = torch::zeros({ X.size(1), n_states }, torch::kFloat32); - 88 444 : auto threads{ std::vector<std::thread>() }; - 89 444 : std::mutex mtx; - 90 2646 : for (auto i = 0; i < n_models; ++i) { - 91 2202 : threads.push_back(std::thread([&, i]() { - 92 2202 : auto ypredict = models[i]->predict_proba(X); - 93 2202 : std::lock_guard<std::mutex> lock(mtx); - 94 2202 : y_pred += ypredict * significanceModels[i]; - 95 2202 : })); + 86 148 : auto n_states = models[0]->getClassNumStates(); + 87 148 : torch::Tensor y_pred = torch::zeros({ X.size(1), n_states }, torch::kFloat32); + 88 148 : auto threads{ std::vector<std::thread>() }; + 89 148 : std::mutex mtx; + 90 882 : for (auto i = 0; i < n_models; ++i) { + 91 734 : threads.push_back(std::thread([&, i]() { + 92 734 : auto ypredict = models[i]->predict_proba(X); + 93 734 : std::lock_guard<std::mutex> lock(mtx); + 94 734 : y_pred += ypredict * significanceModels[i]; + 95 734 : })); 96 : } - 97 2646 : for (auto& thread : threads) { - 98 2202 : thread.join(); + 97 882 : for (auto& thread : threads) { + 98 734 : thread.join(); 99 : } - 100 444 : auto sum = std::reduce(significanceModels.begin(), significanceModels.end()); - 101 444 : y_pred /= sum; - 102 888 : return y_pred; - 103 444 : } - 104 54 : std::vector<std::vector<double>> Ensemble::predict_average_proba(std::vector<std::vector<int>>& X) + 100 148 : auto sum = std::reduce(significanceModels.begin(), significanceModels.end()); + 101 148 : y_pred /= sum; + 102 296 : return y_pred; + 103 148 : } + 104 18 : std::vector<std::vector<double>> Ensemble::predict_average_proba(std::vector<std::vector<int>>& X) 105 : { - 106 54 : auto n_states = models[0]->getClassNumStates(); - 107 54 : std::vector<std::vector<double>> y_pred(X[0].size(), std::vector<double>(n_states, 0.0)); - 108 54 : auto threads{ std::vector<std::thread>() }; - 109 54 : std::mutex mtx; - 110 420 : for (auto i = 0; i < n_models; ++i) { - 111 366 : threads.push_back(std::thread([&, i]() { - 112 366 : auto ypredict = models[i]->predict_proba(X); - 113 366 : assert(ypredict.size() == y_pred.size()); - 114 366 : assert(ypredict[0].size() == y_pred[0].size()); - 115 366 : std::lock_guard<std::mutex> lock(mtx); + 106 18 : auto n_states = models[0]->getClassNumStates(); + 107 18 : std::vector<std::vector<double>> y_pred(X[0].size(), std::vector<double>(n_states, 0.0)); + 108 18 : auto threads{ std::vector<std::thread>() }; + 109 18 : std::mutex mtx; + 110 140 : for (auto i = 0; i < n_models; ++i) { + 111 122 : threads.push_back(std::thread([&, i]() { + 112 122 : auto ypredict = models[i]->predict_proba(X); + 113 122 : assert(ypredict.size() == y_pred.size()); + 114 122 : assert(ypredict[0].size() == y_pred[0].size()); + 115 122 : std::lock_guard<std::mutex> lock(mtx); 116 : // Multiply each prediction by the significance of the model and then add it to the final prediction - 117 72546 : for (auto j = 0; j < ypredict.size(); ++j) { - 118 72180 : std::transform(y_pred[j].begin(), y_pred[j].end(), ypredict[j].begin(), y_pred[j].begin(), - 119 462060 : [significanceModels = significanceModels[i]](double x, double y) { return x + y * significanceModels; }); + 117 24182 : for (auto j = 0; j < ypredict.size(); ++j) { + 118 24060 : std::transform(y_pred[j].begin(), y_pred[j].end(), ypredict[j].begin(), y_pred[j].begin(), + 119 154020 : [significanceModels = significanceModels[i]](double x, double y) { return x + y * significanceModels; }); 120 : } - 121 366 : })); + 121 122 : })); 122 : } - 123 420 : for (auto& thread : threads) { - 124 366 : thread.join(); + 123 140 : for (auto& thread : threads) { + 124 122 : thread.join(); 125 : } - 126 54 : auto sum = std::reduce(significanceModels.begin(), significanceModels.end()); + 126 18 : auto sum = std::reduce(significanceModels.begin(), significanceModels.end()); 127 : //Divide each element of the prediction by the sum of the significances - 128 10074 : for (auto j = 0; j < y_pred.size(); ++j) { - 129 59340 : std::transform(y_pred[j].begin(), y_pred[j].end(), y_pred[j].begin(), [sum](double x) { return x / sum; }); + 128 3358 : for (auto j = 0; j < y_pred.size(); ++j) { + 129 19780 : std::transform(y_pred[j].begin(), y_pred[j].end(), y_pred[j].begin(), [sum](double x) { return x / sum; }); 130 : } - 131 108 : return y_pred; - 132 54 : } - 133 42 : std::vector<std::vector<double>> Ensemble::predict_average_voting(std::vector<std::vector<int>>& X) + 131 36 : return y_pred; + 132 18 : } + 133 14 : std::vector<std::vector<double>> Ensemble::predict_average_voting(std::vector<std::vector<int>>& X) 134 : { - 135 42 : torch::Tensor Xt = bayesnet::vectorToTensor(X, false); - 136 42 : auto y_pred = predict_average_voting(Xt); - 137 42 : std::vector<std::vector<double>> result = tensorToVectorDouble(y_pred); - 138 84 : return result; - 139 42 : } - 140 240 : torch::Tensor Ensemble::predict_average_voting(torch::Tensor& X) + 135 14 : torch::Tensor Xt = bayesnet::vectorToTensor(X, false); + 136 14 : auto y_pred = predict_average_voting(Xt); + 137 14 : std::vector<std::vector<double>> result = tensorToVectorDouble(y_pred); + 138 28 : return result; + 139 14 : } + 140 80 : torch::Tensor Ensemble::predict_average_voting(torch::Tensor& X) 141 : { 142 : // Build a m x n_models tensor with the predictions of each model - 143 240 : torch::Tensor y_pred = torch::zeros({ X.size(1), n_models }, torch::kInt32); - 144 240 : auto threads{ std::vector<std::thread>() }; - 145 240 : std::mutex mtx; - 146 1848 : for (auto i = 0; i < n_models; ++i) { - 147 1608 : threads.push_back(std::thread([&, i]() { - 148 1608 : auto ypredict = models[i]->predict(X); - 149 1608 : std::lock_guard<std::mutex> lock(mtx); - 150 4824 : y_pred.index_put_({ "...", i }, ypredict); - 151 3216 : })); + 143 80 : torch::Tensor y_pred = torch::zeros({ X.size(1), n_models }, torch::kInt32); + 144 80 : auto threads{ std::vector<std::thread>() }; + 145 80 : std::mutex mtx; + 146 616 : for (auto i = 0; i < n_models; ++i) { + 147 536 : threads.push_back(std::thread([&, i]() { + 148 536 : auto ypredict = models[i]->predict(X); + 149 536 : std::lock_guard<std::mutex> lock(mtx); + 150 1608 : y_pred.index_put_({ "...", i }, ypredict); + 151 1072 : })); 152 : } - 153 1848 : for (auto& thread : threads) { - 154 1608 : thread.join(); + 153 616 : for (auto& thread : threads) { + 154 536 : thread.join(); 155 : } - 156 480 : return voting(y_pred); - 157 240 : } - 158 120 : float Ensemble::score(torch::Tensor& X, torch::Tensor& y) + 156 160 : return voting(y_pred); + 157 80 : } + 158 40 : float Ensemble::score(torch::Tensor& X, torch::Tensor& y) 159 : { - 160 120 : auto y_pred = predict(X); - 161 108 : int correct = 0; - 162 33876 : for (int i = 0; i < y_pred.size(0); ++i) { - 163 33768 : if (y_pred[i].item<int>() == y[i].item<int>()) { - 164 29502 : correct++; + 160 40 : auto y_pred = predict(X); + 161 36 : int correct = 0; + 162 11292 : for (int i = 0; i < y_pred.size(0); ++i) { + 163 11256 : if (y_pred[i].item<int>() == y[i].item<int>()) { + 164 9834 : correct++; 165 : } 166 : } - 167 216 : return (double)correct / y_pred.size(0); - 168 108 : } - 169 60 : float Ensemble::score(std::vector<std::vector<int>>& X, std::vector<int>& y) + 167 72 : return (double)correct / y_pred.size(0); + 168 36 : } + 169 20 : float Ensemble::score(std::vector<std::vector<int>>& X, std::vector<int>& y) 170 : { - 171 60 : auto y_pred = predict(X); - 172 48 : int correct = 0; - 173 12876 : for (int i = 0; i < y_pred.size(); ++i) { - 174 12828 : if (y_pred[i] == y[i]) { - 175 10722 : correct++; + 171 20 : auto y_pred = predict(X); + 172 16 : int correct = 0; + 173 4292 : for (int i = 0; i < y_pred.size(); ++i) { + 174 4276 : if (y_pred[i] == y[i]) { + 175 3574 : correct++; 176 : } 177 : } - 178 96 : return (double)correct / y_pred.size(); - 179 48 : } - 180 6 : std::vector<std::string> Ensemble::show() const + 178 32 : return (double)correct / y_pred.size(); + 179 16 : } + 180 2 : std::vector<std::string> Ensemble::show() const 181 : { - 182 6 : auto result = std::vector<std::string>(); - 183 30 : for (auto i = 0; i < n_models; ++i) { - 184 24 : auto res = models[i]->show(); - 185 24 : result.insert(result.end(), res.begin(), res.end()); - 186 24 : } - 187 6 : return result; + 182 2 : auto result = std::vector<std::string>(); + 183 10 : for (auto i = 0; i < n_models; ++i) { + 184 8 : auto res = models[i]->show(); + 185 8 : result.insert(result.end(), res.begin(), res.end()); + 186 8 : } + 187 2 : return result; 188 0 : } - 189 18 : std::vector<std::string> Ensemble::graph(const std::string& title) const + 189 6 : std::vector<std::string> Ensemble::graph(const std::string& title) const 190 : { - 191 18 : auto result = std::vector<std::string>(); - 192 120 : for (auto i = 0; i < n_models; ++i) { - 193 102 : auto res = models[i]->graph(title + "_" + std::to_string(i)); - 194 102 : result.insert(result.end(), res.begin(), res.end()); - 195 102 : } - 196 18 : return result; + 191 6 : auto result = std::vector<std::string>(); + 192 40 : for (auto i = 0; i < n_models; ++i) { + 193 34 : auto res = models[i]->graph(title + "_" + std::to_string(i)); + 194 34 : result.insert(result.end(), res.begin(), res.end()); + 195 34 : } + 196 6 : return result; 197 0 : } - 198 36 : int Ensemble::getNumberOfNodes() const + 198 12 : int Ensemble::getNumberOfNodes() const 199 : { - 200 36 : int nodes = 0; - 201 300 : for (auto i = 0; i < n_models; ++i) { - 202 264 : nodes += models[i]->getNumberOfNodes(); + 200 12 : int nodes = 0; + 201 100 : for (auto i = 0; i < n_models; ++i) { + 202 88 : nodes += models[i]->getNumberOfNodes(); 203 : } - 204 36 : return nodes; + 204 12 : return nodes; 205 : } - 206 36 : int Ensemble::getNumberOfEdges() const + 206 12 : int Ensemble::getNumberOfEdges() const 207 : { - 208 36 : int edges = 0; - 209 300 : for (auto i = 0; i < n_models; ++i) { - 210 264 : edges += models[i]->getNumberOfEdges(); + 208 12 : int edges = 0; + 209 100 : for (auto i = 0; i < n_models; ++i) { + 210 88 : edges += models[i]->getNumberOfEdges(); 211 : } - 212 36 : return edges; + 212 12 : return edges; 213 : } - 214 6 : int Ensemble::getNumberOfStates() const + 214 2 : int Ensemble::getNumberOfStates() const 215 : { - 216 6 : int nstates = 0; - 217 30 : for (auto i = 0; i < n_models; ++i) { - 218 24 : nstates += models[i]->getNumberOfStates(); + 216 2 : int nstates = 0; + 217 10 : for (auto i = 0; i < n_models; ++i) { + 218 8 : nstates += models[i]->getNumberOfStates(); 219 : } - 220 6 : return nstates; + 220 2 : return nstates; 221 : } 222 : } diff --git a/html/bayesnet/ensembles/Ensemble.h.func-c.html b/html/bayesnet/ensembles/Ensemble.h.func-c.html index 130e61a..53b176a 100644 --- a/html/bayesnet/ensembles/Ensemble.h.func-c.html +++ b/html/bayesnet/ensembles/Ensemble.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,21 +65,21 @@ bayesnet::Ensemble::dump_cpt[abi:cxx11]() const - 12 + 4 bayesnet::Ensemble::topological_order[abi:cxx11]() - 18 + 6 bayesnet::Ensemble::~Ensemble() - 168 + 56 diff --git a/html/bayesnet/ensembles/Ensemble.h.func.html b/html/bayesnet/ensembles/Ensemble.h.func.html index 8caed4b..370920f 100644 --- a/html/bayesnet/ensembles/Ensemble.h.func.html +++ b/html/bayesnet/ensembles/Ensemble.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,21 +65,21 @@ bayesnet::Ensemble::dump_cpt[abi:cxx11]() const - 12 + 4 bayesnet::Ensemble::topological_order[abi:cxx11]() - 18 + 6 bayesnet::Ensemble::~Ensemble() - 168 + 56 diff --git a/html/bayesnet/ensembles/Ensemble.h.gcov.html b/html/bayesnet/ensembles/Ensemble.h.gcov.html index 6fc30f8..dea3d01 100644 --- a/html/bayesnet/ensembles/Ensemble.h.gcov.html +++ b/html/bayesnet/ensembles/Ensemble.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -77,7 +77,7 @@ 15 : class Ensemble : public Classifier { 16 : public: 17 : Ensemble(bool predict_voting = true); - 18 168 : virtual ~Ensemble() = default; + 18 56 : virtual ~Ensemble() = default; 19 : torch::Tensor predict(torch::Tensor& X) override; 20 : std::vector<int> predict(std::vector<std::vector<int>>& X) override; 21 : torch::Tensor predict_proba(torch::Tensor& X) override; @@ -89,13 +89,13 @@ 27 : int getNumberOfStates() const override; 28 : std::vector<std::string> show() const override; 29 : std::vector<std::string> graph(const std::string& title) const override; - 30 18 : std::vector<std::string> topological_order() override + 30 6 : std::vector<std::string> topological_order() override 31 : { - 32 18 : return std::vector<std::string>(); + 32 6 : return std::vector<std::string>(); 33 : } - 34 12 : std::string dump_cpt() const override + 34 4 : std::string dump_cpt() const override 35 : { - 36 24 : return ""; + 36 8 : return ""; 37 : } 38 : protected: 39 : torch::Tensor predict_average_voting(torch::Tensor& X); diff --git a/html/bayesnet/ensembles/index-sort-f.html b/html/bayesnet/ensembles/index-sort-f.html index 2485de4..e8a0bea 100644 --- a/html/bayesnet/ensembles/index-sort-f.html +++ b/html/bayesnet/ensembles/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/ensembles/index-sort-l.html b/html/bayesnet/ensembles/index-sort-l.html index f29eb65..8be1f27 100644 --- a/html/bayesnet/ensembles/index-sort-l.html +++ b/html/bayesnet/ensembles/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/ensembles/index.html b/html/bayesnet/ensembles/index.html index 3781825..b1bc63b 100644 --- a/html/bayesnet/ensembles/index.html +++ b/html/bayesnet/ensembles/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/feature_selection/CFS.cc.func-c.html b/html/bayesnet/feature_selection/CFS.cc.func-c.html index 11f733c..a642ea5 100644 --- a/html/bayesnet/feature_selection/CFS.cc.func-c.html +++ b/html/bayesnet/feature_selection/CFS.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,14 +65,14 @@ bayesnet::CFS::fit() - 40 + 12 bayesnet::CFS::computeContinueCondition(std::vector<int, std::allocator<int> > const&) - 186 + 56 diff --git a/html/bayesnet/feature_selection/CFS.cc.func.html b/html/bayesnet/feature_selection/CFS.cc.func.html index aef3596..23ec431 100644 --- a/html/bayesnet/feature_selection/CFS.cc.func.html +++ b/html/bayesnet/feature_selection/CFS.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,14 +65,14 @@ bayesnet::CFS::computeContinueCondition(std::vector<int, std::allocator<int> > const&) - 186 + 56 bayesnet::CFS::fit() - 40 + 12 diff --git a/html/bayesnet/feature_selection/CFS.cc.gcov.html b/html/bayesnet/feature_selection/CFS.cc.gcov.html index e0749b7..0c2038f 100644 --- a/html/bayesnet/feature_selection/CFS.cc.gcov.html +++ b/html/bayesnet/feature_selection/CFS.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,46 +70,46 @@ 8 : #include "bayesnet/utils/bayesnetUtils.h" 9 : #include "CFS.h" 10 : namespace bayesnet { - 11 40 : void CFS::fit() + 11 12 : void CFS::fit() 12 : { - 13 40 : initialize(); - 14 40 : computeSuLabels(); - 15 40 : auto featureOrder = argsort(suLabels); // sort descending order - 16 40 : auto continueCondition = true; - 17 40 : auto feature = featureOrder[0]; - 18 40 : selectedFeatures.push_back(feature); - 19 40 : selectedScores.push_back(suLabels[feature]); - 20 40 : featureOrder.erase(featureOrder.begin()); - 21 226 : while (continueCondition) { - 22 186 : double merit = std::numeric_limits<double>::lowest(); - 23 186 : int bestFeature = -1; - 24 1083 : for (auto feature : featureOrder) { - 25 897 : selectedFeatures.push_back(feature); + 13 12 : initialize(); + 14 12 : computeSuLabels(); + 15 12 : auto featureOrder = argsort(suLabels); // sort descending order + 16 12 : auto continueCondition = true; + 17 12 : auto feature = featureOrder[0]; + 18 12 : selectedFeatures.push_back(feature); + 19 12 : selectedScores.push_back(suLabels[feature]); + 20 12 : featureOrder.erase(featureOrder.begin()); + 21 68 : while (continueCondition) { + 22 56 : double merit = std::numeric_limits<double>::lowest(); + 23 56 : int bestFeature = -1; + 24 328 : for (auto feature : featureOrder) { + 25 272 : selectedFeatures.push_back(feature); 26 : // Compute merit with selectedFeatures - 27 897 : auto meritNew = computeMeritCFS(); - 28 897 : if (meritNew > merit) { - 29 379 : merit = meritNew; - 30 379 : bestFeature = feature; + 27 272 : auto meritNew = computeMeritCFS(); + 28 272 : if (meritNew > merit) { + 29 114 : merit = meritNew; + 30 114 : bestFeature = feature; 31 : } - 32 897 : selectedFeatures.pop_back(); + 32 272 : selectedFeatures.pop_back(); 33 : } - 34 186 : if (bestFeature == -1) { + 34 56 : if (bestFeature == -1) { 35 : // meritNew has to be nan due to constant features 36 0 : break; 37 : } - 38 186 : selectedFeatures.push_back(bestFeature); - 39 186 : selectedScores.push_back(merit); - 40 186 : featureOrder.erase(remove(featureOrder.begin(), featureOrder.end(), bestFeature), featureOrder.end()); - 41 186 : continueCondition = computeContinueCondition(featureOrder); + 38 56 : selectedFeatures.push_back(bestFeature); + 39 56 : selectedScores.push_back(merit); + 40 56 : featureOrder.erase(remove(featureOrder.begin(), featureOrder.end(), bestFeature), featureOrder.end()); + 41 56 : continueCondition = computeContinueCondition(featureOrder); 42 : } - 43 40 : fitted = true; - 44 40 : } - 45 186 : bool CFS::computeContinueCondition(const std::vector<int>& featureOrder) + 43 12 : fitted = true; + 44 12 : } + 45 56 : bool CFS::computeContinueCondition(const std::vector<int>& featureOrder) 46 : { - 47 186 : if (selectedFeatures.size() == maxFeatures || featureOrder.size() == 0) { - 48 7 : return false; + 47 56 : if (selectedFeatures.size() == maxFeatures || featureOrder.size() == 0) { + 48 2 : return false; 49 : } - 50 179 : if (selectedScores.size() >= 5) { + 50 54 : if (selectedScores.size() >= 5) { 51 : /* 52 : "To prevent the best first search from exploring the entire 53 : feature subset search space, a stopping criterion is imposed. @@ -117,25 +117,25 @@ 55 : subsets show no improvement over the current best subset." 56 : as stated in Mark A.Hall Thesis 57 : */ - 58 66 : double item_ant = std::numeric_limits<double>::lowest(); - 59 66 : int num = 0; - 60 66 : std::vector<double> lastFive(selectedScores.end() - 5, selectedScores.end()); - 61 264 : for (auto item : lastFive) { - 62 231 : if (item_ant == std::numeric_limits<double>::lowest()) { - 63 66 : item_ant = item; + 58 20 : double item_ant = std::numeric_limits<double>::lowest(); + 59 20 : int num = 0; + 60 20 : std::vector<double> lastFive(selectedScores.end() - 5, selectedScores.end()); + 61 80 : for (auto item : lastFive) { + 62 70 : if (item_ant == std::numeric_limits<double>::lowest()) { + 63 20 : item_ant = item; 64 : } - 65 231 : if (item > item_ant) { - 66 33 : break; + 65 70 : if (item > item_ant) { + 66 10 : break; 67 : } else { - 68 198 : num++; - 69 198 : item_ant = item; + 68 60 : num++; + 69 60 : item_ant = item; 70 : } 71 : } - 72 66 : if (num == 5) { - 73 33 : return false; + 72 20 : if (num == 5) { + 73 10 : return false; 74 : } - 75 66 : } - 76 146 : return true; + 75 20 : } + 76 44 : return true; 77 : } 78 : } diff --git a/html/bayesnet/feature_selection/CFS.h.func-c.html b/html/bayesnet/feature_selection/CFS.h.func-c.html index c2472d4..465ae29 100644 --- a/html/bayesnet/feature_selection/CFS.h.func-c.html +++ b/html/bayesnet/feature_selection/CFS.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,14 +65,14 @@ bayesnet::CFS::CFS(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, at::Tensor const&) - 26 + 14 bayesnet::CFS::~CFS() - 88 + 28 diff --git a/html/bayesnet/feature_selection/CFS.h.func.html b/html/bayesnet/feature_selection/CFS.h.func.html index 8b0df43..ec3a5d8 100644 --- a/html/bayesnet/feature_selection/CFS.h.func.html +++ b/html/bayesnet/feature_selection/CFS.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,14 +65,14 @@ bayesnet::CFS::CFS(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, at::Tensor const&) - 26 + 14 bayesnet::CFS::~CFS() - 88 + 28 diff --git a/html/bayesnet/feature_selection/CFS.h.gcov.html b/html/bayesnet/feature_selection/CFS.h.gcov.html index f8b8801..b1af91c 100644 --- a/html/bayesnet/feature_selection/CFS.h.gcov.html +++ b/html/bayesnet/feature_selection/CFS.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -75,11 +75,11 @@ 13 : class CFS : public FeatureSelect { 14 : public: 15 : // dataset is a n+1xm tensor of integers where dataset[-1] is the y std::vector - 16 26 : CFS(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights) : - 17 26 : FeatureSelect(samples, features, className, maxFeatures, classNumStates, weights) + 16 14 : CFS(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights) : + 17 14 : FeatureSelect(samples, features, className, maxFeatures, classNumStates, weights) 18 : { - 19 26 : } - 20 88 : virtual ~CFS() {}; + 19 14 : } + 20 28 : virtual ~CFS() {}; 21 : void fit() override; 22 : private: 23 : bool computeContinueCondition(const std::vector<int>& featureOrder); diff --git a/html/bayesnet/feature_selection/FCBF.cc.func-c.html b/html/bayesnet/feature_selection/FCBF.cc.func-c.html index a33fef7..ecb681f 100644 --- a/html/bayesnet/feature_selection/FCBF.cc.func-c.html +++ b/html/bayesnet/feature_selection/FCBF.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,14 +65,14 @@ bayesnet::FCBF::fit() - 34 + 10 bayesnet::FCBF::FCBF(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, at::Tensor const&, double) - 48 + 14 diff --git a/html/bayesnet/feature_selection/FCBF.cc.func.html b/html/bayesnet/feature_selection/FCBF.cc.func.html index fb4d82d..b9aeaa8 100644 --- a/html/bayesnet/feature_selection/FCBF.cc.func.html +++ b/html/bayesnet/feature_selection/FCBF.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,14 +65,14 @@ bayesnet::FCBF::FCBF(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, at::Tensor const&, double) - 48 + 14 bayesnet::FCBF::fit() - 34 + 10 diff --git a/html/bayesnet/feature_selection/FCBF.cc.gcov.html b/html/bayesnet/feature_selection/FCBF.cc.gcov.html index 4fed4df..951a31e 100644 --- a/html/bayesnet/feature_selection/FCBF.cc.gcov.html +++ b/html/bayesnet/feature_selection/FCBF.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,45 +70,45 @@ 8 : #include "FCBF.h" 9 : namespace bayesnet { 10 : - 11 48 : FCBF::FCBF(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights, const double threshold) : - 12 48 : FeatureSelect(samples, features, className, maxFeatures, classNumStates, weights), threshold(threshold) + 11 14 : FCBF::FCBF(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights, const double threshold) : + 12 14 : FeatureSelect(samples, features, className, maxFeatures, classNumStates, weights), threshold(threshold) 13 : { - 14 48 : if (threshold < 1e-7) { - 15 14 : throw std::invalid_argument("Threshold cannot be less than 1e-7"); + 14 14 : if (threshold < 1e-7) { + 15 4 : throw std::invalid_argument("Threshold cannot be less than 1e-7"); 16 : } - 17 48 : } - 18 34 : void FCBF::fit() + 17 14 : } + 18 10 : void FCBF::fit() 19 : { - 20 34 : initialize(); - 21 34 : computeSuLabels(); - 22 34 : auto featureOrder = argsort(suLabels); // sort descending order - 23 34 : auto featureOrderCopy = featureOrder; - 24 284 : for (const auto& feature : featureOrder) { + 20 10 : initialize(); + 21 10 : computeSuLabels(); + 22 10 : auto featureOrder = argsort(suLabels); // sort descending order + 23 10 : auto featureOrderCopy = featureOrder; + 24 84 : for (const auto& feature : featureOrder) { 25 : // Don't self compare - 26 250 : featureOrderCopy.erase(featureOrderCopy.begin()); - 27 250 : if (suLabels.at(feature) == 0.0) { + 26 74 : featureOrderCopy.erase(featureOrderCopy.begin()); + 27 74 : if (suLabels.at(feature) == 0.0) { 28 : // The feature has been removed from the list - 29 108 : continue; + 29 32 : continue; 30 : } - 31 142 : if (suLabels.at(feature) < threshold) { + 31 42 : if (suLabels.at(feature) < threshold) { 32 0 : break; 33 : } 34 : // Remove redundant features - 35 781 : for (const auto& featureCopy : featureOrderCopy) { - 36 639 : double value = computeSuFeatures(feature, featureCopy); - 37 639 : if (value >= suLabels.at(featureCopy)) { + 35 232 : for (const auto& featureCopy : featureOrderCopy) { + 36 190 : double value = computeSuFeatures(feature, featureCopy); + 37 190 : if (value >= suLabels.at(featureCopy)) { 38 : // Remove feature from list - 39 221 : suLabels[featureCopy] = 0.0; + 39 66 : suLabels[featureCopy] = 0.0; 40 : } 41 : } - 42 142 : selectedFeatures.push_back(feature); - 43 142 : selectedScores.push_back(suLabels[feature]); - 44 142 : if (selectedFeatures.size() == maxFeatures) { + 42 42 : selectedFeatures.push_back(feature); + 43 42 : selectedScores.push_back(suLabels[feature]); + 44 42 : if (selectedFeatures.size() == maxFeatures) { 45 0 : break; 46 : } 47 : } - 48 34 : fitted = true; - 49 34 : } + 48 10 : fitted = true; + 49 10 : } 50 : } diff --git a/html/bayesnet/feature_selection/FCBF.h.func-c.html b/html/bayesnet/feature_selection/FCBF.h.func-c.html index 3ed4f71..9bc7618 100644 --- a/html/bayesnet/feature_selection/FCBF.h.func-c.html +++ b/html/bayesnet/feature_selection/FCBF.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::FCBF::~FCBF() - 38 + 20 diff --git a/html/bayesnet/feature_selection/FCBF.h.func.html b/html/bayesnet/feature_selection/FCBF.h.func.html index d83d331..d90b6a2 100644 --- a/html/bayesnet/feature_selection/FCBF.h.func.html +++ b/html/bayesnet/feature_selection/FCBF.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::FCBF::~FCBF() - 38 + 20 diff --git a/html/bayesnet/feature_selection/FCBF.h.gcov.html b/html/bayesnet/feature_selection/FCBF.h.gcov.html index cec7514..d96f6e7 100644 --- a/html/bayesnet/feature_selection/FCBF.h.gcov.html +++ b/html/bayesnet/feature_selection/FCBF.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -76,7 +76,7 @@ 14 : public: 15 : // dataset is a n+1xm tensor of integers where dataset[-1] is the y std::vector 16 : FCBF(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights, const double threshold); - 17 38 : virtual ~FCBF() {}; + 17 20 : virtual ~FCBF() {}; 18 : void fit() override; 19 : private: 20 : double threshold = -1; diff --git a/html/bayesnet/feature_selection/FeatureSelect.cc.func-c.html b/html/bayesnet/feature_selection/FeatureSelect.cc.func-c.html index c36db66..b92a13f 100644 --- a/html/bayesnet/feature_selection/FeatureSelect.cc.func-c.html +++ b/html/bayesnet/feature_selection/FeatureSelect.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,56 +65,56 @@ bayesnet::FeatureSelect::computeSuLabels() - 108 + 32 bayesnet::FeatureSelect::initialize() - 108 + 32 bayesnet::FeatureSelect::getFeatures() const - 116 + 36 bayesnet::FeatureSelect::getScores() const - 116 + 36 bayesnet::FeatureSelect::FeatureSelect(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, at::Tensor const&) - 154 + 46 bayesnet::FeatureSelect::computeMeritCFS() - 1047 + 316 bayesnet::FeatureSelect::symmetricalUncertainty(int, int) - 2751 + 822 bayesnet::FeatureSelect::computeSuFeatures(int, int) - 6499 + 1960 diff --git a/html/bayesnet/feature_selection/FeatureSelect.cc.func.html b/html/bayesnet/feature_selection/FeatureSelect.cc.func.html index 2bdd1de..5e5c961 100644 --- a/html/bayesnet/feature_selection/FeatureSelect.cc.func.html +++ b/html/bayesnet/feature_selection/FeatureSelect.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,56 +65,56 @@ bayesnet::FeatureSelect::FeatureSelect(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, at::Tensor const&) - 154 + 46 bayesnet::FeatureSelect::computeMeritCFS() - 1047 + 316 bayesnet::FeatureSelect::computeSuFeatures(int, int) - 6499 + 1960 bayesnet::FeatureSelect::computeSuLabels() - 108 + 32 bayesnet::FeatureSelect::getFeatures() const - 116 + 36 bayesnet::FeatureSelect::getScores() const - 116 + 36 bayesnet::FeatureSelect::initialize() - 108 + 32 bayesnet::FeatureSelect::symmetricalUncertainty(int, int) - 2751 + 822 diff --git a/html/bayesnet/feature_selection/FeatureSelect.cc.gcov.html b/html/bayesnet/feature_selection/FeatureSelect.cc.gcov.html index b448081..2a66cd4 100644 --- a/html/bayesnet/feature_selection/FeatureSelect.cc.gcov.html +++ b/html/bayesnet/feature_selection/FeatureSelect.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,17 +70,17 @@ 8 : #include "bayesnet/utils/bayesnetUtils.h" 9 : #include "FeatureSelect.h" 10 : namespace bayesnet { - 11 154 : FeatureSelect::FeatureSelect(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights) : - 12 154 : Metrics(samples, features, className, classNumStates), maxFeatures(maxFeatures == 0 ? samples.size(0) - 1 : maxFeatures), weights(weights) + 11 46 : FeatureSelect::FeatureSelect(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights) : + 12 46 : Metrics(samples, features, className, classNumStates), maxFeatures(maxFeatures == 0 ? samples.size(0) - 1 : maxFeatures), weights(weights) 13 : 14 : { - 15 154 : } - 16 108 : void FeatureSelect::initialize() + 15 46 : } + 16 32 : void FeatureSelect::initialize() 17 : { - 18 108 : selectedFeatures.clear(); - 19 108 : selectedScores.clear(); - 20 108 : } - 21 2751 : double FeatureSelect::symmetricalUncertainty(int a, int b) + 18 32 : selectedFeatures.clear(); + 19 32 : selectedScores.clear(); + 20 32 : } + 21 822 : double FeatureSelect::symmetricalUncertainty(int a, int b) 22 : { 23 : /* 24 : Compute symmetrical uncertainty. Normalize* information gain (mutual @@ -88,60 +88,60 @@ 26 : the bias due to high cardinality features. *Range [0, 1] 27 : (https://www.sciencedirect.com/science/article/pii/S0020025519303603) 28 : */ - 29 8253 : auto x = samples.index({ a, "..." }); - 30 8253 : auto y = samples.index({ b, "..." }); - 31 2751 : auto mu = mutualInformation(x, y, weights); - 32 2751 : auto hx = entropy(x, weights); - 33 2751 : auto hy = entropy(y, weights); - 34 2751 : return 2.0 * mu / (hx + hy); - 35 8253 : } - 36 108 : void FeatureSelect::computeSuLabels() + 29 2466 : auto x = samples.index({ a, "..." }); + 30 2466 : auto y = samples.index({ b, "..." }); + 31 822 : auto mu = mutualInformation(x, y, weights); + 32 822 : auto hx = entropy(x, weights); + 33 822 : auto hy = entropy(y, weights); + 34 822 : return 2.0 * mu / (hx + hy); + 35 2466 : } + 36 32 : void FeatureSelect::computeSuLabels() 37 : { 38 : // Compute Simmetrical Uncertainty between features and labels 39 : // https://en.wikipedia.org/wiki/Symmetric_uncertainty - 40 906 : for (int i = 0; i < features.size(); ++i) { - 41 798 : suLabels.push_back(symmetricalUncertainty(i, -1)); + 40 270 : for (int i = 0; i < features.size(); ++i) { + 41 238 : suLabels.push_back(symmetricalUncertainty(i, -1)); 42 : } - 43 108 : } - 44 6499 : double FeatureSelect::computeSuFeatures(const int firstFeature, const int secondFeature) + 43 32 : } + 44 1960 : double FeatureSelect::computeSuFeatures(const int firstFeature, const int secondFeature) 45 : { 46 : // Compute Simmetrical Uncertainty between features 47 : // https://en.wikipedia.org/wiki/Symmetric_uncertainty 48 : try { - 49 6499 : return suFeatures.at({ firstFeature, secondFeature }); + 49 1960 : return suFeatures.at({ firstFeature, secondFeature }); 50 : } - 51 1953 : catch (const std::out_of_range& e) { - 52 1953 : double result = symmetricalUncertainty(firstFeature, secondFeature); - 53 1953 : suFeatures[{firstFeature, secondFeature}] = result; - 54 1953 : return result; - 55 1953 : } + 51 584 : catch (const std::out_of_range& e) { + 52 584 : double result = symmetricalUncertainty(firstFeature, secondFeature); + 53 584 : suFeatures[{firstFeature, secondFeature}] = result; + 54 584 : return result; + 55 584 : } 56 : } - 57 1047 : double FeatureSelect::computeMeritCFS() + 57 316 : double FeatureSelect::computeMeritCFS() 58 : { - 59 1047 : double rcf = 0; - 60 4816 : for (auto feature : selectedFeatures) { - 61 3769 : rcf += suLabels[feature]; + 59 316 : double rcf = 0; + 60 1454 : for (auto feature : selectedFeatures) { + 61 1138 : rcf += suLabels[feature]; 62 : } - 63 1047 : double rff = 0; - 64 1047 : int n = selectedFeatures.size(); - 65 6907 : for (const auto& item : doCombinations(selectedFeatures)) { - 66 5860 : rff += computeSuFeatures(item.first, item.second); - 67 1047 : } - 68 1047 : return rcf / sqrt(n + (n * n - n) * rff); + 63 316 : double rff = 0; + 64 316 : int n = selectedFeatures.size(); + 65 2086 : for (const auto& item : doCombinations(selectedFeatures)) { + 66 1770 : rff += computeSuFeatures(item.first, item.second); + 67 316 : } + 68 316 : return rcf / sqrt(n + (n * n - n) * rff); 69 : } - 70 116 : std::vector<int> FeatureSelect::getFeatures() const + 70 36 : std::vector<int> FeatureSelect::getFeatures() const 71 : { - 72 116 : if (!fitted) { - 73 8 : throw std::runtime_error("FeatureSelect not fitted"); + 72 36 : if (!fitted) { + 73 4 : throw std::runtime_error("FeatureSelect not fitted"); 74 : } - 75 108 : return selectedFeatures; + 75 32 : return selectedFeatures; 76 : } - 77 116 : std::vector<double> FeatureSelect::getScores() const + 77 36 : std::vector<double> FeatureSelect::getScores() const 78 : { - 79 116 : if (!fitted) { - 80 8 : throw std::runtime_error("FeatureSelect not fitted"); + 79 36 : if (!fitted) { + 80 4 : throw std::runtime_error("FeatureSelect not fitted"); 81 : } - 82 108 : return selectedScores; + 82 32 : return selectedScores; 83 : } 84 : } diff --git a/html/bayesnet/feature_selection/FeatureSelect.h.func-c.html b/html/bayesnet/feature_selection/FeatureSelect.h.func-c.html index fa062e7..684dd54 100644 --- a/html/bayesnet/feature_selection/FeatureSelect.h.func-c.html +++ b/html/bayesnet/feature_selection/FeatureSelect.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::FeatureSelect::~FeatureSelect() - 88 + 46 diff --git a/html/bayesnet/feature_selection/FeatureSelect.h.func.html b/html/bayesnet/feature_selection/FeatureSelect.h.func.html index 010ffc0..a20db74 100644 --- a/html/bayesnet/feature_selection/FeatureSelect.h.func.html +++ b/html/bayesnet/feature_selection/FeatureSelect.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::FeatureSelect::~FeatureSelect() - 88 + 46 diff --git a/html/bayesnet/feature_selection/FeatureSelect.h.gcov.html b/html/bayesnet/feature_selection/FeatureSelect.h.gcov.html index dbdfa78..f72b058 100644 --- a/html/bayesnet/feature_selection/FeatureSelect.h.gcov.html +++ b/html/bayesnet/feature_selection/FeatureSelect.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -76,7 +76,7 @@ 14 : public: 15 : // dataset is a n+1xm tensor of integers where dataset[-1] is the y std::vector 16 : FeatureSelect(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights); - 17 88 : virtual ~FeatureSelect() {}; + 17 46 : virtual ~FeatureSelect() {}; 18 : virtual void fit() = 0; 19 : std::vector<int> getFeatures() const; 20 : std::vector<double> getScores() const; diff --git a/html/bayesnet/feature_selection/IWSS.cc.func-c.html b/html/bayesnet/feature_selection/IWSS.cc.func-c.html index 9e774cd..7741560 100644 --- a/html/bayesnet/feature_selection/IWSS.cc.func-c.html +++ b/html/bayesnet/feature_selection/IWSS.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,14 +65,14 @@ bayesnet::IWSS::fit() - 34 + 10 bayesnet::IWSS::IWSS(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, at::Tensor const&, double) - 62 + 18 diff --git a/html/bayesnet/feature_selection/IWSS.cc.func.html b/html/bayesnet/feature_selection/IWSS.cc.func.html index 38a58bc..6374190 100644 --- a/html/bayesnet/feature_selection/IWSS.cc.func.html +++ b/html/bayesnet/feature_selection/IWSS.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,14 +65,14 @@ bayesnet::IWSS::IWSS(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, at::Tensor const&, double) - 62 + 18 bayesnet::IWSS::fit() - 34 + 10 diff --git a/html/bayesnet/feature_selection/IWSS.cc.gcov.html b/html/bayesnet/feature_selection/IWSS.cc.gcov.html index a5cee91..db2c864 100644 --- a/html/bayesnet/feature_selection/IWSS.cc.gcov.html +++ b/html/bayesnet/feature_selection/IWSS.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,48 +70,48 @@ 8 : #include "bayesnet/utils/bayesnetUtils.h" 9 : #include "IWSS.h" 10 : namespace bayesnet { - 11 62 : IWSS::IWSS(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights, const double threshold) : - 12 62 : FeatureSelect(samples, features, className, maxFeatures, classNumStates, weights), threshold(threshold) + 11 18 : IWSS::IWSS(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights, const double threshold) : + 12 18 : FeatureSelect(samples, features, className, maxFeatures, classNumStates, weights), threshold(threshold) 13 : { - 14 62 : if (threshold < 0 || threshold > .5) { - 15 28 : throw std::invalid_argument("Threshold has to be in [0, 0.5]"); + 14 18 : if (threshold < 0 || threshold > .5) { + 15 8 : throw std::invalid_argument("Threshold has to be in [0, 0.5]"); 16 : } - 17 62 : } - 18 34 : void IWSS::fit() + 17 18 : } + 18 10 : void IWSS::fit() 19 : { - 20 34 : initialize(); - 21 34 : computeSuLabels(); - 22 34 : auto featureOrder = argsort(suLabels); // sort descending order - 23 34 : auto featureOrderCopy = featureOrder; + 20 10 : initialize(); + 21 10 : computeSuLabels(); + 22 10 : auto featureOrder = argsort(suLabels); // sort descending order + 23 10 : auto featureOrderCopy = featureOrder; 24 : // Add first and second features to result 25 : // First with its own score - 26 34 : auto first_feature = pop_first(featureOrderCopy); - 27 34 : selectedFeatures.push_back(first_feature); - 28 34 : selectedScores.push_back(suLabels.at(first_feature)); + 26 10 : auto first_feature = pop_first(featureOrderCopy); + 27 10 : selectedFeatures.push_back(first_feature); + 28 10 : selectedScores.push_back(suLabels.at(first_feature)); 29 : // Second with the score of the candidates - 30 34 : selectedFeatures.push_back(pop_first(featureOrderCopy)); - 31 34 : auto merit = computeMeritCFS(); - 32 34 : selectedScores.push_back(merit); - 33 116 : for (const auto feature : featureOrderCopy) { - 34 116 : selectedFeatures.push_back(feature); + 30 10 : selectedFeatures.push_back(pop_first(featureOrderCopy)); + 31 10 : auto merit = computeMeritCFS(); + 32 10 : selectedScores.push_back(merit); + 33 34 : for (const auto feature : featureOrderCopy) { + 34 34 : selectedFeatures.push_back(feature); 35 : // Compute merit with selectedFeatures - 36 116 : auto meritNew = computeMeritCFS(); - 37 116 : double delta = merit != 0.0 ? std::abs(merit - meritNew) / merit : 0.0; - 38 116 : if (meritNew > merit || delta < threshold) { - 39 82 : if (meritNew > merit) { + 36 34 : auto meritNew = computeMeritCFS(); + 37 34 : double delta = merit != 0.0 ? std::abs(merit - meritNew) / merit : 0.0; + 38 34 : if (meritNew > merit || delta < threshold) { + 39 24 : if (meritNew > merit) { 40 0 : merit = meritNew; 41 : } - 42 82 : selectedScores.push_back(meritNew); + 42 24 : selectedScores.push_back(meritNew); 43 : } else { - 44 34 : selectedFeatures.pop_back(); - 45 34 : break; + 44 10 : selectedFeatures.pop_back(); + 45 10 : break; 46 : } - 47 82 : if (selectedFeatures.size() == maxFeatures) { + 47 24 : if (selectedFeatures.size() == maxFeatures) { 48 0 : break; 49 : } 50 : } - 51 34 : fitted = true; - 52 34 : } + 51 10 : fitted = true; + 52 10 : } 53 : } diff --git a/html/bayesnet/feature_selection/IWSS.h.func-c.html b/html/bayesnet/feature_selection/IWSS.h.func-c.html index a1ad55c..45d2042 100644 --- a/html/bayesnet/feature_selection/IWSS.h.func-c.html +++ b/html/bayesnet/feature_selection/IWSS.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::IWSS::~IWSS() - 38 + 20 diff --git a/html/bayesnet/feature_selection/IWSS.h.func.html b/html/bayesnet/feature_selection/IWSS.h.func.html index e57ad86..9fa408f 100644 --- a/html/bayesnet/feature_selection/IWSS.h.func.html +++ b/html/bayesnet/feature_selection/IWSS.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::IWSS::~IWSS() - 38 + 20 diff --git a/html/bayesnet/feature_selection/IWSS.h.gcov.html b/html/bayesnet/feature_selection/IWSS.h.gcov.html index 8aa79b8..2749fe6 100644 --- a/html/bayesnet/feature_selection/IWSS.h.gcov.html +++ b/html/bayesnet/feature_selection/IWSS.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -76,7 +76,7 @@ 14 : public: 15 : // dataset is a n+1xm tensor of integers where dataset[-1] is the y std::vector 16 : IWSS(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int maxFeatures, const int classNumStates, const torch::Tensor& weights, const double threshold); - 17 38 : virtual ~IWSS() {}; + 17 20 : virtual ~IWSS() {}; 18 : void fit() override; 19 : private: 20 : double threshold = -1; diff --git a/html/bayesnet/feature_selection/index-sort-f.html b/html/bayesnet/feature_selection/index-sort-f.html index c6af075..2e71c24 100644 --- a/html/bayesnet/feature_selection/index-sort-f.html +++ b/html/bayesnet/feature_selection/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/feature_selection/index-sort-l.html b/html/bayesnet/feature_selection/index-sort-l.html index 11c73ff..6271255 100644 --- a/html/bayesnet/feature_selection/index-sort-l.html +++ b/html/bayesnet/feature_selection/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/feature_selection/index.html b/html/bayesnet/feature_selection/index.html index 6b8ae39..2ae46ee 100644 --- a/html/bayesnet/feature_selection/index.html +++ b/html/bayesnet/feature_selection/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/index-sort-f.html b/html/bayesnet/index-sort-f.html index 63514f4..7bbbc83 100644 --- a/html/bayesnet/index-sort-f.html +++ b/html/bayesnet/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/index-sort-l.html b/html/bayesnet/index-sort-l.html index d3a3981..dba9744 100644 --- a/html/bayesnet/index-sort-l.html +++ b/html/bayesnet/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/index.html b/html/bayesnet/index.html index b0a17ad..77b30ba 100644 --- a/html/bayesnet/index.html +++ b/html/bayesnet/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/network/Network.cc.func-c.html b/html/bayesnet/network/Network.cc.func-c.html index 4f2dabd..30d087b 100644 --- a/html/bayesnet/network/Network.cc.func-c.html +++ b/html/bayesnet/network/Network.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/network/Network.cc.func.html b/html/bayesnet/network/Network.cc.func.html index 620fd85..6db0e63 100644 --- a/html/bayesnet/network/Network.cc.func.html +++ b/html/bayesnet/network/Network.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/network/Network.cc.gcov.html b/html/bayesnet/network/Network.cc.gcov.html index b8fdb0a..6ed7246 100644 --- a/html/bayesnet/network/Network.cc.gcov.html +++ b/html/bayesnet/network/Network.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/network/Network.h.func-c.html b/html/bayesnet/network/Network.h.func-c.html index c53e47a..ffc2cf9 100644 --- a/html/bayesnet/network/Network.h.func-c.html +++ b/html/bayesnet/network/Network.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::Network::~Network() - 4626 + 1542 diff --git a/html/bayesnet/network/Network.h.func.html b/html/bayesnet/network/Network.h.func.html index 9cba0b3..fc374b6 100644 --- a/html/bayesnet/network/Network.h.func.html +++ b/html/bayesnet/network/Network.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::Network::~Network() - 4626 + 1542 diff --git a/html/bayesnet/network/Network.h.gcov.html b/html/bayesnet/network/Network.h.gcov.html index ab93199..85ecda2 100644 --- a/html/bayesnet/network/Network.h.gcov.html +++ b/html/bayesnet/network/Network.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -79,7 +79,7 @@ 17 : Network(); 18 : explicit Network(float); 19 : explicit Network(const Network&); - 20 4626 : ~Network() = default; + 20 1542 : ~Network() = default; 21 : torch::Tensor& getSamples(); 22 : float getMaxThreads() const; 23 : void addNode(const std::string&); diff --git a/html/bayesnet/network/Node.cc.func-c.html b/html/bayesnet/network/Node.cc.func-c.html index 6082b8c..bde089b 100644 --- a/html/bayesnet/network/Node.cc.func-c.html +++ b/html/bayesnet/network/Node.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,140 +65,140 @@ bayesnet::Node::clear() - 6 + 2 bayesnet::Node::removeChild(bayesnet::Node*) - 18 + 6 bayesnet::Node::removeParent(bayesnet::Node*) - 18 + 6 bayesnet::Node::combinations(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) - 30 + 10 bayesnet::Node::minFill() - 30 + 10 bayesnet::Node::getCPT() - 630 + 210 bayesnet::Node::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) - 918 + 306 auto bayesnet::Node::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(auto:1 const&)#1}::operator()<bayesnet::Node*>(bayesnet::Node* const&) const - 1446 + 482 bayesnet::Node::getParents() - 7608 + 2536 bayesnet::Node::Node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) - 40176 + 13392 bayesnet::Node::computeCPT(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, double, at::Tensor const&) - 42582 + 14194 bayesnet::Node::setNumStates(int) - 42582 + 14194 bayesnet::Node::addParent(bayesnet::Node*) - 74892 + 24964 bayesnet::Node::addChild(bayesnet::Node*) - 74904 + 24968 auto bayesnet::Node::computeCPT(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, double, at::Tensor const&)::{lambda(auto:1 const&)#1}::operator()<bayesnet::Node*>(bayesnet::Node* const&) const - 79080 + 26360 bayesnet::Node::getNumStates() const - 81552 + 27184 bayesnet::Node::getChildren() - 100284 + 33428 bayesnet::Node::getFactorValue(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >&) - 95407308 + 31802436 auto bayesnet::Node::getFactorValue(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >&)::{lambda(auto:1 const&)#1}::operator()<bayesnet::Node*>(bayesnet::Node* const&) const - 176479596 + 58826532 bayesnet::Node::getName[abi:cxx11]() const - 205208016 + 68402672 diff --git a/html/bayesnet/network/Node.cc.func.html b/html/bayesnet/network/Node.cc.func.html index 6ca5a12..89f235e 100644 --- a/html/bayesnet/network/Node.cc.func.html +++ b/html/bayesnet/network/Node.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,140 +65,140 @@ auto bayesnet::Node::computeCPT(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, double, at::Tensor const&)::{lambda(auto:1 const&)#1}::operator()<bayesnet::Node*>(bayesnet::Node* const&) const - 79080 + 26360 auto bayesnet::Node::getFactorValue(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >&)::{lambda(auto:1 const&)#1}::operator()<bayesnet::Node*>(bayesnet::Node* const&) const - 176479596 + 58826532 auto bayesnet::Node::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::{lambda(auto:1 const&)#1}::operator()<bayesnet::Node*>(bayesnet::Node* const&) const - 1446 + 482 bayesnet::Node::Node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) - 40176 + 13392 bayesnet::Node::addChild(bayesnet::Node*) - 74904 + 24968 bayesnet::Node::addParent(bayesnet::Node*) - 74892 + 24964 bayesnet::Node::clear() - 6 + 2 bayesnet::Node::combinations(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&) - 30 + 10 bayesnet::Node::computeCPT(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, double, at::Tensor const&) - 42582 + 14194 bayesnet::Node::getCPT() - 630 + 210 bayesnet::Node::getChildren() - 100284 + 33428 bayesnet::Node::getFactorValue(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, int> > >&) - 95407308 + 31802436 bayesnet::Node::getName[abi:cxx11]() const - 205208016 + 68402672 bayesnet::Node::getNumStates() const - 81552 + 27184 bayesnet::Node::getParents() - 7608 + 2536 bayesnet::Node::graph(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) - 918 + 306 bayesnet::Node::minFill() - 30 + 10 bayesnet::Node::removeChild(bayesnet::Node*) - 18 + 6 bayesnet::Node::removeParent(bayesnet::Node*) - 18 + 6 bayesnet::Node::setNumStates(int) - 42582 + 14194 diff --git a/html/bayesnet/network/Node.cc.gcov.html b/html/bayesnet/network/Node.cc.gcov.html index c02805a..f257011 100644 --- a/html/bayesnet/network/Node.cc.gcov.html +++ b/html/bayesnet/network/Node.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,57 +70,57 @@ 8 : 9 : namespace bayesnet { 10 : - 11 40176 : Node::Node(const std::string& name) - 12 40176 : : name(name), numStates(0), cpTable(torch::Tensor()), parents(std::vector<Node*>()), children(std::vector<Node*>()) + 11 13392 : Node::Node(const std::string& name) + 12 13392 : : name(name), numStates(0), cpTable(torch::Tensor()), parents(std::vector<Node*>()), children(std::vector<Node*>()) 13 : { - 14 40176 : } - 15 6 : void Node::clear() + 14 13392 : } + 15 2 : void Node::clear() 16 : { - 17 6 : parents.clear(); - 18 6 : children.clear(); - 19 6 : cpTable = torch::Tensor(); - 20 6 : dimensions.clear(); - 21 6 : numStates = 0; - 22 6 : } - 23 205208016 : std::string Node::getName() const + 17 2 : parents.clear(); + 18 2 : children.clear(); + 19 2 : cpTable = torch::Tensor(); + 20 2 : dimensions.clear(); + 21 2 : numStates = 0; + 22 2 : } + 23 68402672 : std::string Node::getName() const 24 : { - 25 205208016 : return name; + 25 68402672 : return name; 26 : } - 27 74892 : void Node::addParent(Node* parent) + 27 24964 : void Node::addParent(Node* parent) 28 : { - 29 74892 : parents.push_back(parent); - 30 74892 : } - 31 18 : void Node::removeParent(Node* parent) + 29 24964 : parents.push_back(parent); + 30 24964 : } + 31 6 : void Node::removeParent(Node* parent) 32 : { - 33 18 : parents.erase(std::remove(parents.begin(), parents.end(), parent), parents.end()); - 34 18 : } - 35 18 : void Node::removeChild(Node* child) + 33 6 : parents.erase(std::remove(parents.begin(), parents.end(), parent), parents.end()); + 34 6 : } + 35 6 : void Node::removeChild(Node* child) 36 : { - 37 18 : children.erase(std::remove(children.begin(), children.end(), child), children.end()); - 38 18 : } - 39 74904 : void Node::addChild(Node* child) + 37 6 : children.erase(std::remove(children.begin(), children.end(), child), children.end()); + 38 6 : } + 39 24968 : void Node::addChild(Node* child) 40 : { - 41 74904 : children.push_back(child); - 42 74904 : } - 43 7608 : std::vector<Node*>& Node::getParents() + 41 24968 : children.push_back(child); + 42 24968 : } + 43 2536 : std::vector<Node*>& Node::getParents() 44 : { - 45 7608 : return parents; + 45 2536 : return parents; 46 : } - 47 100284 : std::vector<Node*>& Node::getChildren() + 47 33428 : std::vector<Node*>& Node::getChildren() 48 : { - 49 100284 : return children; + 49 33428 : return children; 50 : } - 51 81552 : int Node::getNumStates() const + 51 27184 : int Node::getNumStates() const 52 : { - 53 81552 : return numStates; + 53 27184 : return numStates; 54 : } - 55 42582 : void Node::setNumStates(int numStates) + 55 14194 : void Node::setNumStates(int numStates) 56 : { - 57 42582 : this->numStates = numStates; - 58 42582 : } - 59 630 : torch::Tensor& Node::getCPT() + 57 14194 : this->numStates = numStates; + 58 14194 : } + 59 210 : torch::Tensor& Node::getCPT() 60 : { - 61 630 : return cpTable; + 61 210 : return cpTable; 62 : } 63 : /* 64 : The MinFill criterion is a heuristic for variable elimination. @@ -129,76 +129,76 @@ 67 : The variable with the minimum number of edges is chosen. 68 : Here this is done computing the length of the combinations of the node neighbors taken 2 by 2. 69 : */ - 70 30 : unsigned Node::minFill() + 70 10 : unsigned Node::minFill() 71 : { - 72 30 : std::unordered_set<std::string> neighbors; - 73 78 : for (auto child : children) { - 74 48 : neighbors.emplace(child->getName()); + 72 10 : std::unordered_set<std::string> neighbors; + 73 26 : for (auto child : children) { + 74 16 : neighbors.emplace(child->getName()); 75 : } - 76 72 : for (auto parent : parents) { - 77 42 : neighbors.emplace(parent->getName()); + 76 24 : for (auto parent : parents) { + 77 14 : neighbors.emplace(parent->getName()); 78 : } - 79 30 : auto source = std::vector<std::string>(neighbors.begin(), neighbors.end()); - 80 60 : return combinations(source).size(); - 81 30 : } - 82 30 : std::vector<std::pair<std::string, std::string>> Node::combinations(const std::vector<std::string>& source) + 79 10 : auto source = std::vector<std::string>(neighbors.begin(), neighbors.end()); + 80 20 : return combinations(source).size(); + 81 10 : } + 82 10 : std::vector<std::pair<std::string, std::string>> Node::combinations(const std::vector<std::string>& source) 83 : { - 84 30 : std::vector<std::pair<std::string, std::string>> result; - 85 120 : for (int i = 0; i < source.size(); ++i) { - 86 90 : std::string temp = source[i]; - 87 186 : for (int j = i + 1; j < source.size(); ++j) { - 88 96 : result.push_back({ temp, source[j] }); + 84 10 : std::vector<std::pair<std::string, std::string>> result; + 85 40 : for (int i = 0; i < source.size(); ++i) { + 86 30 : std::string temp = source[i]; + 87 62 : for (int j = i + 1; j < source.size(); ++j) { + 88 32 : result.push_back({ temp, source[j] }); 89 : } - 90 90 : } - 91 30 : return result; + 90 30 : } + 91 10 : return result; 92 0 : } - 93 42582 : void Node::computeCPT(const torch::Tensor& dataset, const std::vector<std::string>& features, const double laplaceSmoothing, const torch::Tensor& weights) + 93 14194 : void Node::computeCPT(const torch::Tensor& dataset, const std::vector<std::string>& features, const double laplaceSmoothing, const torch::Tensor& weights) 94 : { - 95 42582 : dimensions.clear(); + 95 14194 : dimensions.clear(); 96 : // Get dimensions of the CPT - 97 42582 : dimensions.push_back(numStates); - 98 121662 : transform(parents.begin(), parents.end(), back_inserter(dimensions), [](const auto& parent) { return parent->getNumStates(); }); + 97 14194 : dimensions.push_back(numStates); + 98 40554 : transform(parents.begin(), parents.end(), back_inserter(dimensions), [](const auto& parent) { return parent->getNumStates(); }); 99 : 100 : // Create a tensor of zeros with the dimensions of the CPT - 101 42582 : cpTable = torch::zeros(dimensions, torch::kFloat) + laplaceSmoothing; + 101 14194 : cpTable = torch::zeros(dimensions, torch::kFloat) + laplaceSmoothing; 102 : // Fill table with counts - 103 42582 : auto pos = find(features.begin(), features.end(), name); - 104 42582 : if (pos == features.end()) { + 103 14194 : auto pos = find(features.begin(), features.end(), name); + 104 14194 : if (pos == features.end()) { 105 0 : throw std::logic_error("Feature " + name + " not found in dataset"); 106 : } - 107 42582 : int name_index = pos - features.begin(); - 108 15411546 : for (int n_sample = 0; n_sample < dataset.size(1); ++n_sample) { - 109 15368964 : c10::List<c10::optional<at::Tensor>> coordinates; - 110 46106892 : coordinates.push_back(dataset.index({ name_index, n_sample })); - 111 43942224 : for (auto parent : parents) { - 112 28573260 : pos = find(features.begin(), features.end(), parent->getName()); - 113 28573260 : if (pos == features.end()) { + 107 14194 : int name_index = pos - features.begin(); + 108 5137182 : for (int n_sample = 0; n_sample < dataset.size(1); ++n_sample) { + 109 5122988 : c10::List<c10::optional<at::Tensor>> coordinates; + 110 15368964 : coordinates.push_back(dataset.index({ name_index, n_sample })); + 111 14647408 : for (auto parent : parents) { + 112 9524420 : pos = find(features.begin(), features.end(), parent->getName()); + 113 9524420 : if (pos == features.end()) { 114 0 : throw std::logic_error("Feature parent " + parent->getName() + " not found in dataset"); 115 : } - 116 28573260 : int parent_index = pos - features.begin(); - 117 85719780 : coordinates.push_back(dataset.index({ parent_index, n_sample })); + 116 9524420 : int parent_index = pos - features.begin(); + 117 28573260 : coordinates.push_back(dataset.index({ parent_index, n_sample })); 118 : } 119 : // Increment the count of the corresponding coordinate - 120 30737928 : cpTable.index_put_({ coordinates }, cpTable.index({ coordinates }) + weights.index({ n_sample }).item<double>()); - 121 15368964 : } + 120 10245976 : cpTable.index_put_({ coordinates }, cpTable.index({ coordinates }) + weights.index({ n_sample }).item<double>()); + 121 5122988 : } 122 : // Normalize the counts - 123 42582 : cpTable = cpTable / cpTable.sum(0); - 124 59353770 : } - 125 95407308 : float Node::getFactorValue(std::map<std::string, int>& evidence) + 123 14194 : cpTable = cpTable / cpTable.sum(0); + 124 19784590 : } + 125 31802436 : float Node::getFactorValue(std::map<std::string, int>& evidence) 126 : { - 127 95407308 : c10::List<c10::optional<at::Tensor>> coordinates; + 127 31802436 : c10::List<c10::optional<at::Tensor>> coordinates; 128 : // following predetermined order of indices in the cpTable (see Node.h) - 129 95407308 : coordinates.push_back(at::tensor(evidence[name])); - 130 271886904 : transform(parents.begin(), parents.end(), std::back_inserter(coordinates), [&evidence](const auto& parent) { return at::tensor(evidence[parent->getName()]); }); - 131 190814616 : return cpTable.index({ coordinates }).item<float>(); - 132 95407308 : } - 133 918 : std::vector<std::string> Node::graph(const std::string& className) + 129 31802436 : coordinates.push_back(at::tensor(evidence[name])); + 130 90628968 : transform(parents.begin(), parents.end(), std::back_inserter(coordinates), [&evidence](const auto& parent) { return at::tensor(evidence[parent->getName()]); }); + 131 63604872 : return cpTable.index({ coordinates }).item<float>(); + 132 31802436 : } + 133 306 : std::vector<std::string> Node::graph(const std::string& className) 134 : { - 135 918 : auto output = std::vector<std::string>(); - 136 918 : auto suffix = name == className ? ", fontcolor=red, fillcolor=lightblue, style=filled " : ""; - 137 918 : output.push_back(name + " [shape=circle" + suffix + "] \n"); - 138 2364 : transform(children.begin(), children.end(), back_inserter(output), [this](const auto& child) { return name + " -> " + child->getName(); }); - 139 918 : return output; + 135 306 : auto output = std::vector<std::string>(); + 136 306 : auto suffix = name == className ? ", fontcolor=red, fillcolor=lightblue, style=filled " : ""; + 137 306 : output.push_back(name + " [shape=circle" + suffix + "] \n"); + 138 788 : transform(children.begin(), children.end(), back_inserter(output), [this](const auto& child) { return name + " -> " + child->getName(); }); + 139 306 : return output; 140 0 : } 141 : } diff --git a/html/bayesnet/network/index-sort-f.html b/html/bayesnet/network/index-sort-f.html index c0d9583..289dbd7 100644 --- a/html/bayesnet/network/index-sort-f.html +++ b/html/bayesnet/network/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/network/index-sort-l.html b/html/bayesnet/network/index-sort-l.html index a318281..1d94312 100644 --- a/html/bayesnet/network/index-sort-l.html +++ b/html/bayesnet/network/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/network/index.html b/html/bayesnet/network/index.html index f3e0dd6..628e966 100644 --- a/html/bayesnet/network/index.html +++ b/html/bayesnet/network/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/utils/BayesMetrics.cc.func-c.html b/html/bayesnet/utils/BayesMetrics.cc.func-c.html index 31cb90c..b2371b3 100644 --- a/html/bayesnet/utils/BayesMetrics.cc.func-c.html +++ b/html/bayesnet/utils/BayesMetrics.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,77 +65,77 @@ bayesnet::Metrics::getScoresKBest() const - 48 + 16 bayesnet::Metrics::Metrics(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<int, std::allocator<int> > const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) - 96 + 32 bayesnet::Metrics::maximumSpanningTree(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, at::Tensor const&, int) - 174 + 58 bayesnet::Metrics::conditionalEdge(at::Tensor const&) - 204 + 68 bayesnet::Metrics::SelectKBestWeighted(at::Tensor const&, bool, unsigned int) - 690 + 230 bayesnet::Metrics::Metrics(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) - 2248 + 744 bayesnet::Metrics::SelectKBestWeighted(at::Tensor const&, bool, unsigned int)::{lambda(int, int)#1}::operator()(int, int) const - 2718 + 906 bayesnet::Metrics::conditionalEntropy(at::Tensor const&, at::Tensor const&, at::Tensor const&) - 44793 + 14836 bayesnet::Metrics::mutualInformation(at::Tensor const&, at::Tensor const&, at::Tensor const&) - 44793 + 14836 bayesnet::Metrics::entropy(at::Tensor const&, at::Tensor const&) - 50295 + 16480 bayesnet::Metrics::SelectKBestWeighted(at::Tensor const&, bool, unsigned int)::{lambda(int, int)#2}::operator()(int, int) const - 97212 + 32404 diff --git a/html/bayesnet/utils/BayesMetrics.cc.func.html b/html/bayesnet/utils/BayesMetrics.cc.func.html index c818eec..2861c90 100644 --- a/html/bayesnet/utils/BayesMetrics.cc.func.html +++ b/html/bayesnet/utils/BayesMetrics.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,77 +65,77 @@ bayesnet::Metrics::Metrics(at::Tensor const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) - 2248 + 744 bayesnet::Metrics::Metrics(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<int, std::allocator<int> > const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int) - 96 + 32 bayesnet::Metrics::SelectKBestWeighted(at::Tensor const&, bool, unsigned int) - 690 + 230 bayesnet::Metrics::SelectKBestWeighted(at::Tensor const&, bool, unsigned int)::{lambda(int, int)#1}::operator()(int, int) const - 2718 + 906 bayesnet::Metrics::SelectKBestWeighted(at::Tensor const&, bool, unsigned int)::{lambda(int, int)#2}::operator()(int, int) const - 97212 + 32404 bayesnet::Metrics::conditionalEdge(at::Tensor const&) - 204 + 68 bayesnet::Metrics::conditionalEntropy(at::Tensor const&, at::Tensor const&, at::Tensor const&) - 44793 + 14836 bayesnet::Metrics::entropy(at::Tensor const&, at::Tensor const&) - 50295 + 16480 bayesnet::Metrics::getScoresKBest() const - 48 + 16 bayesnet::Metrics::maximumSpanningTree(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, at::Tensor const&, int) - 174 + 58 bayesnet::Metrics::mutualInformation(at::Tensor const&, at::Tensor const&, at::Tensor const&) - 44793 + 14836 diff --git a/html/bayesnet/utils/BayesMetrics.cc.gcov.html b/html/bayesnet/utils/BayesMetrics.cc.gcov.html index b2453fb..e2b668a 100644 --- a/html/bayesnet/utils/BayesMetrics.cc.gcov.html +++ b/html/bayesnet/utils/BayesMetrics.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,156 +70,156 @@ 8 : #include "BayesMetrics.h" 9 : namespace bayesnet { 10 : //samples is n+1xm tensor used to fit the model - 11 2248 : Metrics::Metrics(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int classNumStates) - 12 2248 : : samples(samples) - 13 2248 : , className(className) - 14 2248 : , features(features) - 15 2248 : , classNumStates(classNumStates) + 11 744 : Metrics::Metrics(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int classNumStates) + 12 744 : : samples(samples) + 13 744 : , className(className) + 14 744 : , features(features) + 15 744 : , classNumStates(classNumStates) 16 : { - 17 2248 : } + 17 744 : } 18 : //samples is n+1xm std::vector used to fit the model - 19 96 : Metrics::Metrics(const std::vector<std::vector<int>>& vsamples, const std::vector<int>& labels, const std::vector<std::string>& features, const std::string& className, const int classNumStates) - 20 96 : : samples(torch::zeros({ static_cast<int>(vsamples.size() + 1), static_cast<int>(vsamples[0].size()) }, torch::kInt32)) - 21 96 : , className(className) - 22 96 : , features(features) - 23 96 : , classNumStates(classNumStates) + 19 32 : Metrics::Metrics(const std::vector<std::vector<int>>& vsamples, const std::vector<int>& labels, const std::vector<std::string>& features, const std::string& className, const int classNumStates) + 20 32 : : samples(torch::zeros({ static_cast<int>(vsamples.size() + 1), static_cast<int>(vsamples[0].size()) }, torch::kInt32)) + 21 32 : , className(className) + 22 32 : , features(features) + 23 32 : , classNumStates(classNumStates) 24 : { - 25 768 : for (int i = 0; i < vsamples.size(); ++i) { - 26 2688 : samples.index_put_({ i, "..." }, torch::tensor(vsamples[i], torch::kInt32)); + 25 256 : for (int i = 0; i < vsamples.size(); ++i) { + 26 896 : samples.index_put_({ i, "..." }, torch::tensor(vsamples[i], torch::kInt32)); 27 : } - 28 384 : samples.index_put_({ -1, "..." }, torch::tensor(labels, torch::kInt32)); - 29 864 : } - 30 690 : std::vector<int> Metrics::SelectKBestWeighted(const torch::Tensor& weights, bool ascending, unsigned k) + 28 128 : samples.index_put_({ -1, "..." }, torch::tensor(labels, torch::kInt32)); + 29 288 : } + 30 230 : std::vector<int> Metrics::SelectKBestWeighted(const torch::Tensor& weights, bool ascending, unsigned k) 31 : { 32 : // Return the K Best features - 33 690 : auto n = features.size(); - 34 690 : if (k == 0) { + 33 230 : auto n = features.size(); + 34 230 : if (k == 0) { 35 0 : k = n; 36 : } 37 : // compute scores - 38 690 : scoresKBest.clear(); - 39 690 : featuresKBest.clear(); - 40 2070 : auto label = samples.index({ -1, "..." }); - 41 15576 : for (int i = 0; i < n; ++i) { - 42 44658 : scoresKBest.push_back(mutualInformation(label, samples.index({ i, "..." }), weights)); - 43 14886 : featuresKBest.push_back(i); + 38 230 : scoresKBest.clear(); + 39 230 : featuresKBest.clear(); + 40 690 : auto label = samples.index({ -1, "..." }); + 41 5192 : for (int i = 0; i < n; ++i) { + 42 14886 : scoresKBest.push_back(mutualInformation(label, samples.index({ i, "..." }), weights)); + 43 4962 : featuresKBest.push_back(i); 44 : } 45 : // sort & reduce scores and features - 46 690 : if (ascending) { - 47 114 : sort(featuresKBest.begin(), featuresKBest.end(), [&](int i, int j) - 48 2718 : { return scoresKBest[i] < scoresKBest[j]; }); - 49 114 : sort(scoresKBest.begin(), scoresKBest.end(), std::less<double>()); - 50 114 : if (k < n) { - 51 168 : for (int i = 0; i < n - k; ++i) { - 52 120 : featuresKBest.erase(featuresKBest.begin()); - 53 120 : scoresKBest.erase(scoresKBest.begin()); + 46 230 : if (ascending) { + 47 38 : sort(featuresKBest.begin(), featuresKBest.end(), [&](int i, int j) + 48 906 : { return scoresKBest[i] < scoresKBest[j]; }); + 49 38 : sort(scoresKBest.begin(), scoresKBest.end(), std::less<double>()); + 50 38 : if (k < n) { + 51 56 : for (int i = 0; i < n - k; ++i) { + 52 40 : featuresKBest.erase(featuresKBest.begin()); + 53 40 : scoresKBest.erase(scoresKBest.begin()); 54 : } 55 : } 56 : } else { - 57 576 : sort(featuresKBest.begin(), featuresKBest.end(), [&](int i, int j) - 58 97212 : { return scoresKBest[i] > scoresKBest[j]; }); - 59 576 : sort(scoresKBest.begin(), scoresKBest.end(), std::greater<double>()); - 60 576 : featuresKBest.resize(k); - 61 576 : scoresKBest.resize(k); + 57 192 : sort(featuresKBest.begin(), featuresKBest.end(), [&](int i, int j) + 58 32404 : { return scoresKBest[i] > scoresKBest[j]; }); + 59 192 : sort(scoresKBest.begin(), scoresKBest.end(), std::greater<double>()); + 60 192 : featuresKBest.resize(k); + 61 192 : scoresKBest.resize(k); 62 : } - 63 1380 : return featuresKBest; - 64 16266 : } - 65 48 : std::vector<double> Metrics::getScoresKBest() const + 63 460 : return featuresKBest; + 64 5422 : } + 65 16 : std::vector<double> Metrics::getScoresKBest() const 66 : { - 67 48 : return scoresKBest; + 67 16 : return scoresKBest; 68 : } 69 : - 70 204 : torch::Tensor Metrics::conditionalEdge(const torch::Tensor& weights) + 70 68 : torch::Tensor Metrics::conditionalEdge(const torch::Tensor& weights) 71 : { - 72 204 : auto result = std::vector<double>(); - 73 204 : auto source = std::vector<std::string>(features); - 74 204 : source.push_back(className); - 75 204 : auto combinations = doCombinations(source); + 72 68 : auto result = std::vector<double>(); + 73 68 : auto source = std::vector<std::string>(features); + 74 68 : source.push_back(className); + 75 68 : auto combinations = doCombinations(source); 76 : // Compute class prior - 77 204 : auto margin = torch::zeros({ classNumStates }, torch::kFloat); - 78 1104 : for (int value = 0; value < classNumStates; ++value) { - 79 3600 : auto mask = samples.index({ -1, "..." }) == value; - 80 900 : margin[value] = mask.sum().item<double>() / samples.size(1); - 81 900 : } - 82 5508 : for (auto [first, second] : combinations) { - 83 5304 : int index_first = find(features.begin(), features.end(), first) - features.begin(); - 84 5304 : int index_second = find(features.begin(), features.end(), second) - features.begin(); - 85 5304 : double accumulated = 0; - 86 31440 : for (int value = 0; value < classNumStates; ++value) { - 87 104544 : auto mask = samples.index({ -1, "..." }) == value; - 88 78408 : auto first_dataset = samples.index({ index_first, mask }); - 89 78408 : auto second_dataset = samples.index({ index_second, mask }); - 90 52272 : auto weights_dataset = weights.index({ mask }); - 91 52272 : auto mi = mutualInformation(first_dataset, second_dataset, weights_dataset); - 92 26136 : auto pb = margin[value].item<double>(); - 93 26136 : accumulated += pb * mi; - 94 26136 : } - 95 5304 : result.push_back(accumulated); - 96 5304 : } - 97 204 : long n_vars = source.size(); - 98 204 : auto matrix = torch::zeros({ n_vars, n_vars }); - 99 204 : auto indices = torch::triu_indices(n_vars, n_vars, 1); - 100 5508 : for (auto i = 0; i < result.size(); ++i) { - 101 5304 : auto x = indices[0][i]; - 102 5304 : auto y = indices[1][i]; - 103 5304 : matrix[x][y] = result[i]; - 104 5304 : matrix[y][x] = result[i]; - 105 5304 : } - 106 408 : return matrix; - 107 131784 : } - 108 50295 : double Metrics::entropy(const torch::Tensor& feature, const torch::Tensor& weights) + 77 68 : auto margin = torch::zeros({ classNumStates }, torch::kFloat); + 78 368 : for (int value = 0; value < classNumStates; ++value) { + 79 1200 : auto mask = samples.index({ -1, "..." }) == value; + 80 300 : margin[value] = mask.sum().item<double>() / samples.size(1); + 81 300 : } + 82 1836 : for (auto [first, second] : combinations) { + 83 1768 : int index_first = find(features.begin(), features.end(), first) - features.begin(); + 84 1768 : int index_second = find(features.begin(), features.end(), second) - features.begin(); + 85 1768 : double accumulated = 0; + 86 10480 : for (int value = 0; value < classNumStates; ++value) { + 87 34848 : auto mask = samples.index({ -1, "..." }) == value; + 88 26136 : auto first_dataset = samples.index({ index_first, mask }); + 89 26136 : auto second_dataset = samples.index({ index_second, mask }); + 90 17424 : auto weights_dataset = weights.index({ mask }); + 91 17424 : auto mi = mutualInformation(first_dataset, second_dataset, weights_dataset); + 92 8712 : auto pb = margin[value].item<double>(); + 93 8712 : accumulated += pb * mi; + 94 8712 : } + 95 1768 : result.push_back(accumulated); + 96 1768 : } + 97 68 : long n_vars = source.size(); + 98 68 : auto matrix = torch::zeros({ n_vars, n_vars }); + 99 68 : auto indices = torch::triu_indices(n_vars, n_vars, 1); + 100 1836 : for (auto i = 0; i < result.size(); ++i) { + 101 1768 : auto x = indices[0][i]; + 102 1768 : auto y = indices[1][i]; + 103 1768 : matrix[x][y] = result[i]; + 104 1768 : matrix[y][x] = result[i]; + 105 1768 : } + 106 136 : return matrix; + 107 43928 : } + 108 16480 : double Metrics::entropy(const torch::Tensor& feature, const torch::Tensor& weights) 109 : { - 110 50295 : torch::Tensor counts = feature.bincount(weights); - 111 50295 : double totalWeight = counts.sum().item<double>(); - 112 50295 : torch::Tensor probs = counts.to(torch::kFloat) / totalWeight; - 113 50295 : torch::Tensor logProbs = torch::log(probs); - 114 50295 : torch::Tensor entropy = -probs * logProbs; - 115 100590 : return entropy.nansum().item<double>(); - 116 50295 : } + 110 16480 : torch::Tensor counts = feature.bincount(weights); + 111 16480 : double totalWeight = counts.sum().item<double>(); + 112 16480 : torch::Tensor probs = counts.to(torch::kFloat) / totalWeight; + 113 16480 : torch::Tensor logProbs = torch::log(probs); + 114 16480 : torch::Tensor entropy = -probs * logProbs; + 115 32960 : return entropy.nansum().item<double>(); + 116 16480 : } 117 : // H(Y|X) = sum_{x in X} p(x) H(Y|X=x) - 118 44793 : double Metrics::conditionalEntropy(const torch::Tensor& firstFeature, const torch::Tensor& secondFeature, const torch::Tensor& weights) + 118 14836 : double Metrics::conditionalEntropy(const torch::Tensor& firstFeature, const torch::Tensor& secondFeature, const torch::Tensor& weights) 119 : { - 120 44793 : int numSamples = firstFeature.sizes()[0]; - 121 44793 : torch::Tensor featureCounts = secondFeature.bincount(weights); - 122 44793 : std::unordered_map<int, std::unordered_map<int, double>> jointCounts; - 123 44793 : double totalWeight = 0; - 124 8954403 : for (auto i = 0; i < numSamples; i++) { - 125 8909610 : jointCounts[secondFeature[i].item<int>()][firstFeature[i].item<int>()] += weights[i].item<double>(); - 126 8909610 : totalWeight += weights[i].item<float>(); + 120 14836 : int numSamples = firstFeature.sizes()[0]; + 121 14836 : torch::Tensor featureCounts = secondFeature.bincount(weights); + 122 14836 : std::unordered_map<int, std::unordered_map<int, double>> jointCounts; + 123 14836 : double totalWeight = 0; + 124 2946924 : for (auto i = 0; i < numSamples; i++) { + 125 2932088 : jointCounts[secondFeature[i].item<int>()][firstFeature[i].item<int>()] += weights[i].item<double>(); + 126 2932088 : totalWeight += weights[i].item<float>(); 127 : } - 128 44793 : if (totalWeight == 0) + 128 14836 : if (totalWeight == 0) 129 0 : return 0; - 130 44793 : double entropyValue = 0; - 131 222747 : for (int value = 0; value < featureCounts.sizes()[0]; ++value) { - 132 177954 : double p_f = featureCounts[value].item<double>() / totalWeight; - 133 177954 : double entropy_f = 0; - 134 601680 : for (auto& [label, jointCount] : jointCounts[value]) { - 135 423726 : double p_l_f = jointCount / featureCounts[value].item<double>(); - 136 423726 : if (p_l_f > 0) { - 137 423726 : entropy_f -= p_l_f * log(p_l_f); + 130 14836 : double entropyValue = 0; + 131 73754 : for (int value = 0; value < featureCounts.sizes()[0]; ++value) { + 132 58918 : double p_f = featureCounts[value].item<double>() / totalWeight; + 133 58918 : double entropy_f = 0; + 134 198966 : for (auto& [label, jointCount] : jointCounts[value]) { + 135 140048 : double p_l_f = jointCount / featureCounts[value].item<double>(); + 136 140048 : if (p_l_f > 0) { + 137 140048 : entropy_f -= p_l_f * log(p_l_f); 138 : } else { 139 0 : entropy_f = 0; 140 : } 141 : } - 142 177954 : entropyValue += p_f * entropy_f; + 142 58918 : entropyValue += p_f * entropy_f; 143 : } - 144 44793 : return entropyValue; - 145 44793 : } + 144 14836 : return entropyValue; + 145 14836 : } 146 : // I(X;Y) = H(Y) - H(Y|X) - 147 44793 : double Metrics::mutualInformation(const torch::Tensor& firstFeature, const torch::Tensor& secondFeature, const torch::Tensor& weights) + 147 14836 : double Metrics::mutualInformation(const torch::Tensor& firstFeature, const torch::Tensor& secondFeature, const torch::Tensor& weights) 148 : { - 149 44793 : return entropy(firstFeature, weights) - conditionalEntropy(firstFeature, secondFeature, weights); + 149 14836 : return entropy(firstFeature, weights) - conditionalEntropy(firstFeature, secondFeature, weights); 150 : } 151 : /* 152 : Compute the maximum spanning tree considering the weights as distances 153 : and the indices of the weights as nodes of this square matrix using 154 : Kruskal algorithm 155 : */ - 156 174 : std::vector<std::pair<int, int>> Metrics::maximumSpanningTree(const std::vector<std::string>& features, const torch::Tensor& weights, const int root) + 156 58 : std::vector<std::pair<int, int>> Metrics::maximumSpanningTree(const std::vector<std::string>& features, const torch::Tensor& weights, const int root) 157 : { - 158 174 : auto mst = MST(features, weights, root); - 159 348 : return mst.maximumSpanningTree(); - 160 174 : } + 158 58 : auto mst = MST(features, weights, root); + 159 116 : return mst.maximumSpanningTree(); + 160 58 : } 161 : } diff --git a/html/bayesnet/utils/BayesMetrics.h.func-c.html b/html/bayesnet/utils/BayesMetrics.h.func-c.html index e6c7ed6..ad15cfb 100644 --- a/html/bayesnet/utils/BayesMetrics.h.func-c.html +++ b/html/bayesnet/utils/BayesMetrics.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,35 +65,35 @@ int bayesnet::Metrics::pop_first<int>(std::vector<int, std::allocator<int> >&) - 68 + 20 std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > bayesnet::Metrics::doCombinations<int>(std::vector<int, std::allocator<int> > const&) - 1251 + 384 std::vector, std::allocator >, std::__cxx11::basic_string, std::allocator > >, std::allocator, std::allocator >, std::__cxx11::basic_string, std::allocator > > > > bayesnet::Metrics::doCombinations, std::allocator > >(std::vector, std::allocator >, std::allocator, std::allocator > > > const&) - 204 + 68 std::vector, std::allocator > > bayesnet::Metrics::doCombinations(std::vector > const&) - 1047 + 316 bayesnet::Metrics::Metrics() - 2658 + 886 diff --git a/html/bayesnet/utils/BayesMetrics.h.func.html b/html/bayesnet/utils/BayesMetrics.h.func.html index 3f215b7..2d4b6e9 100644 --- a/html/bayesnet/utils/BayesMetrics.h.func.html +++ b/html/bayesnet/utils/BayesMetrics.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,35 +65,35 @@ bayesnet::Metrics::Metrics() - 2658 + 886 int bayesnet::Metrics::pop_first<int>(std::vector<int, std::allocator<int> >&) - 68 + 20 std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > bayesnet::Metrics::doCombinations<int>(std::vector<int, std::allocator<int> > const&) - 1251 + 384 std::vector, std::allocator > > bayesnet::Metrics::doCombinations(std::vector > const&) - 1047 + 316 std::vector, std::allocator >, std::__cxx11::basic_string, std::allocator > >, std::allocator, std::allocator >, std::__cxx11::basic_string, std::allocator > > > > bayesnet::Metrics::doCombinations, std::allocator > >(std::vector, std::allocator >, std::allocator, std::allocator > > > const&) - 204 + 68 diff --git a/html/bayesnet/utils/BayesMetrics.h.gcov.html b/html/bayesnet/utils/BayesMetrics.h.gcov.html index 2c56556..e541368 100644 --- a/html/bayesnet/utils/BayesMetrics.h.gcov.html +++ b/html/bayesnet/utils/BayesMetrics.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -74,7 +74,7 @@ 12 : namespace bayesnet { 13 : class Metrics { 14 : public: - 15 2658 : Metrics() = default; + 15 886 : Metrics() = default; 16 : Metrics(const torch::Tensor& samples, const std::vector<std::string>& features, const std::string& className, const int classNumStates); 17 : Metrics(const std::vector<std::vector<int>>& vsamples, const std::vector<int>& labels, const std::vector<std::string>& features, const std::string& className, const int classNumStates); 18 : std::vector<int> SelectKBestWeighted(const torch::Tensor& weights, bool ascending = false, unsigned k = 0); @@ -88,23 +88,23 @@ 26 : double entropy(const torch::Tensor& feature, const torch::Tensor& weights); 27 : std::vector<std::string> features; 28 : template <class T> - 29 1251 : std::vector<std::pair<T, T>> doCombinations(const std::vector<T>& source) + 29 384 : std::vector<std::pair<T, T>> doCombinations(const std::vector<T>& source) 30 : { - 31 1251 : std::vector<std::pair<T, T>> result; - 32 6532 : for (int i = 0; i < source.size(); ++i) { - 33 5281 : T temp = source[i]; - 34 16445 : for (int j = i + 1; j < source.size(); ++j) { - 35 11164 : result.push_back({ temp, source[j] }); + 31 384 : std::vector<std::pair<T, T>> result; + 32 2026 : for (int i = 0; i < source.size(); ++i) { + 33 1642 : T temp = source[i]; + 34 5180 : for (int j = i + 1; j < source.size(); ++j) { + 35 3538 : result.push_back({ temp, source[j] }); 36 : } 37 : } - 38 1251 : return result; + 38 384 : return result; 39 0 : } 40 : template <class T> - 41 68 : T pop_first(std::vector<T>& v) + 41 20 : T pop_first(std::vector<T>& v) 42 : { - 43 68 : T temp = v[0]; - 44 68 : v.erase(v.begin()); - 45 68 : return temp; + 43 20 : T temp = v[0]; + 44 20 : v.erase(v.begin()); + 45 20 : return temp; 46 : } 47 : private: 48 : int classNumStates = 0; diff --git a/html/bayesnet/utils/Mst.cc.func-c.html b/html/bayesnet/utils/Mst.cc.func-c.html index c6d2865..db26ebb 100644 --- a/html/bayesnet/utils/Mst.cc.func-c.html +++ b/html/bayesnet/utils/Mst.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,70 +65,70 @@ bayesnet::Graph::Graph(int) - 174 + 58 bayesnet::Graph::kruskal_algorithm() - 174 + 58 bayesnet::MST::MST(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, at::Tensor const&, int) - 174 + 58 bayesnet::MST::maximumSpanningTree() - 174 + 58 bayesnet::reorder(std::vector<std::pair<float, std::pair<int, int> >, std::allocator<std::pair<float, std::pair<int, int> > > >, int) - 174 + 58 bayesnet::Graph::union_set(int, int) - 954 + 318 bayesnet::insertElement(std::__cxx11::list<int, std::allocator<int> >&, int) - 954 + 318 bayesnet::Graph::addEdge(int, int, float) - 3456 + 1152 auto bayesnet::Graph::kruskal_algorithm()::{lambda(auto:1 const&, auto:2 const&)#1}::operator()<std::pair<float, std::pair<int, int> >, std::pair<float, std::pair<int, int> > >(std::pair<float, std::pair<int, int> > const&, std::pair<float, std::pair<int, int> > const&) const - 13278 + 4426 bayesnet::Graph::find_set(int) - 15978 + 5326 diff --git a/html/bayesnet/utils/Mst.cc.func.html b/html/bayesnet/utils/Mst.cc.func.html index e5770b6..578ab90 100644 --- a/html/bayesnet/utils/Mst.cc.func.html +++ b/html/bayesnet/utils/Mst.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,70 +65,70 @@ auto bayesnet::Graph::kruskal_algorithm()::{lambda(auto:1 const&, auto:2 const&)#1}::operator()<std::pair<float, std::pair<int, int> >, std::pair<float, std::pair<int, int> > >(std::pair<float, std::pair<int, int> > const&, std::pair<float, std::pair<int, int> > const&) const - 13278 + 4426 bayesnet::Graph::Graph(int) - 174 + 58 bayesnet::Graph::addEdge(int, int, float) - 3456 + 1152 bayesnet::Graph::find_set(int) - 15978 + 5326 bayesnet::Graph::kruskal_algorithm() - 174 + 58 bayesnet::Graph::union_set(int, int) - 954 + 318 bayesnet::MST::MST(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, at::Tensor const&, int) - 174 + 58 bayesnet::MST::maximumSpanningTree() - 174 + 58 bayesnet::insertElement(std::__cxx11::list<int, std::allocator<int> >&, int) - 954 + 318 bayesnet::reorder(std::vector<std::pair<float, std::pair<int, int> >, std::allocator<std::pair<float, std::pair<int, int> > > >, int) - 174 + 58 diff --git a/html/bayesnet/utils/Mst.cc.gcov.html b/html/bayesnet/utils/Mst.cc.gcov.html index fb11c90..5b0a5c8 100644 --- a/html/bayesnet/utils/Mst.cc.gcov.html +++ b/html/bayesnet/utils/Mst.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -76,108 +76,108 @@ 14 : */ 15 : 16 : namespace bayesnet { - 17 348 : Graph::Graph(int V) : V(V), parent(std::vector<int>(V)) + 17 116 : Graph::Graph(int V) : V(V), parent(std::vector<int>(V)) 18 : { - 19 1302 : for (int i = 0; i < V; i++) - 20 1128 : parent[i] = i; - 21 174 : G.clear(); - 22 174 : T.clear(); - 23 174 : } - 24 3456 : void Graph::addEdge(int u, int v, float wt) + 19 434 : for (int i = 0; i < V; i++) + 20 376 : parent[i] = i; + 21 58 : G.clear(); + 22 58 : T.clear(); + 23 58 : } + 24 1152 : void Graph::addEdge(int u, int v, float wt) 25 : { - 26 3456 : G.push_back({ wt, { u, v } }); - 27 3456 : } - 28 15978 : int Graph::find_set(int i) + 26 1152 : G.push_back({ wt, { u, v } }); + 27 1152 : } + 28 5326 : int Graph::find_set(int i) 29 : { 30 : // If i is the parent of itself - 31 15978 : if (i == parent[i]) - 32 6912 : return i; + 31 5326 : if (i == parent[i]) + 32 2304 : return i; 33 : else 34 : //else recursively find the parent of i - 35 9066 : return find_set(parent[i]); + 35 3022 : return find_set(parent[i]); 36 : } - 37 954 : void Graph::union_set(int u, int v) + 37 318 : void Graph::union_set(int u, int v) 38 : { - 39 954 : parent[u] = parent[v]; - 40 954 : } - 41 174 : void Graph::kruskal_algorithm() + 39 318 : parent[u] = parent[v]; + 40 318 : } + 41 58 : void Graph::kruskal_algorithm() 42 : { 43 : // sort the edges ordered on decreasing weight - 44 13452 : stable_sort(G.begin(), G.end(), [](const auto& left, const auto& right) {return left.first > right.first;}); - 45 3630 : for (int i = 0; i < G.size(); i++) { + 44 4484 : stable_sort(G.begin(), G.end(), [](const auto& left, const auto& right) {return left.first > right.first;}); + 45 1210 : for (int i = 0; i < G.size(); i++) { 46 : int uSt, vEd; - 47 3456 : uSt = find_set(G[i].second.first); - 48 3456 : vEd = find_set(G[i].second.second); - 49 3456 : if (uSt != vEd) { - 50 954 : T.push_back(G[i]); // add to mst std::vector - 51 954 : union_set(uSt, vEd); + 47 1152 : uSt = find_set(G[i].second.first); + 48 1152 : vEd = find_set(G[i].second.second); + 49 1152 : if (uSt != vEd) { + 50 318 : T.push_back(G[i]); // add to mst std::vector + 51 318 : union_set(uSt, vEd); 52 : } 53 : } - 54 174 : } + 54 58 : } 55 : - 56 954 : void insertElement(std::list<int>& variables, int variable) + 56 318 : void insertElement(std::list<int>& variables, int variable) 57 : { - 58 954 : if (std::find(variables.begin(), variables.end(), variable) == variables.end()) { - 59 954 : variables.push_front(variable); + 58 318 : if (std::find(variables.begin(), variables.end(), variable) == variables.end()) { + 59 318 : variables.push_front(variable); 60 : } - 61 954 : } + 61 318 : } 62 : - 63 174 : std::vector<std::pair<int, int>> reorder(std::vector<std::pair<float, std::pair<int, int>>> T, int root_original) + 63 58 : std::vector<std::pair<int, int>> reorder(std::vector<std::pair<float, std::pair<int, int>>> T, int root_original) 64 : { 65 : // Create the edges of a DAG from the MST 66 : // replacing unordered_set with list because unordered_set cannot guarantee the order of the elements inserted - 67 174 : auto result = std::vector<std::pair<int, int>>(); - 68 174 : auto visited = std::vector<int>(); - 69 174 : auto nextVariables = std::list<int>(); - 70 174 : nextVariables.push_front(root_original); - 71 1302 : while (nextVariables.size() > 0) { - 72 1128 : int root = nextVariables.front(); - 73 1128 : nextVariables.pop_front(); - 74 3984 : for (int i = 0; i < T.size(); ++i) { - 75 2856 : auto [weight, edge] = T[i]; - 76 2856 : auto [from, to] = edge; - 77 2856 : if (from == root || to == root) { - 78 954 : visited.insert(visited.begin(), i); - 79 954 : if (from == root) { - 80 636 : result.push_back({ from, to }); - 81 636 : insertElement(nextVariables, to); + 67 58 : auto result = std::vector<std::pair<int, int>>(); + 68 58 : auto visited = std::vector<int>(); + 69 58 : auto nextVariables = std::list<int>(); + 70 58 : nextVariables.push_front(root_original); + 71 434 : while (nextVariables.size() > 0) { + 72 376 : int root = nextVariables.front(); + 73 376 : nextVariables.pop_front(); + 74 1328 : for (int i = 0; i < T.size(); ++i) { + 75 952 : auto [weight, edge] = T[i]; + 76 952 : auto [from, to] = edge; + 77 952 : if (from == root || to == root) { + 78 318 : visited.insert(visited.begin(), i); + 79 318 : if (from == root) { + 80 212 : result.push_back({ from, to }); + 81 212 : insertElement(nextVariables, to); 82 : } else { - 83 318 : result.push_back({ to, from }); - 84 318 : insertElement(nextVariables, from); + 83 106 : result.push_back({ to, from }); + 84 106 : insertElement(nextVariables, from); 85 : } 86 : } 87 : } 88 : // Remove visited - 89 2082 : for (int i = 0; i < visited.size(); ++i) { - 90 954 : T.erase(T.begin() + visited[i]); + 89 694 : for (int i = 0; i < visited.size(); ++i) { + 90 318 : T.erase(T.begin() + visited[i]); 91 : } - 92 1128 : visited.clear(); + 92 376 : visited.clear(); 93 : } - 94 174 : if (T.size() > 0) { + 94 58 : if (T.size() > 0) { 95 0 : for (int i = 0; i < T.size(); ++i) { 96 0 : auto [weight, edge] = T[i]; 97 0 : auto [from, to] = edge; 98 0 : result.push_back({ from, to }); 99 : } 100 : } - 101 348 : return result; - 102 174 : } + 101 116 : return result; + 102 58 : } 103 : - 104 174 : MST::MST(const std::vector<std::string>& features, const torch::Tensor& weights, const int root) : features(features), weights(weights), root(root) {} - 105 174 : std::vector<std::pair<int, int>> MST::maximumSpanningTree() + 104 58 : MST::MST(const std::vector<std::string>& features, const torch::Tensor& weights, const int root) : features(features), weights(weights), root(root) {} + 105 58 : std::vector<std::pair<int, int>> MST::maximumSpanningTree() 106 : { - 107 174 : auto num_features = features.size(); - 108 174 : Graph g(num_features); + 107 58 : auto num_features = features.size(); + 108 58 : Graph g(num_features); 109 : // Make a complete graph - 110 1128 : for (int i = 0; i < num_features - 1; ++i) { - 111 4410 : for (int j = i + 1; j < num_features; ++j) { - 112 3456 : g.addEdge(i, j, weights[i][j].item<float>()); + 110 376 : for (int i = 0; i < num_features - 1; ++i) { + 111 1470 : for (int j = i + 1; j < num_features; ++j) { + 112 1152 : g.addEdge(i, j, weights[i][j].item<float>()); 113 : } 114 : } - 115 174 : g.kruskal_algorithm(); - 116 174 : auto mst = g.get_mst(); - 117 348 : return reorder(mst, root); - 118 174 : } + 115 58 : g.kruskal_algorithm(); + 116 58 : auto mst = g.get_mst(); + 117 116 : return reorder(mst, root); + 118 58 : } 119 : 120 : } diff --git a/html/bayesnet/utils/Mst.h.func-c.html b/html/bayesnet/utils/Mst.h.func-c.html index 9706ec4..c4a09f2 100644 --- a/html/bayesnet/utils/Mst.h.func-c.html +++ b/html/bayesnet/utils/Mst.h.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::Graph::get_mst() - 174 + 58 diff --git a/html/bayesnet/utils/Mst.h.func.html b/html/bayesnet/utils/Mst.h.func.html index cde5717..6ceb4e9 100644 --- a/html/bayesnet/utils/Mst.h.func.html +++ b/html/bayesnet/utils/Mst.h.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,7 +65,7 @@ bayesnet::Graph::get_mst() - 174 + 58 diff --git a/html/bayesnet/utils/Mst.h.gcov.html b/html/bayesnet/utils/Mst.h.gcov.html index e253982..a4fa97f 100644 --- a/html/bayesnet/utils/Mst.h.gcov.html +++ b/html/bayesnet/utils/Mst.h.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -89,7 +89,7 @@ 27 : int find_set(int i); 28 : void union_set(int u, int v); 29 : void kruskal_algorithm(); - 30 174 : std::vector <std::pair<float, std::pair<int, int>>> get_mst() { return T; } + 30 58 : std::vector <std::pair<float, std::pair<int, int>>> get_mst() { return T; } 31 : private: 32 : int V; // number of nodes in graph 33 : std::vector <std::pair<float, std::pair<int, int>>> G; // std::vector for graph diff --git a/html/bayesnet/utils/bayesnetUtils.cc.func-c.html b/html/bayesnet/utils/bayesnetUtils.cc.func-c.html index 5042e0e..7d80a60 100644 --- a/html/bayesnet/utils/bayesnetUtils.cc.func-c.html +++ b/html/bayesnet/utils/bayesnetUtils.cc.func-c.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::tensorToVectorDouble(at::Tensor&) - 42 + 14 bayesnet::vectorToTensor(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool) - 54 + 18 bayesnet::argsort(std::vector<double, std::allocator<double> >&) - 186 + 58 bayesnet::argsort(std::vector<double, std::allocator<double> >&)::{lambda(int, int)#1}::operator()(int, int) const - 3630 + 1134 diff --git a/html/bayesnet/utils/bayesnetUtils.cc.func.html b/html/bayesnet/utils/bayesnetUtils.cc.func.html index ac17db7..95e5984 100644 --- a/html/bayesnet/utils/bayesnetUtils.cc.func.html +++ b/html/bayesnet/utils/bayesnetUtils.cc.func.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -65,28 +65,28 @@ bayesnet::argsort(std::vector<double, std::allocator<double> >&) - 186 + 58 bayesnet::argsort(std::vector<double, std::allocator<double> >&)::{lambda(int, int)#1}::operator()(int, int) const - 3630 + 1134 bayesnet::tensorToVectorDouble(at::Tensor&) - 42 + 14 bayesnet::vectorToTensor(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, bool) - 54 + 18 diff --git a/html/bayesnet/utils/bayesnetUtils.cc.gcov.html b/html/bayesnet/utils/bayesnetUtils.cc.gcov.html index eab60f2..f647da2 100644 --- a/html/bayesnet/utils/bayesnetUtils.cc.gcov.html +++ b/html/bayesnet/utils/bayesnetUtils.cc.gcov.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % @@ -70,38 +70,38 @@ 8 : #include "bayesnetUtils.h" 9 : namespace bayesnet { 10 : // Return the indices in descending order - 11 186 : std::vector<int> argsort(std::vector<double>& nums) + 11 58 : std::vector<int> argsort(std::vector<double>& nums) 12 : { - 13 186 : int n = nums.size(); - 14 186 : std::vector<int> indices(n); - 15 186 : iota(indices.begin(), indices.end(), 0); - 16 3816 : sort(indices.begin(), indices.end(), [&nums](int i, int j) {return nums[i] > nums[j];}); - 17 186 : return indices; + 13 58 : int n = nums.size(); + 14 58 : std::vector<int> indices(n); + 15 58 : iota(indices.begin(), indices.end(), 0); + 16 1192 : sort(indices.begin(), indices.end(), [&nums](int i, int j) {return nums[i] > nums[j];}); + 17 58 : return indices; 18 0 : } - 19 42 : std::vector<std::vector<double>> tensorToVectorDouble(torch::Tensor& dtensor) + 19 14 : std::vector<std::vector<double>> tensorToVectorDouble(torch::Tensor& dtensor) 20 : { 21 : // convert mxn tensor to mxn std::vector - 22 42 : std::vector<std::vector<double>> result; + 22 14 : std::vector<std::vector<double>> result; 23 : // Iterate over cols - 24 10818 : for (int i = 0; i < dtensor.size(0); ++i) { - 25 32328 : auto col_tensor = dtensor.index({ i, "..." }); - 26 10776 : auto col = std::vector<double>(col_tensor.data_ptr<float>(), col_tensor.data_ptr<float>() + dtensor.size(1)); - 27 10776 : result.push_back(col); - 28 10776 : } - 29 42 : return result; - 30 10776 : } - 31 54 : torch::Tensor vectorToTensor(std::vector<std::vector<int>>& vector, bool transpose) + 24 3606 : for (int i = 0; i < dtensor.size(0); ++i) { + 25 10776 : auto col_tensor = dtensor.index({ i, "..." }); + 26 3592 : auto col = std::vector<double>(col_tensor.data_ptr<float>(), col_tensor.data_ptr<float>() + dtensor.size(1)); + 27 3592 : result.push_back(col); + 28 3592 : } + 29 14 : return result; + 30 3592 : } + 31 18 : torch::Tensor vectorToTensor(std::vector<std::vector<int>>& vector, bool transpose) 32 : { 33 : // convert nxm std::vector to mxn tensor if transpose - 34 54 : long int m = transpose ? vector[0].size() : vector.size(); - 35 54 : long int n = transpose ? vector.size() : vector[0].size(); - 36 54 : auto tensor = torch::zeros({ m, n }, torch::kInt32); - 37 354 : for (int i = 0; i < m; ++i) { - 38 74886 : for (int j = 0; j < n; ++j) { - 39 74586 : tensor[i][j] = transpose ? vector[j][i] : vector[i][j]; + 34 18 : long int m = transpose ? vector[0].size() : vector.size(); + 35 18 : long int n = transpose ? vector.size() : vector[0].size(); + 36 18 : auto tensor = torch::zeros({ m, n }, torch::kInt32); + 37 118 : for (int i = 0; i < m; ++i) { + 38 24962 : for (int j = 0; j < n; ++j) { + 39 24862 : tensor[i][j] = transpose ? vector[j][i] : vector[i][j]; 40 : } 41 : } - 42 54 : return tensor; + 42 18 : return tensor; 43 0 : } 44 : } diff --git a/html/bayesnet/utils/index-sort-f.html b/html/bayesnet/utils/index-sort-f.html index 31ce615..7b3c439 100644 --- a/html/bayesnet/utils/index-sort-f.html +++ b/html/bayesnet/utils/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/utils/index-sort-l.html b/html/bayesnet/utils/index-sort-l.html index d333f50..dabab15 100644 --- a/html/bayesnet/utils/index-sort-l.html +++ b/html/bayesnet/utils/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/bayesnet/utils/index.html b/html/bayesnet/utils/index.html index ec69b1f..70714f2 100644 --- a/html/bayesnet/utils/index.html +++ b/html/bayesnet/utils/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/index-sort-f.html b/html/index-sort-f.html index 3aff0e5..2e50c68 100644 --- a/html/index-sort-f.html +++ b/html/index-sort-f.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/index-sort-l.html b/html/index-sort-l.html index 4fc8a21..fed2186 100644 --- a/html/index-sort-l.html +++ b/html/index-sort-l.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/html/index.html b/html/index.html index e10f486..ac4f871 100644 --- a/html/index.html +++ b/html/index.html @@ -37,7 +37,7 @@ Test Date: - 2024-04-30 13:59:18 + 2024-04-30 20:26:57 Functions: 100.0 % diff --git a/tests/lib/Files/ArffFiles.cc b/lib/Files/ArffFiles.cc similarity index 100% rename from tests/lib/Files/ArffFiles.cc rename to lib/Files/ArffFiles.cc diff --git a/tests/lib/Files/ArffFiles.h b/lib/Files/ArffFiles.h similarity index 100% rename from tests/lib/Files/ArffFiles.h rename to lib/Files/ArffFiles.h diff --git a/tests/lib/Files/CMakeLists.txt b/lib/Files/CMakeLists.txt similarity index 100% rename from tests/lib/Files/CMakeLists.txt rename to lib/Files/CMakeLists.txt diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a58fa12..1e116c0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,6 +1,6 @@ if(ENABLE_TESTING) include_directories( - ${BayesNet_SOURCE_DIR}/tests/lib/Files + ${BayesNet_SOURCE_DIR}/lib/Files ${BayesNet_SOURCE_DIR}/lib/folding ${BayesNet_SOURCE_DIR}/lib/mdlp ${BayesNet_SOURCE_DIR}/lib/json/include