Add XBAODE & XSPODE from bayesnet
This commit is contained in:
@@ -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)
|
||||||
|
158
src/experimental_clfs/ExpEnsemble.cpp
Normal file
158
src/experimental_clfs/ExpEnsemble.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
66
src/experimental_clfs/ExpEnsemble.h
Normal file
66
src/experimental_clfs/ExpEnsemble.h
Normal 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
|
@@ -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()) {
|
||||||
|
@@ -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";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -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:
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
|
@@ -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:
|
||||||
|
@@ -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 registrarXA1DE("XA1DE",
|
static Registrar registrarXSPODE("XSPODE",
|
||||||
[](void) -> bayesnet::BaseClassifier* { return new XA1DE();});
|
[](void) -> bayesnet::BaseClassifier* { return new bayesnet::XSpode(0);});
|
||||||
static Registrar registrarXBAODE("XBAODE",
|
static Registrar registrarXBAODE("XBAODE",
|
||||||
[](void) -> bayesnet::BaseClassifier* { return new XBAODE();});
|
[](void) -> bayesnet::BaseClassifier* { return new bayesnet::XBAODE();});
|
||||||
|
static Registrar registrarXA1DE("XA1DE",
|
||||||
|
[](void) -> bayesnet::BaseClassifier* { return new XA1DE();});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
Reference in New Issue
Block a user