Add XBAODE & XSPODE from bayesnet

This commit is contained in:
2025-03-09 19:20:51 +01:00
parent ae7b89b134
commit 664a6a5aeb
8 changed files with 302 additions and 49 deletions

View File

@@ -27,7 +27,6 @@ add_executable(
reports/ReportExcel.cpp reports/ReportBase.cpp reports/ExcelFile.cpp reports/ReportExcel.cpp reports/ReportBase.cpp reports/ExcelFile.cpp
results/Result.cpp results/Result.cpp
experimental_clfs/XA1DE.cpp experimental_clfs/XA1DE.cpp
experimental_clfs/XBAODE.cpp
experimental_clfs/ExpClf.cpp experimental_clfs/ExpClf.cpp
) )
target_link_libraries(b_best Boost::boost "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}") target_link_libraries(b_best Boost::boost "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}")
@@ -41,7 +40,6 @@ add_executable(b_grid commands/b_grid.cpp ${grid_sources}
reports/ReportConsole.cpp reports/ReportBase.cpp reports/ReportConsole.cpp reports/ReportBase.cpp
results/Result.cpp results/Result.cpp
experimental_clfs/XA1DE.cpp experimental_clfs/XA1DE.cpp
experimental_clfs/XBAODE.cpp
experimental_clfs/ExpClf.cpp experimental_clfs/ExpClf.cpp
) )
target_link_libraries(b_grid ${MPI_CXX_LIBRARIES} "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy) target_link_libraries(b_grid ${MPI_CXX_LIBRARIES} "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy)
@@ -53,7 +51,6 @@ 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 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 results/Result.cpp results/ResultsDatasetExcel.cpp results/ResultsDataset.cpp results/ResultsDatasetConsole.cpp
experimental_clfs/XA1DE.cpp experimental_clfs/XA1DE.cpp
experimental_clfs/XBAODE.cpp
experimental_clfs/ExpClf.cpp experimental_clfs/ExpClf.cpp
) )
target_link_libraries(b_list "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}") target_link_libraries(b_list "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}")
@@ -66,7 +63,6 @@ add_executable(b_main commands/b_main.cpp ${main_sources}
reports/ReportConsole.cpp reports/ReportBase.cpp reports/ReportConsole.cpp reports/ReportBase.cpp
results/Result.cpp results/Result.cpp
experimental_clfs/XA1DE.cpp experimental_clfs/XA1DE.cpp
experimental_clfs/XBAODE.cpp
experimental_clfs/ExpClf.cpp experimental_clfs/ExpClf.cpp
) )
target_link_libraries(b_main "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy) target_link_libraries(b_main "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy)

View File

