From 5daf7cbd69e9f9d89a7b101e98debaa62c395977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Monta=C3=B1ana=20G=C3=B3mez?= Date: Sun, 23 Feb 2025 19:44:13 +0100 Subject: [PATCH] Create XBAODE classifier --- src/CMakeLists.txt | 4 ++ src/experimental_clfs/XA1DE.h | 6 +-- src/experimental_clfs/XBAODE.cpp | 90 ++++++++++++++++++++++++++++++++ src/experimental_clfs/XBAODE.h | 67 ++++++++++++++++++++++++ src/experimental_clfs/Xaode.hpp | 5 ++ src/main/Models.h | 1 + src/main/modelRegister.h | 78 +++++++++++++-------------- 7 files changed, 210 insertions(+), 41 deletions(-) create mode 100644 src/experimental_clfs/XBAODE.cpp create mode 100644 src/experimental_clfs/XBAODE.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b49299..41d0d91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,6 +26,7 @@ add_executable( reports/ReportExcel.cpp reports/ReportBase.cpp reports/ExcelFile.cpp results/Result.cpp experimental_clfs/XA1DE.cpp + experimental_clfs/XBAODE.cpp ) target_link_libraries(b_best Boost::boost "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}") @@ -38,6 +39,7 @@ add_executable(b_grid commands/b_grid.cpp ${grid_sources} reports/ReportConsole.cpp reports/ReportBase.cpp results/Result.cpp experimental_clfs/XA1DE.cpp + experimental_clfs/XBAODE.cpp ) target_link_libraries(b_grid ${MPI_CXX_LIBRARIES} "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy) @@ -48,6 +50,7 @@ add_executable(b_list commands/b_list.cpp reports/ReportExcel.cpp reports/ExcelFile.cpp reports/ReportBase.cpp reports/DatasetsExcel.cpp reports/DatasetsConsole.cpp reports/ReportsPaged.cpp results/Result.cpp results/ResultsDatasetExcel.cpp results/ResultsDataset.cpp results/ResultsDatasetConsole.cpp experimental_clfs/XA1DE.cpp + experimental_clfs/XBAODE.cpp ) target_link_libraries(b_list "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}") @@ -59,6 +62,7 @@ add_executable(b_main commands/b_main.cpp ${main_sources} reports/ReportConsole.cpp reports/ReportBase.cpp results/Result.cpp experimental_clfs/XA1DE.cpp + experimental_clfs/XBAODE.cpp ) target_link_libraries(b_main "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy) diff --git a/src/experimental_clfs/XA1DE.h b/src/experimental_clfs/XA1DE.h index 0a2e4c4..b4bd5ce 100644 --- a/src/experimental_clfs/XA1DE.h +++ b/src/experimental_clfs/XA1DE.h @@ -22,8 +22,6 @@ namespace platform { public: XA1DE(); virtual ~XA1DE() = default; - const std::string CLASSIFIER_NOT_FITTED = "Classifier has not been fitted"; - XA1DE& fit(std::vector>& X, std::vector& y, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) override; XA1DE& fit(torch::Tensor& X, torch::Tensor& y, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) override; XA1DE& fit(torch::Tensor& dataset, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) override; @@ -49,10 +47,12 @@ namespace platform { std::vector& getValidHyperparameters() { return validHyperparameters; } void setDebug(bool debug) { this->debug = debug; } std::vector graph(const std::string& title = "") const override { return {}; } + void set_active_parents(std::vector active_parents) { aode_.set_active_parents(active_parents); } protected: void trainModel(const torch::Tensor& weights, const bayesnet::Smoothing_t smoothing) override {}; private: + const std::string CLASSIFIER_NOT_FITTED = "Classifier has not been fitted"; inline void normalize_weights(int num_instances) { double sum = std::accumulate(weights_.begin(), weights_.end(), 0.0); @@ -74,7 +74,7 @@ namespace platform { bayesnet::status_t status = bayesnet::NORMAL; std::vector notes; bool use_threads = true; - std::string version = "0.9.7"; + std::string version = "1.0.0"; bool fitted = false; }; } diff --git a/src/experimental_clfs/XBAODE.cpp b/src/experimental_clfs/XBAODE.cpp new file mode 100644 index 0000000..b4a135d --- /dev/null +++ b/src/experimental_clfs/XBAODE.cpp @@ -0,0 +1,90 @@ +// *************************************************************** +// SPDX-FileCopyrightText: Copyright 2025 Ricardo Montañana Gómez +// SPDX-FileType: SOURCE +// SPDX-License-Identifier: MIT +// *************************************************************** + +#include "XBAODE.h" + +namespace platform { + XBAODE::XBAODE() : semaphore_{ CountingSemaphore::getInstance() } + { + } + XBAODE& XBAODE::fit(std::vector>& X, std::vector& y, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) + { + aode_.fit(X, y, features, className, states, smoothing); + fitted = true; + return *this; + } + std::vector> XBAODE::predict_proba(std::vector>& test_data) + { + return aode_.predict_proba_threads(test_data); + } + std::vector XBAODE::predict(std::vector>& test_data) + { + if (!fitted) { + throw std::logic_error(CLASSIFIER_NOT_FITTED); + } + return aode_.predict(test_data); + } + float XBAODE::score(std::vector>& test_data, std::vector& labels) + { + return aode_.score(test_data, labels); + } + + // + // statistics + // + int XBAODE::getNumberOfNodes() const + { + return aode_.getNumberOfNodes(); + } + int XBAODE::getNumberOfEdges() const + { + return aode_.getNumberOfEdges(); + } + int XBAODE::getNumberOfStates() const + { + return aode_.getNumberOfStates(); + } + int XBAODE::getClassNumStates() const + { + return aode_.getClassNumStates(); + } + + // + // Fit + // + // fit(std::vector>& X, std::vector& y, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) + XBAODE& XBAODE::fit(torch::Tensor& X, torch::Tensor& y, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) + { + aode_.fit(X, y, features, className, states, smoothing); + return *this; + } + XBAODE& XBAODE::fit(torch::Tensor& dataset, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) + { + aode_.fit(dataset, features, className, states, smoothing); + return *this; + } + XBAODE& XBAODE::fit(torch::Tensor& dataset, const std::vector& features, const std::string& className, std::map>& states, const torch::Tensor& weights, const bayesnet::Smoothing_t smoothing) + { + aode_.fit(dataset, features, className, states, weights, smoothing); + return *this; + } + // + // Predict + // + torch::Tensor XBAODE::predict(torch::Tensor& X) + { + return aode_.predict(X); + } + torch::Tensor XBAODE::predict_proba(torch::Tensor& X) + { + return aode_.predict_proba(X); + } + float XBAODE::score(torch::Tensor& X, torch::Tensor& y) + { + return aode_.score(X, y); + } + +} \ No newline at end of file diff --git a/src/experimental_clfs/XBAODE.h b/src/experimental_clfs/XBAODE.h new file mode 100644 index 0000000..ba9e8f7 --- /dev/null +++ b/src/experimental_clfs/XBAODE.h @@ -0,0 +1,67 @@ +// *************************************************************** +// SPDX-FileCopyrightText: Copyright 2025 Ricardo Montañana Gómez +// SPDX-FileType: SOURCE +// SPDX-License-Identifier: MIT +// *************************************************************** + +#ifndef XBAODE_H +#define XBAODE_H +#include +#include +#include +#include +#include +#include "common/Timer.hpp" +#include "CountingSemaphore.hpp" +#include "bayesnet/ensembles/Boost.h" +#include "XA1DE.h" + +namespace platform { + + class XBAODE : public bayesnet::Boost { + public: + XBAODE(); + virtual ~XBAODE() = default; + const std::string CLASSIFIER_NOT_FITTED = "Classifier has not been fitted"; + + XBAODE& fit(std::vector>& X, std::vector& y, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) override; + XBAODE& fit(torch::Tensor& X, torch::Tensor& y, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) override; + XBAODE& fit(torch::Tensor& dataset, const std::vector& features, const std::string& className, std::map>& states, const bayesnet::Smoothing_t smoothing) override; + XBAODE& fit(torch::Tensor& dataset, const std::vector& features, const std::string& className, std::map>& states, const torch::Tensor& weights, const bayesnet::Smoothing_t smoothing) override; + std::vector predict(std::vector>& X) override; + torch::Tensor predict(torch::Tensor& X) override; + torch::Tensor predict_proba(torch::Tensor& X) override; + std::vector> predict_proba_threads(const std::vector>& test_data); + std::vector> predict_proba(std::vector>& X) override; + float score(std::vector>& X, std::vector& y) override; + float score(torch::Tensor& X, torch::Tensor& y) override; + int getNumberOfNodes() const override; + int getNumberOfEdges() const override; + int getNumberOfStates() const override; + int getClassNumStates() const override; + bayesnet::status_t getStatus() const override { return status; } + std::string getVersion() override { return version; }; + std::vector show() const override { return {}; } + std::vector topological_order() override { return {}; } + std::vector getNotes() const override { return notes; } + std::string dump_cpt() const override { return ""; } + std::vector& getValidHyperparameters() { return validHyperparameters; } + void setDebug(bool debug) { this->debug = debug; } + std::vector graph(const std::string& title = "") const override { return {}; } + void set_active_parents(std::vector active_parents) { aode_.set_active_parents(active_parents); } + protected: + void trainModel(const torch::Tensor& weights, const bayesnet::Smoothing_t smoothing) override {}; + + private: + XA1DE aode_; + std::vector weights_; + CountingSemaphore& semaphore_; + bool debug = false; + bayesnet::status_t status = bayesnet::NORMAL; + std::vector notes; + bool use_threads = true; + std::string version = "0.9.7"; + bool fitted = false; + }; +} +#endif // XBAODE_H \ No newline at end of file diff --git a/src/experimental_clfs/Xaode.hpp b/src/experimental_clfs/Xaode.hpp index b11d20a..93a8d2d 100644 --- a/src/experimental_clfs/Xaode.hpp +++ b/src/experimental_clfs/Xaode.hpp @@ -552,6 +552,10 @@ namespace platform { { return (nFeatures_ + 1) * nFeatures_; } + void set_active_parents(std::vector active_parents) + { + this->active_parents = active_parents; + } private: @@ -583,6 +587,7 @@ namespace platform { MatrixState matrixState_; double SMOOTHING = 1.0; + std::vector active_parents; }; } #endif // XAODE_H \ No newline at end of file diff --git a/src/main/Models.h b/src/main/Models.h index 7e8e1b4..4da2f57 100644 --- a/src/main/Models.h +++ b/src/main/Models.h @@ -21,6 +21,7 @@ #include #include #include "../experimental_clfs/XA1DE.h" +#include "../experimental_clfs/XBAODE.h" namespace platform { class Models { public: diff --git a/src/main/modelRegister.h b/src/main/modelRegister.h index 9043855..cd86995 100644 --- a/src/main/modelRegister.h +++ b/src/main/modelRegister.h @@ -1,41 +1,43 @@ #ifndef MODELREGISTER_H #define MODELREGISTER_H - -static platform::Registrar registrarT("TAN", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::TAN();}); -static platform::Registrar registrarTLD("TANLd", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::TANLd();}); -static platform::Registrar registrarS("SPODE", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::SPODE(2);}); -static platform::Registrar registrarSn("SPnDE", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::SPnDE({ 0, 1 });}); -static platform::Registrar registrarSLD("SPODELd", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::SPODELd(2);}); -static platform::Registrar registrarK("KDB", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::KDB(2);}); -static platform::Registrar registrarKLD("KDBLd", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::KDBLd(2);}); -static platform::Registrar registrarA("AODE", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::AODE();}); -static platform::Registrar registrarA2("A2DE", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::A2DE();}); -static platform::Registrar registrarALD("AODELd", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::AODELd();}); -static platform::Registrar registrarBA("BoostAODE", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::BoostAODE();}); -static platform::Registrar registrarBA2("BoostA2DE", - [](void) -> bayesnet::BaseClassifier* { return new bayesnet::BoostA2DE();}); -static platform::Registrar registrarSt("STree", - [](void) -> bayesnet::BaseClassifier* { return new pywrap::STree();}); -static platform::Registrar registrarOdte("Odte", - [](void) -> bayesnet::BaseClassifier* { return new pywrap::ODTE();}); -static platform::Registrar registrarSvc("SVC", - [](void) -> bayesnet::BaseClassifier* { return new pywrap::SVC();}); -static platform::Registrar registrarRaF("RandomForest", - [](void) -> bayesnet::BaseClassifier* { return new pywrap::RandomForest();}); -static platform::Registrar registrarXGB("XGBoost", - [](void) -> bayesnet::BaseClassifier* { return new pywrap::XGBoost();}); -static platform::Registrar registrarXA1DE("XA1DE", - [](void) -> bayesnet::BaseClassifier* { return new platform::XA1DE();}); - +namespace platform { + static Registrar registrarT("TAN", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::TAN();}); + static Registrar registrarTLD("TANLd", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::TANLd();}); + static Registrar registrarS("SPODE", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::SPODE(2);}); + static Registrar registrarSn("SPnDE", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::SPnDE({ 0, 1 });}); + static Registrar registrarSLD("SPODELd", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::SPODELd(2);}); + static Registrar registrarK("KDB", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::KDB(2);}); + static Registrar registrarKLD("KDBLd", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::KDBLd(2);}); + static Registrar registrarA("AODE", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::AODE();}); + static Registrar registrarA2("A2DE", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::A2DE();}); + static Registrar registrarALD("AODELd", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::AODELd();}); + static Registrar registrarBA("BoostAODE", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::BoostAODE();}); + static Registrar registrarBA2("BoostA2DE", + [](void) -> bayesnet::BaseClassifier* { return new bayesnet::BoostA2DE();}); + static Registrar registrarSt("STree", + [](void) -> bayesnet::BaseClassifier* { return new pywrap::STree();}); + static Registrar registrarOdte("Odte", + [](void) -> bayesnet::BaseClassifier* { return new pywrap::ODTE();}); + static Registrar registrarSvc("SVC", + [](void) -> bayesnet::BaseClassifier* { return new pywrap::SVC();}); + static Registrar registrarRaF("RandomForest", + [](void) -> bayesnet::BaseClassifier* { return new pywrap::RandomForest();}); + static Registrar registrarXGB("XGBoost", + [](void) -> bayesnet::BaseClassifier* { return new pywrap::XGBoost();}); + static Registrar registrarXA1DE("XA1DE", + [](void) -> bayesnet::BaseClassifier* { return new XA1DE();}); + static Registrar registrarXBAODE("XBAODE", + [](void) -> bayesnet::BaseClassifier* { return new XBAODE();}); +} #endif \ No newline at end of file