@@ -0,0 +1,158 @@
// ***************************************************************
// SPDX-FileCopyrightText: Copyright 2025 Ricardo Montañana Gómez
// SPDX-FileType: SOURCE
// SPDX-License-Identifier: MIT
// ***************************************************************
#include "ExpEnsemble.h"
#include "TensorUtils.hpp"
namespace platform {
ExpEnsemble::ExpEnsemble() : semaphore_{ CountingSemaphore::getInstance() }, Boost(false)
{
validHyperparameters = {};
}
//
// Parents
//
void ExpEnsemble::add_model(std::unique_ptr<XSpode> model)
{
models.push_back(std::move(model));
n_models++;
}
void ExpEnsemble::remove_last_model()
{
models.pop_back();
n_models--;
}
//
// Predict
//
torch::Tensor ExpEnsemble::predict(torch::Tensor& X)
{
auto X_ = TensorUtils::to_matrix(X);
torch::Tensor y = torch::tensor(predict(X_));
return y;
}
torch::Tensor ExpEnsemble::predict_proba(torch::Tensor& X)
{
auto X_ = TensorUtils::to_matrix(X);
auto probabilities = predict_proba(X_);
auto n_samples = X.size(1);
int n_classes = probabilities[0].size();
auto y = torch::zeros({ n_samples, n_classes });
for (int i = 0; i < n_samples; i++) {
for (int j = 0; j < n_classes; j++) {
y[i][j] = probabilities[i][j];
}
}
return y;
}
float ExpEnsemble::score(torch::Tensor& X, torch::Tensor& y)
{
auto X_ = TensorUtils::to_matrix(X);
auto y_ = TensorUtils::to_vector<int>(y);
return score(X_, y_);
}
std::vector<std::vector<double>> ExpEnsemble::predict_proba(const std::vector<std::vector<int>>& test_data)
{
int test_size = test_data[0].size();
int sample_size = test_data.size();
auto probabilities = std::vector<std::vector<double>>(test_size, std::vector<double>(getClassNumStates()));
int chunk_size = std::min(150, int(test_size / semaphore_.getMaxCount()) + 1);
std::vector<std::thread> threads;
auto worker = [&](const std::vector<std::vector<int>>& samples, int begin, int chunk, int sample_size, std::vector<std::vector<double>>& predictions) {
std::string threadName = "(V)PWorker-" + std::to_string(begin) + "-" + std::to_string(chunk);
#if defined(__linux__)
pthread_setname_np(pthread_self(), threadName.c_str());
#else
pthread_setname_np(threadName.c_str());
#endif
std::vector<int> instance(sample_size);
for (int sample = begin; sample < begin + chunk; ++sample) {
for (int feature = 0; feature < sample_size; ++feature) {
instance[feature] = samples[feature][sample];
}
// predictions[sample] = aode_.predict_proba(instance);
}
semaphore_.release();
};
for (int begin = 0; begin < test_size; begin += chunk_size) {
int chunk = std::min(chunk_size, test_size - begin);
semaphore_.acquire();
threads.emplace_back(worker, test_data, begin, chunk, sample_size, std::ref(probabilities));
}
for (auto& thread : threads) {
thread.join();
}
return probabilities;
}
std::vector<int> ExpEnsemble::predict(std::vector<std::vector<int>>& test_data)
{
if (!fitted) {
throw std::logic_error(CLASSIFIER_NOT_FITTED);
}
auto probabilities = predict_proba(test_data);
std::vector<int> predictions(probabilities.size(), 0);
for (size_t i = 0; i < probabilities.size(); i++) {
predictions[i] = std::distance(probabilities[i].begin(), std::max_element(probabilities[i].begin(), probabilities[i].end()));
}
return predictions;
}
float ExpEnsemble::score(std::vector<std::vector<int>>& test_data, std::vector<int>& labels)
{
Timer timer;
timer.start();
std::vector<int> predictions = predict(test_data);
int correct = 0;
for (size_t i = 0; i < predictions.size(); i++) {
if (predictions[i] == labels[i]) {
correct++;
}
}
if (debug) {
std::cout << "* Time to predict: " << timer.getDurationString() << std::endl;
}
return static_cast<float>(correct) / predictions.size();
}
//
// statistics
//
int ExpEnsemble::getNumberOfNodes() const
{
if (models_.empty()) {
return 0;
}
return n_models * (models_.at(0)->getNFeatures() + 1);
}
int ExpEnsemble::getNumberOfEdges() const
{
if (models_.empty()) {
return 0;
}
return n_models * (2 * models_.at(0)->getNFeatures() - 1);
}
int ExpEnsemble::getNumberOfStates() const
{
if (models_.empty()) {
return 0;
}
auto states = models_.at(0)->getStates();
int nFeatures = models_.at(0)->getNFeatures();
return std::accumulate(states.begin(), states.end(), 0) * nFeatures * n_models;
}
int ExpEnsemble::getClassNumStates() const
{
if (models_.empty()) {
return 0;
}
return models_.at(0)->statesClass();
}
}

View File

@@ -0,0 +1,66 @@
// ***************************************************************
// SPDX-FileCopyrightText: Copyright 2025 Ricardo Montañana Gómez
// SPDX-FileType: SOURCE
// SPDX-License-Identifier: MIT
// ***************************************************************
#ifndef EXPENSEMBLE_H
#define EXPENSEMBLE_H
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include <limits>
#include <bayesnet/ensembles/Boost.h>
#include <bayesnet/network/Smoothing.h>
#include "common/Timer.hpp"
#include "CountingSemaphore.hpp"
#include "XSpode.hpp"
namespace platform {
class ExpEnsemble : public bayesnet::Boost {
public:
ExpEnsemble();
virtual ~ExpEnsemble() = default;
std::vector<int> predict(std::vector<std::vector<int>>& X) override;
torch::Tensor predict(torch::Tensor& X) override;
torch::Tensor predict_proba(torch::Tensor& X) override;
std::vector<int> predict_spode(std::vector<std::vector<int>>& test_data, int parent);
std::vector<std::vector<double>> predict_proba(const std::vector<std::vector<int>>& X);
float score(std::vector<std::vector<int>>& X, std::vector<int>& 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;
std::vector<std::string> show() const override { return {}; }
std::vector<std::string> topological_order() override { return {}; }
std::string dump_cpt() const override { return ""; }
void setDebug(bool debug) { this->debug = debug; }
bayesnet::status_t getStatus() const override { return status; }
std::vector<std::string> getNotes() const override { return notes; }
std::vector<std::string> graph(const std::string& title = "") const override { return {}; }
protected:
void add_model(std::unique_ptr<XSpode> model);
void remove_last_model();
bool debug = false;
std::vector <std::unique_ptr<XSpode>> models_;
torch::Tensor weights_;
std::vector<double> significanceModels_;
const std::string CLASSIFIER_NOT_FITTED = "Classifier has not been fitted";
inline void normalize_weights(int num_instances)
{
double sum = weights_.sum().item<double>();
if (sum == 0) {
weights_ = torch::full({ num_instances }, 1.0);
} else {
for (int i = 0; i < weights_.size(0); ++i) {
weights_[i] = weights_[i].item<double>() * num_instances / sum;
}
}
}
private:
CountingSemaphore& semaphore_;
};
}
#endif // EXPENSEMBLE_H

View File

@@ -19,6 +19,16 @@ namespace platform {
validHyperparameters = { "alpha_block", "order", "convergence", "convergence_best", "bisection", "threshold", "maxTolerance", validHyperparameters = { "alpha_block", "order", "convergence", "convergence_best", "bisection", "threshold", "maxTolerance",
"predict_voting", "select_features" }; "predict_voting", "select_features" };
} }
void XBAODE::add_model(std::unique_ptr<XSpode> model)
{
models.push_back(std::move(model));
n_models++;
}
void XBAODE::remove_last_model()
{
models.pop_back();
n_models--;
}
void XBAODE::trainModel(const torch::Tensor& weights, const bayesnet::Smoothing_t smoothing) void XBAODE::trainModel(const torch::Tensor& weights, const bayesnet::Smoothing_t smoothing)
{ {
fitted = true; fitted = true;
@@ -30,30 +40,36 @@ namespace platform {
// //
// Logging setup // Logging setup
// //
loguru::set_thread_name("XBAODE"); // loguru::set_thread_name("XBAODE");
loguru::g_stderr_verbosity = loguru::Verbosity_OFF; // loguru::g_stderr_verbosity = loguru::Verbosity_OFF;
loguru::add_file("XBAODE.log", loguru::Truncate, loguru::Verbosity_MAX); // loguru::add_file("XBAODE.log", loguru::Truncate, loguru::Verbosity_MAX);
// Algorithm based on the adaboost algorithm for classification // Algorithm based on the adaboost algorithm for classification
// as explained in Ensemble methods (Zhi-Hua Zhou, 2012) // as explained in Ensemble methods (Zhi-Hua Zhou, 2012)
double alpha_t = 0; double alpha_t = 0;
weights_ = torch::full({ m }, 1.0 / static_cast<double>(m), torch::kFloat64); weights_ = torch::full({ m }, 1.0 / static_cast<double>(m), torch::kFloat64); // m initialized in Classifier.cc
significanceModels.resize(n, 0.0); // n initialized in Classifier.cc
bool finished = false; bool finished = false;
std::vector<int> featuresUsed; std::vector<int> featuresUsed;
aode_.fit(X_train_, y_train_, features, className, states, weights_, false);
n_models = 0; n_models = 0;
std::unique_ptr<XSpode> model;
if (selectFeatures) { if (selectFeatures) {
featuresUsed = featureSelection(weights_); featuresUsed = featureSelection(weights_);
add_active_parents(featuresUsed); for (const auto& parent : featuresUsed) {
model = std::unique_ptr<XSpode>(new XSpode(parent));
model->fit(X_train_, y_train_, weights_, smoothing);
std::cout << model->getNFeatures() << std::endl;
add_model(std::move(model));
}
notes.push_back("Used features in initialization: " + std::to_string(featuresUsed.size()) + " of " + std::to_string(features.size()) + " with " + select_features_algorithm); notes.push_back("Used features in initialization: " + std::to_string(featuresUsed.size()) + " of " + std::to_string(features.size()) + " with " + select_features_algorithm);
auto ypred = ExpClf::predict(X_train); auto ypred = ExpEnsemble::predict(X_train);
std::tie(weights_, alpha_t, finished) = update_weights(y_train, ypred, weights_); std::tie(weights_, alpha_t, finished) = update_weights(y_train, ypred, weights_);
// Update significance of the models // Update significance of the models
for (const auto& parent : featuresUsed) { for (const auto& parent : featuresUsed) {
aode_.significance_models_[parent] = alpha_t; significanceModels_[parent] = alpha_t;
} }
n_models = featuresUsed.size(); n_models = featuresUsed.size();
VLOG_SCOPE_F(1, "SelectFeatures. alpha_t: %f n_models: %d", alpha_t, n_models); // VLOG_SCOPE_F(1, "SelectFeatures. alpha_t: %f n_models: %d", alpha_t, n_models);
if (finished) { if (finished) {
return; return;
} }
@@ -83,29 +99,28 @@ namespace platform {
); );
int k = bisection ? pow(2, tolerance) : 1; int k = bisection ? pow(2, tolerance) : 1;
int counter = 0; // The model counter of the current pack int counter = 0; // The model counter of the current pack
VLOG_SCOPE_F(1, "counter=%d k=%d featureSelection.size: %zu", counter, k, featureSelection.size()); // VLOG_SCOPE_F(1, "counter=%d k=%d featureSelection.size: %zu", counter, k, featureSelection.size());
while (counter++ < k && featureSelection.size() > 0) { while (counter++ < k && featureSelection.size() > 0) {
auto feature = featureSelection[0]; auto feature = featureSelection[0];
featureSelection.erase(featureSelection.begin()); featureSelection.erase(featureSelection.begin());
auto model = XSpode(feature); model = std::unique_ptr<XSpode>(new XSpode(feature));
model.fit(X_train_, y_train_, weights_, smoothing); model->fit(X_train_, y_train_, weights_, smoothing);
std::vector<int> ypred; std::vector<int> ypred;
if (alpha_block) { if (alpha_block) {
// //
// Compute the prediction with the current ensemble + model // Compute the prediction with the current ensemble + model
// //
// Add the model to the ensemble // Add the model to the ensemble
n_models++; significanceModels[feature] = 1.0;
aode_.significance_models_[feature] = 1.0; add_model(std::move(model));
aode_.add_active_parent(feature);
// Compute the prediction // Compute the prediction
ypred = ExpClf::predict(X_train_); ypred = ExpEnsemble::predict(X_train_);
// Remove the model from the ensemble // Remove the model from the ensemble
aode_.significance_models_[feature] = 0.0; significanceModels[feature] = 0.0;
aode_.remove_last_parent(); model = std::move(models_.back());
n_models--; remove_last_model();
} else { } else {
ypred = model.predict(X_train_); ypred = model->predict(X_train_);
} }
// Step 3.1: Compute the classifier amout of say // Step 3.1: Compute the classifier amout of say
auto ypred_t = torch::tensor(ypred); auto ypred_t = torch::tensor(ypred);
@@ -113,13 +128,12 @@ namespace platform {
// Step 3.4: Store classifier and its accuracy to weigh its future vote // Step 3.4: Store classifier and its accuracy to weigh its future vote
numItemsPack++; numItemsPack++;
featuresUsed.push_back(feature); featuresUsed.push_back(feature);
aode_.add_active_parent(feature); add_model(std::move(model));
aode_.significance_models_[feature] = alpha_t; significanceModels[feature] = alpha_t;
n_models++; // VLOG_SCOPE_F(2, "finished: %d numItemsPack: %d n_models: %d featuresUsed: %zu", finished, numItemsPack, n_models, featuresUsed.size());
VLOG_SCOPE_F(2, "finished: %d numItemsPack: %d n_models: %d featuresUsed: %zu", finished, numItemsPack, n_models, featuresUsed.size());
} // End of the pack } // End of the pack
if (convergence && !finished) { if (convergence && !finished) {
auto y_val_predict = ExpClf::predict(X_test); auto y_val_predict = ExpEnsemble::predict(X_test);
double accuracy = (y_val_predict == y_test).sum().item<double>() / (double)y_test.size(0); double accuracy = (y_val_predict == y_test).sum().item<double>() / (double)y_test.size(0);
if (priorAccuracy == 0) { if (priorAccuracy == 0) {
priorAccuracy = accuracy; priorAccuracy = accuracy;
@@ -127,10 +141,10 @@ namespace platform {
improvement = accuracy - priorAccuracy; improvement = accuracy - priorAccuracy;
} }
if (improvement < convergence_threshold) { if (improvement < convergence_threshold) {
VLOG_SCOPE_F(3, " (improvement<threshold) tolerance: %d numItemsPack: %d improvement: %f prior: %f current: %f", tolerance, numItemsPack, improvement, priorAccuracy, accuracy); // VLOG_SCOPE_F(3, " (improvement<threshold) tolerance: %d numItemsPack: %d improvement: %f prior: %f current: %f", tolerance, numItemsPack, improvement, priorAccuracy, accuracy);
tolerance++; tolerance++;
} else { } else {
VLOG_SCOPE_F(3, "* (improvement>=threshold) Reset. tolerance: %d numItemsPack: %d improvement: %f prior: %f current: %f", tolerance, numItemsPack, improvement, priorAccuracy, accuracy); // VLOG_SCOPE_F(3, "* (improvement>=threshold) Reset. tolerance: %d numItemsPack: %d improvement: %f prior: %f current: %f", tolerance, numItemsPack, improvement, priorAccuracy, accuracy);
tolerance = 0; // Reset the counter if the model performs better tolerance = 0; // Reset the counter if the model performs better
numItemsPack = 0; numItemsPack = 0;
} }
@@ -142,22 +156,21 @@ namespace platform {
priorAccuracy = accuracy; priorAccuracy = accuracy;
} }
} }
VLOG_SCOPE_F(1, "tolerance: %d featuresUsed.size: %zu features.size: %zu", tolerance, featuresUsed.size(), features.size()); // VLOG_SCOPE_F(1, "tolerance: %d featuresUsed.size: %zu features.size: %zu", tolerance, featuresUsed.size(), features.size());
finished = finished || tolerance > maxTolerance || featuresUsed.size() == features.size(); finished = finished || tolerance > maxTolerance || featuresUsed.size() == features.size();
} }
if (tolerance > maxTolerance) { if (tolerance > maxTolerance) {
if (numItemsPack < n_models) { if (numItemsPack < n_models) {
notes.push_back("Convergence threshold reached & " + std::to_string(numItemsPack) + " models eliminated"); notes.push_back("Convergence threshold reached & " + std::to_string(numItemsPack) + " models eliminated");
VLOG_SCOPE_F(4, "Convergence threshold reached & %d models eliminated of %d", numItemsPack, n_models); // VLOG_SCOPE_F(4, "Convergence threshold reached & %d models eliminated of %d", numItemsPack, n_models);
for (int i = featuresUsed.size() - 1; i >= featuresUsed.size() - numItemsPack; --i) { for (int i = featuresUsed.size() - 1; i >= featuresUsed.size() - numItemsPack; --i) {
aode_.remove_last_parent(); remove_last_model();
aode_.significance_models_[featuresUsed[i]] = 0.0; significanceModels[featuresUsed[i]] = 0.0;
n_models--;
} }
VLOG_SCOPE_F(4, "*Convergence threshold %d models left & %d features used.", n_models, featuresUsed.size()); // VLOG_SCOPE_F(4, "*Convergence threshold %d models left & %d features used.", n_models, featuresUsed.size());
} else { } else {
notes.push_back("Convergence threshold reached & 0 models eliminated"); notes.push_back("Convergence threshold reached & 0 models eliminated");
VLOG_SCOPE_F(4, "Convergence threshold reached & 0 models eliminated n_models=%d numItemsPack=%d", n_models, numItemsPack); // VLOG_SCOPE_F(4, "Convergence threshold reached & 0 models eliminated n_models=%d numItemsPack=%d", n_models, numItemsPack);
} }
} }
if (featuresUsed.size() != features.size()) { if (featuresUsed.size() != features.size()) {

View File

@@ -12,10 +12,10 @@
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#include "common/Timer.hpp" #include "common/Timer.hpp"
#include "ExpClf.h" #include "ExpEnsemble.h"
namespace platform { namespace platform {
class XBAODE { class XBAODE : public Boost {
// Hay que hacer un vector de modelos entrenados y hacer un predict ensemble con todos ellos // Hay que hacer un vector de modelos entrenados y hacer un predict ensemble con todos ellos
// Probar XA1DE con smooth original y laplace y comprobar diferencias si se pasan pesos a 1 o a 1/m // Probar XA1DE con smooth original y laplace y comprobar diferencias si se pasan pesos a 1 o a 1/m
@@ -25,10 +25,10 @@ namespace platform {
protected: protected:
void trainModel(const torch::Tensor& weights, const bayesnet::Smoothing_t smoothing) override; void trainModel(const torch::Tensor& weights, const bayesnet::Smoothing_t smoothing) override;
private: private:
void add_model(std::unique_ptr<XSpode> model);
void remove_last_model();
std::vector<std::vector<int>> X_train_, X_test_; std::vector<std::vector<int>> X_train_, X_test_;
std::vector<int> y_train_, y_test_; std::vector<int> y_train_, y_test_;
torch::Tensor dataset;
int n_models;
std::string version = "0.9.7"; std::string version = "0.9.7";
}; };
} }

View File

@@ -11,24 +11,29 @@
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <torch/torch.h>
#include <bayesnet/network/Smoothing.h>
#include <bayesnet/classifiers/Classifier.h>
#include "CountingSemaphore.hpp" #include "CountingSemaphore.hpp"
namespace platform { namespace platform {
class XSpode { class XSpode : public bayesnet::Classifier {
public: public:
// -------------------------------------- // --------------------------------------
// Constructor // Constructor
// //
// Supply which feature index is the single super-parent (“spIndex”). // Supply which feature index is the single super-parent (“spIndex”).
// -------------------------------------- // --------------------------------------
XSpode(int spIndex) explicit XSpode(int spIndex)
: superParent_{ spIndex }, : superParent_{ spIndex },
nFeatures_{ 0 }, nFeatures_{ 0 },
statesClass_{ 0 }, statesClass_{ 0 },
fitted_{ false },
alpha_{ 1.0 }, alpha_{ 1.0 },
semaphore_{ CountingSemaphore::getInstance() } initializer_{ 1.0 },
semaphore_{ CountingSemaphore::getInstance() } : bayesnet::Classifier(bayesnet::Network())
{ {
} }
@@ -380,6 +385,17 @@ namespace platform {
oss << "---------------------\n"; oss << "---------------------\n";
return oss.str(); return oss.str();
} }
int statesClass() const { return statesClass_; }
int getNFeatures() const { return nFeatures_; }
int getNumberOfStates() const
{
return std::accumulate(states_.begin(), states_.end(), 0) * nFeatures_;
}
int getNumberOfEdges() const
{
return nFeatures_ * (2 * nFeatures_ - 1);
}
std::vector<int>& getStates() { return states_; }
private: private:
// -------------------------------------- // --------------------------------------

View File

@@ -5,11 +5,13 @@
#include <bayesnet/ensembles/AODE.h> #include <bayesnet/ensembles/AODE.h>
#include <bayesnet/ensembles/A2DE.h> #include <bayesnet/ensembles/A2DE.h>
#include <bayesnet/ensembles/AODELd.h> #include <bayesnet/ensembles/AODELd.h>
#include <bayesnet/ensembles/XBAODE.h>
#include <bayesnet/ensembles/BoostAODE.h> #include <bayesnet/ensembles/BoostAODE.h>
#include <bayesnet/ensembles/BoostA2DE.h> #include <bayesnet/ensembles/BoostA2DE.h>
#include <bayesnet/classifiers/TAN.h> #include <bayesnet/classifiers/TAN.h>
#include <bayesnet/classifiers/KDB.h> #include <bayesnet/classifiers/KDB.h>
#include <bayesnet/classifiers/SPODE.h> #include <bayesnet/classifiers/SPODE.h>
#include <bayesnet/classifiers/XSPODE.h>
#include <bayesnet/classifiers/SPnDE.h> #include <bayesnet/classifiers/SPnDE.h>
#include <bayesnet/classifiers/TANLd.h> #include <bayesnet/classifiers/TANLd.h>
#include <bayesnet/classifiers/KDBLd.h> #include <bayesnet/classifiers/KDBLd.h>
@@ -21,7 +23,7 @@
#include <pyclassifiers/XGBoost.h> #include <pyclassifiers/XGBoost.h>
#include <pyclassifiers/RandomForest.h> #include <pyclassifiers/RandomForest.h>
#include "../experimental_clfs/XA1DE.h" #include "../experimental_clfs/XA1DE.h"
#include "../experimental_clfs/XBAODE.h"
namespace platform { namespace platform {
class Models { class Models {
public: public:

View File

@@ -35,9 +35,11 @@ namespace platform {
[](void) -> bayesnet::BaseClassifier* { return new pywrap::RandomForest();}); [](void) -> bayesnet::BaseClassifier* { return new pywrap::RandomForest();});
static Registrar registrarXGB("XGBoost", static Registrar registrarXGB("XGBoost",
[](void) -> bayesnet::BaseClassifier* { return new pywrap::XGBoost();}); [](void) -> bayesnet::BaseClassifier* { return new pywrap::XGBoost();});
static Registrar registrarXSPODE("XSPODE",
[](void) -> bayesnet::BaseClassifier* { return new bayesnet::XSpode(0);});
static Registrar registrarXBAODE("XBAODE",
[](void) -> bayesnet::BaseClassifier* { return new bayesnet::XBAODE();});
static Registrar registrarXA1DE("XA1DE", static Registrar registrarXA1DE("XA1DE",
[](void) -> bayesnet::BaseClassifier* { return new XA1DE();}); [](void) -> bayesnet::BaseClassifier* { return new XA1DE();});
static Registrar registrarXBAODE("XBAODE",
[](void) -> bayesnet::BaseClassifier* { return new XBAODE();});
} }
#endif #endif