Compare commits

..

1 Commits
main ... cuda

Author SHA1 Message Date
baa631dd66
Add Cuda iniitialization in Classifier 2024-09-18 12:13:11 +02:00
45 changed files with 1081 additions and 5892 deletions

View File

@ -1,4 +1,4 @@
compilation_database_dir: build_Debug compilation_database_dir: build_debug
output_directory: diagrams output_directory: diagrams
diagrams: diagrams:
BayesNet: BayesNet:

View File

@ -1,6 +1,6 @@
FROM mcr.microsoft.com/devcontainers/cpp:ubuntu22.04 FROM mcr.microsoft.com/devcontainers/cpp:ubuntu22.04
ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="3.29.3" ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="3.22.2"
# Optionally install the cmake for vcpkg # Optionally install the cmake for vcpkg
COPY ./reinstall-cmake.sh /tmp/ COPY ./reinstall-cmake.sh /tmp/
@ -23,7 +23,7 @@ RUN add-apt-repository ppa:ubuntu-toolchain-r/test
RUN apt-get update RUN apt-get update
# Install GCC 13.1 # Install GCC 13.1
RUN apt-get install -y gcc-13 g++-13 doxygen RUN apt-get install -y gcc-13 g++-13
# Install lcov 2.1 # Install lcov 2.1
RUN wget --quiet https://github.com/linux-test-project/lcov/releases/download/v2.1/lcov-2.1.tar.gz && \ RUN wget --quiet https://github.com/linux-test-project/lcov/releases/download/v2.1/lcov-2.1.tar.gz && \

8
.gitmodules vendored
View File

@ -1,3 +1,8 @@
[submodule "lib/mdlp"]
path = lib/mdlp
url = https://github.com/rmontanana/mdlp
main = main
update = merge
[submodule "lib/json"] [submodule "lib/json"]
path = lib/json path = lib/json
url = https://github.com/nlohmann/json.git url = https://github.com/nlohmann/json.git
@ -16,6 +21,3 @@
[submodule "tests/lib/Files"] [submodule "tests/lib/Files"]
path = tests/lib/Files path = tests/lib/Files
url = https://github.com/rmontanana/ArffFiles url = https://github.com/rmontanana/ArffFiles
[submodule "lib/mdlp"]
path = lib/mdlp
url = https://github.com/rmontanana/mdlp

2
.vscode/launch.json vendored
View File

@ -16,7 +16,7 @@
"name": "test", "name": "test",
"program": "${workspaceFolder}/build_Debug/tests/TestBayesNet", "program": "${workspaceFolder}/build_Debug/tests/TestBayesNet",
"args": [ "args": [
"No features selected" "[Network]"
], ],
"cwd": "${workspaceFolder}/build_Debug/tests" "cwd": "${workspaceFolder}/build_Debug/tests"
}, },

View File

@ -7,15 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [1.0.6] 2024-11-23
### Fixed
- Prevent existing edges to be added to the network in the `add_edge` method.
- Don't allow to add nodes or edges on already fiited networks.
- Number of threads spawned
- Network class tests
### Added ### Added
- Library logo generated with <https://openart.ai> to README.md - Library logo generated with <https://openart.ai> to README.md
@ -23,21 +14,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- *convergence_best* hyperparameter to the BoostAODE class, to control the way the prior accuracy is computed if convergence is set. Default value is *false*. - *convergence_best* hyperparameter to the BoostAODE class, to control the way the prior accuracy is computed if convergence is set. Default value is *false*.
- SPnDE model. - SPnDE model.
- A2DE model. - A2DE model.
- BoostA2DE model.
- A2DE & SPnDE tests. - A2DE & SPnDE tests.
- Add tests to reach 99% of coverage. - Add tests to reach 99% of coverage.
- Add tests to check the correct version of the mdlp, folding and json libraries. - Add tests to check the correct version of the mdlp, folding and json libraries.
- Library documentation generated with Doxygen. - Library documentation generated with Doxygen.
- Link to documentation in the README.md. - Link to documentation in the README.md.
- Three types of smoothing the Bayesian Network ORIGINAL, LAPLACE and CESTNIK. - Three types of smoothing the Bayesian Network OLD_LAPLACE, LAPLACE and CESTNIK.
### Internal ### Internal
- Fixed doxygen optional dependency
- Add env parallel variable to Makefile
- Add CountingSemaphore class to manage the number of threads spawned.
- Ignore CUDA language in CMake CodeCoverage module.
- Update mdlp library as a git submodule.
- Create library ShuffleArffFile to limit the number of samples with a parameter and shuffle them. - Create library ShuffleArffFile to limit the number of samples with a parameter and shuffle them.
- Refactor catch2 library location to test/lib - Refactor catch2 library location to test/lib
- Refactor loadDataset function in tests. - Refactor loadDataset function in tests.
@ -48,13 +33,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add a Makefile target (doc) to generate the documentation. - Add a Makefile target (doc) to generate the documentation.
- Add a Makefile target (doc-install) to install the documentation. - Add a Makefile target (doc-install) to install the documentation.
### Libraries versions
- mdlp: 2.0.1
- Folding: 1.1.0
- json: 3.11
- ArffFiles: 1.1.0
## [1.0.5] 2024-04-20 ## [1.0.5] 2024-04-20
### Added ### Added

View File

@ -49,13 +49,17 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CODE_COVERAGE ON) set(CODE_COVERAGE ON)
endif (CMAKE_BUILD_TYPE STREQUAL "Debug") endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
message(STATUS "Languages=${LANGUAGES}")
if (CODE_COVERAGE) if (CODE_COVERAGE)
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
message("ALL LANGUAGES: ${LANGUAGES}")
foreach(LANG ${LANGUAGES})
message("${LANG} compiler is \"${CMAKE_${LANG}_COMPILER_ID}\"")
endforeach()
enable_testing() enable_testing()
include(CodeCoverage) #include(CodeCoverage)
MESSAGE(STATUS "Code coverage enabled") #MESSAGE("Code coverage enabled")
SET(GCC_COVERAGE_LINK_FLAGS " ${GCC_COVERAGE_LINK_FLAGS} -lgcov --coverage") #SET(GCC_COVERAGE_LINK_FLAGS " ${GCC_COVERAGE_LINK_FLAGS} -lgcov --coverage")
endif (CODE_COVERAGE) endif (CODE_COVERAGE)
if (ENABLE_CLANG_TIDY) if (ENABLE_CLANG_TIDY)
@ -64,7 +68,6 @@ endif (ENABLE_CLANG_TIDY)
# External libraries - dependencies of BayesNet # External libraries - dependencies of BayesNet
# --------------------------------------------- # ---------------------------------------------
# include(FetchContent) # include(FetchContent)
add_git_submodule("lib/json") add_git_submodule("lib/json")
add_git_submodule("lib/mdlp") add_git_submodule("lib/mdlp")
@ -77,7 +80,7 @@ add_subdirectory(bayesnet)
# Testing # Testing
# ------- # -------
if (ENABLE_TESTING) if (ENABLE_TESTING)
MESSAGE(STATUS "Testing enabled") MESSAGE("Testing enabled")
add_subdirectory(tests/lib/catch2) add_subdirectory(tests/lib/catch2)
include(CTest) include(CTest)
add_subdirectory(tests) add_subdirectory(tests)
@ -95,14 +98,10 @@ install(FILES ${CMAKE_BINARY_DIR}/configured_files/include/bayesnet/config.h DES
# Documentation # Documentation
# ------------- # -------------
find_package(Doxygen) find_package(Doxygen)
if (Doxygen_FOUND) set(DOC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/docs)
set(DOC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/docs) set(doxyfile_in ${DOC_DIR}/Doxyfile.in)
set(doxyfile_in ${DOC_DIR}/Doxyfile.in) set(doxyfile ${DOC_DIR}/Doxyfile)
set(doxyfile ${DOC_DIR}/Doxyfile) configure_file(${doxyfile_in} ${doxyfile} @ONLY)
configure_file(${doxyfile_in} ${doxyfile} @ONLY) doxygen_add_docs(doxygen
doxygen_add_docs(doxygen WORKING_DIRECTORY ${DOC_DIR}
WORKING_DIRECTORY ${DOC_DIR}
CONFIG_FILE ${doxyfile}) CONFIG_FILE ${doxyfile})
else (Doxygen_FOUND)
MESSAGE("* Doxygen not found")
endif (Doxygen_FOUND)

View File

@ -43,7 +43,7 @@ setup: ## Install dependencies for tests and coverage
fi fi
@echo "* You should install plantuml & graphviz for the diagrams" @echo "* You should install plantuml & graphviz for the diagrams"
diagrams: ## Create an UML class diagram & dependency of the project (diagrams/BayesNet.png) diagrams: ## Create an UML class diagram & depnendency of the project (diagrams/BayesNet.png)
@which $(plantuml) || (echo ">>> Please install plantuml"; exit 1) @which $(plantuml) || (echo ">>> Please install plantuml"; exit 1)
@which $(dot) || (echo ">>> Please install graphviz"; exit 1) @which $(dot) || (echo ">>> Please install graphviz"; exit 1)
@which $(clang-uml) || (echo ">>> Please install clang-uml"; exit 1) @which $(clang-uml) || (echo ">>> Please install clang-uml"; exit 1)
@ -58,10 +58,10 @@ diagrams: ## Create an UML class diagram & dependency of the project (diagrams/B
@$(dot) -Tsvg $(f_debug)/dependency.dot.BayesNet -o $(f_diagrams)/dependency.svg @$(dot) -Tsvg $(f_debug)/dependency.dot.BayesNet -o $(f_diagrams)/dependency.svg
buildd: ## Build the debug targets buildd: ## Build the debug targets
cmake --build $(f_debug) -t $(app_targets) --parallel $(CMAKE_BUILD_PARALLEL_LEVEL) cmake --build $(f_debug) -t $(app_targets) --parallel
buildr: ## Build the release targets buildr: ## Build the release targets
cmake --build $(f_release) -t $(app_targets) --parallel $(CMAKE_BUILD_PARALLEL_LEVEL) cmake --build $(f_release) -t $(app_targets) --parallel
clean: ## Clean the tests info clean: ## Clean the tests info
@echo ">>> Cleaning Debug BayesNet tests..."; @echo ">>> Cleaning Debug BayesNet tests...";
@ -105,7 +105,7 @@ opt = ""
test: ## Run tests (opt="-s") to verbose output the tests, (opt="-c='Test Maximum Spanning Tree'") to run only that section test: ## Run tests (opt="-s") to verbose output the tests, (opt="-c='Test Maximum Spanning Tree'") to run only that section
@echo ">>> Running BayesNet tests..."; @echo ">>> Running BayesNet tests...";
@$(MAKE) clean @$(MAKE) clean
@cmake --build $(f_debug) -t $(test_targets) --parallel $(CMAKE_BUILD_PARALLEL_LEVEL) @cmake --build $(f_debug) -t $(test_targets) --parallel
@for t in $(test_targets); do \ @for t in $(test_targets); do \
echo ">>> Running $$t...";\ echo ">>> Running $$t...";\
if [ -f $(f_debug)/tests/$$t ]; then \ if [ -f $(f_debug)/tests/$$t ]; then \
@ -172,7 +172,7 @@ docdir = ""
doc-install: ## Install documentation doc-install: ## Install documentation
@echo ">>> Installing documentation..." @echo ">>> Installing documentation..."
@if [ "$(docdir)" = "" ]; then \ @if [ "$(docdir)" = "" ]; then \
echo "docdir parameter has to be set when calling doc-install, i.e. docdir=../bayesnet_help"; \ echo "docdir parameter has to be set when calling doc-install"; \
exit 1; \ exit 1; \
fi fi
@if [ ! -d $(docdir) ]; then \ @if [ ! -d $(docdir) ]; then \

View File

@ -7,10 +7,9 @@
[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=rmontanana_BayesNet&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=rmontanana_BayesNet) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=rmontanana_BayesNet&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=rmontanana_BayesNet)
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=rmontanana_BayesNet&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=rmontanana_BayesNet) [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=rmontanana_BayesNet&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=rmontanana_BayesNet)
![Gitea Last Commit](https://img.shields.io/gitea/last-commit/rmontanana/bayesnet?gitea_url=https://gitea.rmontanana.es:3000&logo=gitea) ![Gitea Last Commit](https://img.shields.io/gitea/last-commit/rmontanana/bayesnet?gitea_url=https://gitea.rmontanana.es:3000&logo=gitea)
[![Coverage Badge](https://img.shields.io/badge/Coverage-99,1%25-green)](html/index.html) [![Coverage Badge](https://img.shields.io/badge/Coverage-97,1%25-green)](html/index.html)
[![DOI](https://zenodo.org/badge/667782806.svg)](https://doi.org/10.5281/zenodo.14210344)
Bayesian Network Classifiers library Bayesian Network Classifiers using libtorch from scratch
## Dependencies ## Dependencies
@ -72,8 +71,6 @@ make sample fname=tests/data/glass.arff
#### - AODE #### - AODE
#### - A2DE
#### - [BoostAODE](docs/BoostAODE.md) #### - [BoostAODE](docs/BoostAODE.md)
#### - BoostA2DE #### - BoostA2DE

View File

@ -9,4 +9,4 @@ include_directories(
file(GLOB_RECURSE Sources "*.cc") file(GLOB_RECURSE Sources "*.cc")
add_library(BayesNet ${Sources}) add_library(BayesNet ${Sources})
target_link_libraries(BayesNet fimdlp "${TORCH_LIBRARIES}") target_link_libraries(BayesNet mdlp "${TORCH_LIBRARIES}")

View File

@ -9,7 +9,15 @@
#include "Classifier.h" #include "Classifier.h"
namespace bayesnet { namespace bayesnet {
Classifier::Classifier(Network model) : model(model), m(0), n(0), metrics(Metrics()), fitted(false) {} Classifier::Classifier(Network model) : model(model), m(0), n(0), metrics(Metrics()), fitted(false), device(torch::kCPU)
{
if (torch::cuda::is_available()) {
device = torch::Device(torch::kCUDA);
std::cout << "CUDA is available! Using GPU." << std::endl;
} else {
std::cout << "CUDA is not available. Using CPU." << std::endl;
}
}
const std::string CLASSIFIER_NOT_FITTED = "Classifier has not been fitted"; const std::string CLASSIFIER_NOT_FITTED = "Classifier has not been fitted";
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, const Smoothing_t smoothing) 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, const Smoothing_t smoothing)
{ {
@ -31,7 +39,7 @@ namespace bayesnet {
{ {
try { try {
auto yresized = torch::transpose(ytmp.view({ ytmp.size(0), 1 }), 0, 1); auto yresized = torch::transpose(ytmp.view({ ytmp.size(0), 1 }), 0, 1);
dataset = torch::cat({ dataset, yresized }, 0); dataset = torch::cat({ dataset, yresized }, 0).to(device);
} }
catch (const std::exception& e) { catch (const std::exception& e) {
std::stringstream oss; std::stringstream oss;
@ -50,7 +58,7 @@ namespace bayesnet {
{ {
dataset = X; dataset = X;
buildDataset(y); buildDataset(y);
const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble); const torch::Tensor weights = torch::full({ dataset.size(1) }, 1.0 / dataset.size(1), torch::kDouble).to(device);
return build(features, className, states, weights, smoothing); return build(features, className, states, weights, smoothing);
} }
// X is nxm where n is the number of features and m the number of samples // X is nxm where n is the number of features and m the number of samples

View File

@ -38,6 +38,7 @@ namespace bayesnet {
std::string dump_cpt() const override; std::string dump_cpt() const override;
void setHyperparameters(const nlohmann::json& hyperparameters) override; //For classifiers that don't have hyperparameters void setHyperparameters(const nlohmann::json& hyperparameters) override; //For classifiers that don't have hyperparameters
protected: protected:
torch::Device device;
bool fitted; bool fitted;
unsigned int m, n; // m: number of samples, n: number of features unsigned int m, n; // m: number of samples, n: number of features
Network model; Network model;

View File

@ -20,8 +20,7 @@ namespace bayesnet {
// Fills std::vectors Xv & yv with the data from tensors X_ (discretized) & y // Fills std::vectors Xv & yv with the data from tensors X_ (discretized) & y
states = fit_local_discretization(y); states = fit_local_discretization(y);
// We have discretized the input data // We have discretized the input data
// 1st we need to fit the model to build the normal AODE structure, Ensemble::fit // 1st we need to fit the model to build the normal TAN structure, TAN::fit initializes the base Bayesian network
// calls buildModel to initialize the base models
Ensemble::fit(dataset, features, className, states, smoothing); Ensemble::fit(dataset, features, className, states, smoothing);
return *this; return *this;

View File

@ -59,9 +59,6 @@ namespace bayesnet {
std::vector<int> featuresUsed; std::vector<int> featuresUsed;
if (selectFeatures) { if (selectFeatures) {
featuresUsed = initializeModels(smoothing); featuresUsed = initializeModels(smoothing);
if (featuresUsed.size() == 0) {
return;
}
auto ypred = predict(X_train); auto ypred = 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

View File

@ -209,7 +209,7 @@ namespace bayesnet {
pthread_setname_np(threadName.c_str()); pthread_setname_np(threadName.c_str());
#endif #endif
double numStates = static_cast<double>(node.second->getNumStates()); double numStates = static_cast<double>(node.second->getNumStates());
double smoothing_factor; double smoothing_factor = 0.0;
switch (smoothing) { switch (smoothing) {
case Smoothing_t::ORIGINAL: case Smoothing_t::ORIGINAL:
smoothing_factor = 1.0 / n_samples; smoothing_factor = 1.0 / n_samples;
@ -221,7 +221,7 @@ namespace bayesnet {
smoothing_factor = 1 / numStates; smoothing_factor = 1 / numStates;
break; break;
default: default:
smoothing_factor = 0.0; // No smoothing throw std::invalid_argument("Smoothing method not recognized " + std::to_string(static_cast<int>(smoothing)));
} }
node.second->computeCPT(samples, features, smoothing_factor, weights); node.second->computeCPT(samples, features, smoothing_factor, weights);
semaphore.release(); semaphore.release();
@ -234,6 +234,16 @@ namespace bayesnet {
for (auto& thread : threads) { for (auto& thread : threads) {
thread.join(); thread.join();
} }
// std::fstream file;
// file.open("cpt.txt", std::fstream::out | std::fstream::app);
// file << std::string(80, '*') << std::endl;
// for (const auto& item : graph("Test")) {
// file << item << std::endl;
// }
// file << std::string(80, '-') << std::endl;
// file << dump_cpt() << std::endl;
// file << std::string(80, '=') << std::endl;
// file.close();
fitted = true; fitted = true;
} }
torch::Tensor Network::predict_tensor(const torch::Tensor& samples, const bool proba) torch::Tensor Network::predict_tensor(const torch::Tensor& samples, const bool proba)

View File

@ -97,7 +97,7 @@ namespace bayesnet {
dimensions.push_back(numStates); dimensions.push_back(numStates);
transform(parents.begin(), parents.end(), back_inserter(dimensions), [](const auto& parent) { return parent->getNumStates(); }); transform(parents.begin(), parents.end(), back_inserter(dimensions), [](const auto& parent) { return parent->getNumStates(); });
// Create a tensor of zeros with the dimensions of the CPT // Create a tensor of zeros with the dimensions of the CPT
cpTable = torch::zeros(dimensions, torch::kDouble) + smoothing; cpTable = torch::zeros(dimensions, torch::kDouble).to(device) + smoothing;
// Fill table with counts // Fill table with counts
auto pos = find(features.begin(), features.end(), name); auto pos = find(features.begin(), features.end(), name);
if (pos == features.end()) { if (pos == features.end()) {

View File

@ -53,14 +53,14 @@ namespace bayesnet {
} }
} }
void MST::insertElement(std::list<int>& variables, int variable) void insertElement(std::list<int>& variables, int variable)
{ {
if (std::find(variables.begin(), variables.end(), variable) == variables.end()) { if (std::find(variables.begin(), variables.end(), variable) == variables.end()) {
variables.push_front(variable); variables.push_front(variable);
} }
} }
std::vector<std::pair<int, int>> MST::reorder(std::vector<std::pair<float, std::pair<int, int>>> T, int root_original) std::vector<std::pair<int, int>> reorder(std::vector<std::pair<float, std::pair<int, int>>> T, int root_original)
{ {
// Create the edges of a DAG from the MST // Create the edges of a DAG from the MST
// replacing unordered_set with list because unordered_set cannot guarantee the order of the elements inserted // replacing unordered_set with list because unordered_set cannot guarantee the order of the elements inserted

View File

@ -14,8 +14,6 @@ namespace bayesnet {
public: public:
MST() = default; MST() = default;
MST(const std::vector<std::string>& features, const torch::Tensor& weights, const int root); MST(const std::vector<std::string>& features, const torch::Tensor& weights, const int root);
void insertElement(std::list<int>& variables, int variable);
std::vector<std::pair<int, int>> reorder(std::vector<std::pair<float, std::pair<int, int>>> T, int root_original);
std::vector<std::pair<int, int>> maximumSpanningTree(); std::vector<std::pair<int, int>> maximumSpanningTree();
private: private:
torch::Tensor weights; torch::Tensor weights;

View File

@ -137,7 +137,7 @@
include(CMakeParseArguments) include(CMakeParseArguments)
option(CODE_COVERAGE_VERBOSE "Verbose information" TRUE) option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
# Check prereqs # Check prereqs
find_program( GCOV_PATH gcov ) find_program( GCOV_PATH gcov )
@ -160,11 +160,7 @@ foreach(LANG ${LANGUAGES})
endif() endif()
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU" elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang") AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
if ("${LANG}" MATCHES "CUDA") message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
message(STATUS "Ignoring CUDA")
else()
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif()
endif() endif()
endforeach() endforeach()

View File

@ -1,16 +1,36 @@
@startuml @startuml
title clang-uml class diagram model title clang-uml class diagram model
class "bayesnet::Node" as C_0010428199432536647474 class "bayesnet::Metrics" as C_0000736965376885623323
class C_0010428199432536647474 #aliceblue;line:blue;line.dotted;text:blue { class C_0000736965376885623323 #aliceblue;line:blue;line.dotted;text:blue {
+Metrics() = default : void
+Metrics(const torch::Tensor & samples, const std::vector<std::string> & features, const std::string & className, const int classNumStates) : void
+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) : void
..
+SelectKBestWeighted(const torch::Tensor & weights, bool ascending = false, unsigned int k = 0) : std::vector<int>
+conditionalEdge(const torch::Tensor & weights) : torch::Tensor
+conditionalEdgeWeights(std::vector<float> & weights) : std::vector<float>
#doCombinations<T>(const std::vector<T> & source) : std::vector<std::pair<T, T> >
#entropy(const torch::Tensor & feature, const torch::Tensor & weights) : double
+getScoresKBest() const : std::vector<double>
+maximumSpanningTree(const std::vector<std::string> & features, const torch::Tensor & weights, const int root) : std::vector<std::pair<int,int>>
+mutualInformation(const torch::Tensor & firstFeature, const torch::Tensor & secondFeature, const torch::Tensor & weights) : double
#pop_first<T>(std::vector<T> & v) : T
__
#className : std::string
#features : std::vector<std::string>
#samples : torch::Tensor
}
class "bayesnet::Node" as C_0001303524929067080934
class C_0001303524929067080934 #aliceblue;line:blue;line.dotted;text:blue {
+Node(const std::string &) : void +Node(const std::string &) : void
.. ..
+addChild(Node *) : void +addChild(Node *) : void
+addParent(Node *) : void +addParent(Node *) : void
+clear() : void +clear() : void
+computeCPT(const torch::Tensor & dataset, const std::vector<std::string> & features, const double smoothing, const torch::Tensor & weights) : void +computeCPT(const torch::Tensor & dataset, const std::vector<std::string> & features, const double laplaceSmoothing, const torch::Tensor & weights) : void
+getCPT() : torch::Tensor & +getCPT() : torch::Tensor &
+getChildren() : std::vector<Node *> & +getChildren() : std::vector<Node *> &
+getFactorValue(std::map<std::string,int> &) : double +getFactorValue(std::map<std::string,int> &) : float
+getName() const : std::string +getName() const : std::string
+getNumStates() const : int +getNumStates() const : int
+getParents() : std::vector<Node *> & +getParents() : std::vector<Node *> &
@ -21,29 +41,24 @@ class C_0010428199432536647474 #aliceblue;line:blue;line.dotted;text:blue {
+setNumStates(int) : void +setNumStates(int) : void
__ __
} }
enum "bayesnet::Smoothing_t" as C_0013393078277439680282 class "bayesnet::Network" as C_0001186707649890429575
enum C_0013393078277439680282 { class C_0001186707649890429575 #aliceblue;line:blue;line.dotted;text:blue {
NONE
ORIGINAL
LAPLACE
CESTNIK
}
class "bayesnet::Network" as C_0009493661199123436603
class C_0009493661199123436603 #aliceblue;line:blue;line.dotted;text:blue {
+Network() : void +Network() : void
+Network(float) : void
+Network(const Network &) : void +Network(const Network &) : void
+~Network() = default : void +~Network() = default : void
.. ..
+addEdge(const std::string &, const std::string &) : void +addEdge(const std::string &, const std::string &) : void
+addNode(const std::string &) : void +addNode(const std::string &) : void
+dump_cpt() const : std::string +dump_cpt() const : std::string
+fit(const torch::Tensor & samples, const torch::Tensor & weights, const std::vector<std::string> & featureNames, const std::string & className, const std::map<std::string,std::vector<int>> & states, const Smoothing_t smoothing) : void +fit(const torch::Tensor & samples, const torch::Tensor & weights, const std::vector<std::string> & featureNames, const std::string & className, const std::map<std::string,std::vector<int>> & states) : void
+fit(const torch::Tensor & X, const torch::Tensor & y, const torch::Tensor & weights, const std::vector<std::string> & featureNames, const std::string & className, const std::map<std::string,std::vector<int>> & states, const Smoothing_t smoothing) : void +fit(const torch::Tensor & X, const torch::Tensor & y, const torch::Tensor & weights, const std::vector<std::string> & featureNames, const std::string & className, const std::map<std::string,std::vector<int>> & states) : void
+fit(const std::vector<std::vector<int>> & input_data, const std::vector<int> & labels, const std::vector<double> & weights, const std::vector<std::string> & featureNames, const std::string & className, const std::map<std::string,std::vector<int>> & states, const Smoothing_t smoothing) : void +fit(const std::vector<std::vector<int>> & input_data, const std::vector<int> & labels, const std::vector<double> & weights, const std::vector<std::string> & featureNames, const std::string & className, const std::map<std::string,std::vector<int>> & states) : void
+getClassName() const : std::string +getClassName() const : std::string
+getClassNumStates() const : int +getClassNumStates() const : int
+getEdges() const : std::vector<std::pair<std::string,std::string>> +getEdges() const : std::vector<std::pair<std::string,std::string>>
+getFeatures() const : std::vector<std::string> +getFeatures() const : std::vector<std::string>
+getMaxThreads() const : float
+getNodes() : std::map<std::string,std::unique_ptr<Node>> & +getNodes() : std::map<std::string,std::unique_ptr<Node>> &
+getNumEdges() const : int +getNumEdges() const : int
+getSamples() : torch::Tensor & +getSamples() : torch::Tensor &
@ -61,21 +76,21 @@ class C_0009493661199123436603 #aliceblue;line:blue;line.dotted;text:blue {
+version() : std::string +version() : std::string
__ __
} }
enum "bayesnet::status_t" as C_0005907365846270811004 enum "bayesnet::status_t" as C_0000738420730783851375
enum C_0005907365846270811004 { enum C_0000738420730783851375 {
NORMAL NORMAL
WARNING WARNING
ERROR ERROR
} }
abstract "bayesnet::BaseClassifier" as C_0002617087915615796317 abstract "bayesnet::BaseClassifier" as C_0000327135989451974539
abstract C_0002617087915615796317 #aliceblue;line:blue;line.dotted;text:blue { abstract C_0000327135989451974539 #aliceblue;line:blue;line.dotted;text:blue {
+~BaseClassifier() = default : void +~BaseClassifier() = default : void
.. ..
{abstract} +dump_cpt() const = 0 : std::string {abstract} +dump_cpt() const = 0 : std::string
{abstract} +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, const Smoothing_t smoothing) = 0 : BaseClassifier & {abstract} +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 : BaseClassifier &
{abstract} +fit(torch::Tensor & dataset, const std::vector<std::string> & features, const std::string & className, std::map<std::string,std::vector<int>> & states, const Smoothing_t smoothing) = 0 : BaseClassifier & {abstract} +fit(torch::Tensor & dataset, const std::vector<std::string> & features, const std::string & className, std::map<std::string,std::vector<int>> & states) = 0 : BaseClassifier &
{abstract} +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, const Smoothing_t smoothing) = 0 : BaseClassifier & {abstract} +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 : BaseClassifier &
{abstract} +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, const Smoothing_t smoothing) = 0 : BaseClassifier & {abstract} +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) = 0 : BaseClassifier &
{abstract} +getClassNumStates() const = 0 : int {abstract} +getClassNumStates() const = 0 : int
{abstract} +getNotes() const = 0 : std::vector<std::string> {abstract} +getNotes() const = 0 : std::vector<std::string>
{abstract} +getNumberOfEdges() const = 0 : int {abstract} +getNumberOfEdges() const = 0 : int
@ -94,35 +109,12 @@ abstract C_0002617087915615796317 #aliceblue;line:blue;line.dotted;text:blue {
{abstract} +setHyperparameters(const nlohmann::json & hyperparameters) = 0 : void {abstract} +setHyperparameters(const nlohmann::json & hyperparameters) = 0 : void
{abstract} +show() const = 0 : std::vector<std::string> {abstract} +show() const = 0 : std::vector<std::string>
{abstract} +topological_order() = 0 : std::vector<std::string> {abstract} +topological_order() = 0 : std::vector<std::string>
{abstract} #trainModel(const torch::Tensor & weights, const Smoothing_t smoothing) = 0 : void {abstract} #trainModel(const torch::Tensor & weights) = 0 : void
__ __
#validHyperparameters : std::vector<std::string> #validHyperparameters : std::vector<std::string>
} }
class "bayesnet::Metrics" as C_0005895723015084986588 abstract "bayesnet::Classifier" as C_0002043996622900301644
class C_0005895723015084986588 #aliceblue;line:blue;line.dotted;text:blue { abstract C_0002043996622900301644 #aliceblue;line:blue;line.dotted;text:blue {
+Metrics() = default : void
+Metrics(const torch::Tensor & samples, const std::vector<std::string> & features, const std::string & className, const int classNumStates) : void
+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) : void
..
+SelectKBestWeighted(const torch::Tensor & weights, bool ascending = false, unsigned int k = 0) : std::vector<int>
+SelectKPairs(const torch::Tensor & weights, std::vector<int> & featuresExcluded, bool ascending = false, unsigned int k = 0) : std::vector<std::pair<int,int>>
+conditionalEdge(const torch::Tensor & weights) : torch::Tensor
+conditionalEntropy(const torch::Tensor & firstFeature, const torch::Tensor & secondFeature, const torch::Tensor & labels, const torch::Tensor & weights) : double
+conditionalMutualInformation(const torch::Tensor & firstFeature, const torch::Tensor & secondFeature, const torch::Tensor & labels, const torch::Tensor & weights) : double
#doCombinations<T>(const std::vector<T> & source) : std::vector<std::pair<T, T> >
+entropy(const torch::Tensor & feature, const torch::Tensor & weights) : double
+getScoresKBest() const : std::vector<double>
+getScoresKPairs() const : std::vector<std::pair<std::pair<int,int>,double>>
+maximumSpanningTree(const std::vector<std::string> & features, const torch::Tensor & weights, const int root) : std::vector<std::pair<int,int>>
+mutualInformation(const torch::Tensor & firstFeature, const torch::Tensor & secondFeature, const torch::Tensor & weights) : double
#pop_first<T>(std::vector<T> & v) : T
__
#className : std::string
#features : std::vector<std::string>
#samples : torch::Tensor
}
abstract "bayesnet::Classifier" as C_0016351972983202413152
abstract C_0016351972983202413152 #aliceblue;line:blue;line.dotted;text:blue {
+Classifier(Network model) : void +Classifier(Network model) : void
+~Classifier() = default : void +~Classifier() = default : void
.. ..
@ -131,10 +123,10 @@ abstract C_0016351972983202413152 #aliceblue;line:blue;line.dotted;text:blue {
{abstract} #buildModel(const torch::Tensor & weights) = 0 : void {abstract} #buildModel(const torch::Tensor & weights) = 0 : void
#checkFitParameters() : void #checkFitParameters() : void
+dump_cpt() const : std::string +dump_cpt() const : std::string
+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, const Smoothing_t smoothing) : 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) : 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, const Smoothing_t smoothing) : 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) : Classifier &
+fit(torch::Tensor & dataset, const std::vector<std::string> & features, const std::string & className, std::map<std::string,std::vector<int>> & states, const Smoothing_t smoothing) : Classifier & +fit(torch::Tensor & dataset, const std::vector<std::string> & features, const std::string & className, std::map<std::string,std::vector<int>> & states) : 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, const Smoothing_t smoothing) : 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) : Classifier &
+getClassNumStates() const : int +getClassNumStates() const : int
+getNotes() const : std::vector<std::string> +getNotes() const : std::vector<std::string>
+getNumberOfEdges() const : int +getNumberOfEdges() const : int
@ -151,7 +143,7 @@ abstract C_0016351972983202413152 #aliceblue;line:blue;line.dotted;text:blue {
+setHyperparameters(const nlohmann::json & hyperparameters) : void +setHyperparameters(const nlohmann::json & hyperparameters) : void
+show() const : std::vector<std::string> +show() const : std::vector<std::string>
+topological_order() : std::vector<std::string> +topological_order() : std::vector<std::string>
#trainModel(const torch::Tensor & weights, const Smoothing_t smoothing) : void #trainModel(const torch::Tensor & weights) : void
__ __
#className : std::string #className : std::string
#dataset : torch::Tensor #dataset : torch::Tensor
@ -165,8 +157,8 @@ __
#states : std::map<std::string,std::vector<int>> #states : std::map<std::string,std::vector<int>>
#status : status_t #status : status_t
} }
class "bayesnet::KDB" as C_0008902920152122000044 class "bayesnet::KDB" as C_0001112865019015250005
class C_0008902920152122000044 #aliceblue;line:blue;line.dotted;text:blue { class C_0001112865019015250005 #aliceblue;line:blue;line.dotted;text:blue {
+KDB(int k, float theta = 0.03) : void +KDB(int k, float theta = 0.03) : void
+~KDB() = default : void +~KDB() = default : void
.. ..
@ -175,26 +167,8 @@ class C_0008902920152122000044 #aliceblue;line:blue;line.dotted;text:blue {
+setHyperparameters(const nlohmann::json & hyperparameters_) : void +setHyperparameters(const nlohmann::json & hyperparameters_) : void
__ __
} }
class "bayesnet::SPODE" as C_0004096182510460307610 class "bayesnet::TAN" as C_0001760994424884323017
class C_0004096182510460307610 #aliceblue;line:blue;line.dotted;text:blue { class C_0001760994424884323017 #aliceblue;line:blue;line.dotted;text:blue {
+SPODE(int root) : void
+~SPODE() = default : void
..
#buildModel(const torch::Tensor & weights) : void
+graph(const std::string & name = "SPODE") const : std::vector<std::string>
__
}
class "bayesnet::SPnDE" as C_0016268916386101512883
class C_0016268916386101512883 #aliceblue;line:blue;line.dotted;text:blue {
+SPnDE(std::vector<int> parents) : void
+~SPnDE() = default : void
..
#buildModel(const torch::Tensor & weights) : void
+graph(const std::string & name = "SPnDE") const : std::vector<std::string>
__
}
class "bayesnet::TAN" as C_0014087955399074584137
class C_0014087955399074584137 #aliceblue;line:blue;line.dotted;text:blue {
+TAN() : void +TAN() : void
+~TAN() = default : void +~TAN() = default : void
.. ..
@ -202,8 +176,8 @@ class C_0014087955399074584137 #aliceblue;line:blue;line.dotted;text:blue {
+graph(const std::string & name = "TAN") const : std::vector<std::string> +graph(const std::string & name = "TAN") const : std::vector<std::string>
__ __
} }
class "bayesnet::Proposal" as C_0017759964713298103839 class "bayesnet::Proposal" as C_0002219995589162262979
class C_0017759964713298103839 #aliceblue;line:blue;line.dotted;text:blue { class C_0002219995589162262979 #aliceblue;line:blue;line.dotted;text:blue {
+Proposal(torch::Tensor & pDataset, std::vector<std::string> & features_, std::string & className_) : void +Proposal(torch::Tensor & pDataset, std::vector<std::string> & features_, std::string & className_) : void
+~Proposal() : void +~Proposal() : void
.. ..
@ -216,42 +190,74 @@ __
#discretizers : map<std::string,mdlp::CPPFImdlp *> #discretizers : map<std::string,mdlp::CPPFImdlp *>
#y : torch::Tensor #y : torch::Tensor
} }
class "bayesnet::KDBLd" as C_0002756018222998454702 class "bayesnet::TANLd" as C_0001668829096702037834
class C_0002756018222998454702 #aliceblue;line:blue;line.dotted;text:blue { class C_0001668829096702037834 #aliceblue;line:blue;line.dotted;text:blue {
+KDBLd(int k) : void
+~KDBLd() = default : void
..
+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, const Smoothing_t smoothing) : KDBLd &
+graph(const std::string & name = "KDB") const : std::vector<std::string>
+predict(torch::Tensor & X) : torch::Tensor
{static} +version() : std::string
__
}
class "bayesnet::SPODELd" as C_0010957245114062042836
class C_0010957245114062042836 #aliceblue;line:blue;line.dotted;text:blue {
+SPODELd(int root) : void
+~SPODELd() = default : void
..
+commonFit(const std::vector<std::string> & features, const std::string & className, std::map<std::string,std::vector<int>> & states, const Smoothing_t smoothing) : SPODELd &
+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, const Smoothing_t smoothing) : SPODELd &
+fit(torch::Tensor & dataset, const std::vector<std::string> & features, const std::string & className, std::map<std::string,std::vector<int>> & states, const Smoothing_t smoothing) : SPODELd &
+graph(const std::string & name = "SPODELd") const : std::vector<std::string>
+predict(torch::Tensor & X) : torch::Tensor
{static} +version() : std::string
__
}
class "bayesnet::TANLd" as C_0013350632773616302678
class C_0013350632773616302678 #aliceblue;line:blue;line.dotted;text:blue {
+TANLd() : void +TANLd() : void
+~TANLd() = default : void +~TANLd() = default : void
.. ..
+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, const Smoothing_t smoothing) : TANLd & +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) : TANLd &
+graph(const std::string & name = "TANLd") const : std::vector<std::string> +graph(const std::string & name = "TAN") const : std::vector<std::string>
+predict(torch::Tensor & X) : torch::Tensor +predict(torch::Tensor & X) : torch::Tensor
{static} +version() : std::string
__ __
} }
class "bayesnet::Ensemble" as C_0015881931090842884611 abstract "bayesnet::FeatureSelect" as C_0001695326193250580823
class C_0015881931090842884611 #aliceblue;line:blue;line.dotted;text:blue { abstract C_0001695326193250580823 #aliceblue;line:blue;line.dotted;text:blue {
+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) : void
+~FeatureSelect() : void
..
#computeMeritCFS() : double
#computeSuFeatures(const int a, const int b) : double
#computeSuLabels() : void
{abstract} +fit() = 0 : void
+getFeatures() const : std::vector<int>
+getScores() const : std::vector<double>
#initialize() : void
#symmetricalUncertainty(int a, int b) : double
__
#fitted : bool
#maxFeatures : int
#selectedFeatures : std::vector<int>
#selectedScores : std::vector<double>
#suFeatures : std::map<std::pair<int,int>,double>
#suLabels : std::vector<double>
#weights : const torch::Tensor &
}
class "bayesnet::CFS" as C_0000011627355691342494
class C_0000011627355691342494 #aliceblue;line:blue;line.dotted;text:blue {
+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) : void
+~CFS() : void
..
+fit() : void
__
}
class "bayesnet::FCBF" as C_0000144682015341746929
class C_0000144682015341746929 #aliceblue;line:blue;line.dotted;text:blue {
+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) : void
+~FCBF() : void
..
+fit() : void
__
}
class "bayesnet::IWSS" as C_0000008268514674428553
class C_0000008268514674428553 #aliceblue;line:blue;line.dotted;text:blue {
+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) : void
+~IWSS() : void
..
+fit() : void
__
}
class "bayesnet::SPODE" as C_0000512022813807538451
class C_0000512022813807538451 #aliceblue;line:blue;line.dotted;text:blue {
+SPODE(int root) : void
+~SPODE() = default : void
..
#buildModel(const torch::Tensor & weights) : void
+graph(const std::string & name = "SPODE") const : std::vector<std::string>
__
}
class "bayesnet::Ensemble" as C_0001985241386355360576
class C_0001985241386355360576 #aliceblue;line:blue;line.dotted;text:blue {
+Ensemble(bool predict_voting = true) : void +Ensemble(bool predict_voting = true) : void
+~Ensemble() = default : void +~Ensemble() = default : void
.. ..
@ -274,7 +280,7 @@ class C_0015881931090842884611 #aliceblue;line:blue;line.dotted;text:blue {
+score(torch::Tensor & X, torch::Tensor & y) : float +score(torch::Tensor & X, torch::Tensor & y) : float
+show() const : std::vector<std::string> +show() const : std::vector<std::string>
+topological_order() : std::vector<std::string> +topological_order() : std::vector<std::string>
#trainModel(const torch::Tensor & weights, const Smoothing_t smoothing) : void #trainModel(const torch::Tensor & weights) : void
#voting(torch::Tensor & votes) : torch::Tensor #voting(torch::Tensor & votes) : torch::Tensor
__ __
#models : std::vector<std::unique_ptr<Classifier>> #models : std::vector<std::unique_ptr<Classifier>>
@ -282,223 +288,41 @@ __
#predict_voting : bool #predict_voting : bool
#significanceModels : std::vector<double> #significanceModels : std::vector<double>
} }
class "bayesnet::A2DE" as C_0001410789567057647859 class "bayesnet::(anonymous_45089536)" as C_0001186398587753535158
class C_0001410789567057647859 #aliceblue;line:blue;line.dotted;text:blue { class C_0001186398587753535158 #aliceblue;line:blue;line.dotted;text:blue {
+A2DE(bool predict_voting = false) : void
+~A2DE() : void
..
#buildModel(const torch::Tensor & weights) : void
+graph(const std::string & title = "A2DE") const : std::vector<std::string>
+setHyperparameters(const nlohmann::json & hyperparameters) : void
__
}
class "bayesnet::AODE" as C_0006288892608974306258
class C_0006288892608974306258 #aliceblue;line:blue;line.dotted;text:blue {
+AODE(bool predict_voting = false) : void
+~AODE() : void
..
#buildModel(const torch::Tensor & weights) : void
+graph(const std::string & title = "AODE") const : std::vector<std::string>
+setHyperparameters(const nlohmann::json & hyperparameters) : void
__
}
abstract "bayesnet::FeatureSelect" as C_0013562609546004646591
abstract C_0013562609546004646591 #aliceblue;line:blue;line.dotted;text:blue {
+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) : void
+~FeatureSelect() : void
..
#computeMeritCFS() : double
#computeSuFeatures(const int a, const int b) : double
#computeSuLabels() : void
{abstract} +fit() = 0 : void
+getFeatures() const : std::vector<int>
+getScores() const : std::vector<double>
#initialize() : void
#symmetricalUncertainty(int a, int b) : double
__
#fitted : bool
#maxFeatures : int
#selectedFeatures : std::vector<int>
#selectedScores : std::vector<double>
#suFeatures : std::map<std::pair<int,int>,double>
#suLabels : std::vector<double>
#weights : const torch::Tensor &
}
class "bayesnet::(anonymous_60342586)" as C_0005584545181746538542
class C_0005584545181746538542 #aliceblue;line:blue;line.dotted;text:blue {
__ __
+CFS : std::string +CFS : std::string
+FCBF : std::string +FCBF : std::string
+IWSS : std::string +IWSS : std::string
} }
class "bayesnet::(anonymous_60343240)" as C_0016227156982041949444 class "bayesnet::(anonymous_45090163)" as C_0000602764946063116717
class C_0016227156982041949444 #aliceblue;line:blue;line.dotted;text:blue { class C_0000602764946063116717 #aliceblue;line:blue;line.dotted;text:blue {
__ __
+ASC : std::string +ASC : std::string
+DESC : std::string +DESC : std::string
+RAND : std::string +RAND : std::string
} }
class "bayesnet::Boost" as C_0009819322948617116148 class "bayesnet::BoostAODE" as C_0000358471592399852382
class C_0009819322948617116148 #aliceblue;line:blue;line.dotted;text:blue { class C_0000358471592399852382 #aliceblue;line:blue;line.dotted;text:blue {
+Boost(bool predict_voting = false) : void
+~Boost() = default : void
..
#buildModel(const torch::Tensor & weights) : void
#featureSelection(torch::Tensor & weights_) : std::vector<int>
+setHyperparameters(const nlohmann::json & hyperparameters_) : void
#update_weights(torch::Tensor & ytrain, torch::Tensor & ypred, torch::Tensor & weights) : std::tuple<torch::Tensor &,double,bool>
#update_weights_block(int k, torch::Tensor & ytrain, torch::Tensor & weights) : std::tuple<torch::Tensor &,double,bool>
__
#X_test : torch::Tensor
#X_train : torch::Tensor
#bisection : bool
#block_update : bool
#convergence : bool
#convergence_best : bool
#featureSelector : FeatureSelect *
#maxTolerance : int
#order_algorithm : std::string
#selectFeatures : bool
#select_features_algorithm : std::string
#threshold : double
#y_test : torch::Tensor
#y_train : torch::Tensor
}
class "bayesnet::AODELd" as C_0003898187834670349177
class C_0003898187834670349177 #aliceblue;line:blue;line.dotted;text:blue {
+AODELd(bool predict_voting = true) : void
+~AODELd() = default : void
..
#buildModel(const torch::Tensor & weights) : void
+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_, const Smoothing_t smoothing) : AODELd &
+graph(const std::string & name = "AODELd") const : std::vector<std::string>
#trainModel(const torch::Tensor & weights, const Smoothing_t smoothing) : void
__
}
class "bayesnet::(anonymous_60275628)" as C_0009086919615463763584
class C_0009086919615463763584 #aliceblue;line:blue;line.dotted;text:blue {
__
+CFS : std::string
+FCBF : std::string
+IWSS : std::string
}
class "bayesnet::(anonymous_60276282)" as C_0015251985607563196159
class C_0015251985607563196159 #aliceblue;line:blue;line.dotted;text:blue {
__
+ASC : std::string
+DESC : std::string
+RAND : std::string
}
class "bayesnet::BoostA2DE" as C_0000272055465257861326
class C_0000272055465257861326 #aliceblue;line:blue;line.dotted;text:blue {
+BoostA2DE(bool predict_voting = false) : void
+~BoostA2DE() = default : void
..
+graph(const std::string & title = "BoostA2DE") const : std::vector<std::string>
#trainModel(const torch::Tensor & weights, const Smoothing_t smoothing) : void
__
}
class "bayesnet::(anonymous_60275502)" as C_0016033655851510053155
class C_0016033655851510053155 #aliceblue;line:blue;line.dotted;text:blue {
__
+CFS : std::string
+FCBF : std::string
+IWSS : std::string
}
class "bayesnet::(anonymous_60276156)" as C_0000379522761622473555
class C_0000379522761622473555 #aliceblue;line:blue;line.dotted;text:blue {
__
+ASC : std::string
+DESC : std::string
+RAND : std::string
}
class "bayesnet::BoostAODE" as C_0002867772739198819061
class C_0002867772739198819061 #aliceblue;line:blue;line.dotted;text:blue {
+BoostAODE(bool predict_voting = false) : void +BoostAODE(bool predict_voting = false) : void
+~BoostAODE() = default : void +~BoostAODE() = default : void
.. ..
#buildModel(const torch::Tensor & weights) : void
+graph(const std::string & title = "BoostAODE") const : std::vector<std::string> +graph(const std::string & title = "BoostAODE") const : std::vector<std::string>
#trainModel(const torch::Tensor & weights, const Smoothing_t smoothing) : void +setHyperparameters(const nlohmann::json & hyperparameters_) : void
#trainModel(const torch::Tensor & weights) : void
__ __
} }
class "bayesnet::CFS" as C_0000093018845530739957 class "bayesnet::MST" as C_0000131858426172291700
class C_0000093018845530739957 #aliceblue;line:blue;line.dotted;text:blue { class C_0000131858426172291700 #aliceblue;line:blue;line.dotted;text:blue {
+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) : void
+~CFS() : void
..
+fit() : void
__
}
class "bayesnet::FCBF" as C_0001157456122733975432
class C_0001157456122733975432 #aliceblue;line:blue;line.dotted;text:blue {
+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) : void
+~FCBF() : void
..
+fit() : void
__
}
class "bayesnet::IWSS" as C_0000066148117395428429
class C_0000066148117395428429 #aliceblue;line:blue;line.dotted;text:blue {
+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) : void
+~IWSS() : void
..
+fit() : void
__
}
class "bayesnet::(anonymous_60730495)" as C_0004857727320042830573
class C_0004857727320042830573 #aliceblue;line:blue;line.dotted;text:blue {
__
+CFS : std::string
+FCBF : std::string
+IWSS : std::string
}
class "bayesnet::(anonymous_60731150)" as C_0000076541533312623385
class C_0000076541533312623385 #aliceblue;line:blue;line.dotted;text:blue {
__
+ASC : std::string
+DESC : std::string
+RAND : std::string
}
class "bayesnet::(anonymous_60653004)" as C_0001444063444142949758
class C_0001444063444142949758 #aliceblue;line:blue;line.dotted;text:blue {
__
+CFS : std::string
+FCBF : std::string
+IWSS : std::string
}
class "bayesnet::(anonymous_60653658)" as C_0007139277546931322856
class C_0007139277546931322856 #aliceblue;line:blue;line.dotted;text:blue {
__
+ASC : std::string
+DESC : std::string
+RAND : std::string
}
class "bayesnet::(anonymous_60731375)" as C_0010493853592456211189
class C_0010493853592456211189 #aliceblue;line:blue;line.dotted;text:blue {
__
+CFS : std::string
+FCBF : std::string
+IWSS : std::string
}
class "bayesnet::(anonymous_60732030)" as C_0007011438637915849564
class C_0007011438637915849564 #aliceblue;line:blue;line.dotted;text:blue {
__
+ASC : std::string
+DESC : std::string
+RAND : std::string
}
class "bayesnet::MST" as C_0001054867409378333602
class C_0001054867409378333602 #aliceblue;line:blue;line.dotted;text:blue {
+MST() = default : void +MST() = default : void
+MST(const std::vector<std::string> & features, const torch::Tensor & weights, const int root) : void +MST(const std::vector<std::string> & features, const torch::Tensor & weights, const int root) : void
.. ..
+insertElement(std::list<int> & variables, int variable) : void
+maximumSpanningTree() : std::vector<std::pair<int,int>> +maximumSpanningTree() : std::vector<std::pair<int,int>>
+reorder(std::vector<std::pair<float,std::pair<int,int>>> T, int root_original) : std::vector<std::pair<int,int>>
__ __
} }
class "bayesnet::Graph" as C_0009576333456015187741 class "bayesnet::Graph" as C_0001197041682001898467
class C_0009576333456015187741 #aliceblue;line:blue;line.dotted;text:blue { class C_0001197041682001898467 #aliceblue;line:blue;line.dotted;text:blue {
+Graph(int V) : void +Graph(int V) : void
.. ..
+addEdge(int u, int v, float wt) : void +addEdge(int u, int v, float wt) : void
@ -508,73 +332,81 @@ class C_0009576333456015187741 #aliceblue;line:blue;line.dotted;text:blue {
+union_set(int u, int v) : void +union_set(int u, int v) : void
__ __
} }
C_0010428199432536647474 --> C_0010428199432536647474 : -parents class "bayesnet::KDBLd" as C_0000344502277874806837
C_0010428199432536647474 --> C_0010428199432536647474 : -children class C_0000344502277874806837 #aliceblue;line:blue;line.dotted;text:blue {
C_0009493661199123436603 ..> C_0013393078277439680282 +KDBLd(int k) : void
C_0009493661199123436603 o-- C_0010428199432536647474 : -nodes +~KDBLd() = default : void
C_0002617087915615796317 ..> C_0013393078277439680282 ..
C_0002617087915615796317 ..> C_0005907365846270811004 +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) : KDBLd &
C_0016351972983202413152 ..> C_0013393078277439680282 +graph(const std::string & name = "KDB") const : std::vector<std::string>
C_0016351972983202413152 o-- C_0009493661199123436603 : #model +predict(torch::Tensor & X) : torch::Tensor
C_0016351972983202413152 o-- C_0005895723015084986588 : #metrics {static} +version() : std::string
C_0016351972983202413152 o-- C_0005907365846270811004 : #status __
C_0002617087915615796317 <|-- C_0016351972983202413152 }
class "bayesnet::AODE" as C_0000786111576121788282
class C_0000786111576121788282 #aliceblue;line:blue;line.dotted;text:blue {
+AODE(bool predict_voting = false) : void
+~AODE() : void
..
#buildModel(const torch::Tensor & weights) : void
+graph(const std::string & title = "AODE") const : std::vector<std::string>
+setHyperparameters(const nlohmann::json & hyperparameters) : void
__
}
class "bayesnet::SPODELd" as C_0001369655639257755354
class C_0001369655639257755354 #aliceblue;line:blue;line.dotted;text:blue {
+SPODELd(int root) : void
+~SPODELd() = default : void
..
+commonFit(const std::vector<std::string> & features, const std::string & className, std::map<std::string,std::vector<int>> & states) : SPODELd &
+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) : SPODELd &
+fit(torch::Tensor & dataset, const std::vector<std::string> & features, const std::string & className, std::map<std::string,std::vector<int>> & states) : SPODELd &
+graph(const std::string & name = "SPODE") const : std::vector<std::string>
+predict(torch::Tensor & X) : torch::Tensor
{static} +version() : std::string
__
}
class "bayesnet::AODELd" as C_0000487273479333793647
class C_0000487273479333793647 #aliceblue;line:blue;line.dotted;text:blue {
+AODELd(bool predict_voting = true) : void
+~AODELd() = default : void
..
#buildModel(const torch::Tensor & weights) : void
+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_) : AODELd &
+graph(const std::string & name = "AODELd") const : std::vector<std::string>
#trainModel(const torch::Tensor & weights) : void
__
}
C_0001303524929067080934 --> C_0001303524929067080934 : -parents
C_0001303524929067080934 --> C_0001303524929067080934 : -children
C_0001186707649890429575 o-- C_0001303524929067080934 : -nodes
C_0000327135989451974539 ..> C_0000738420730783851375
C_0002043996622900301644 o-- C_0001186707649890429575 : #model
C_0002043996622900301644 o-- C_0000736965376885623323 : #metrics
C_0002043996622900301644 o-- C_0000738420730783851375 : #status
C_0000327135989451974539 <|-- C_0002043996622900301644
C_0002043996622900301644 <|-- C_0001112865019015250005
C_0002043996622900301644 <|-- C_0001760994424884323017
C_0002219995589162262979 ..> C_0001186707649890429575
C_0001760994424884323017 <|-- C_0001668829096702037834
C_0002219995589162262979 <|-- C_0001668829096702037834
C_0000736965376885623323 <|-- C_0001695326193250580823
C_0001695326193250580823 <|-- C_0000011627355691342494
C_0001695326193250580823 <|-- C_0000144682015341746929
C_0001695326193250580823 <|-- C_0000008268514674428553
C_0002043996622900301644 <|-- C_0000512022813807538451
C_0001985241386355360576 o-- C_0002043996622900301644 : #models
C_0002043996622900301644 <|-- C_0001985241386355360576
C_0000358471592399852382 --> C_0001695326193250580823 : -featureSelector
C_0001985241386355360576 <|-- C_0000358471592399852382
C_0001112865019015250005 <|-- C_0000344502277874806837
C_0002219995589162262979 <|-- C_0000344502277874806837
C_0001985241386355360576 <|-- C_0000786111576121788282
C_0000512022813807538451 <|-- C_0001369655639257755354
C_0002219995589162262979 <|-- C_0001369655639257755354
C_0001985241386355360576 <|-- C_0000487273479333793647
C_0002219995589162262979 <|-- C_0000487273479333793647
C_0016351972983202413152 <|-- C_0008902920152122000044 'Generated with clang-uml, version 0.5.1
'LLVM version clang version 17.0.6 (Fedora 17.0.6-2.fc39)
C_0016351972983202413152 <|-- C_0004096182510460307610
C_0016351972983202413152 <|-- C_0016268916386101512883
C_0016351972983202413152 <|-- C_0014087955399074584137
C_0017759964713298103839 ..> C_0009493661199123436603
C_0002756018222998454702 ..> C_0013393078277439680282
C_0008902920152122000044 <|-- C_0002756018222998454702
C_0017759964713298103839 <|-- C_0002756018222998454702
C_0010957245114062042836 ..> C_0013393078277439680282
C_0004096182510460307610 <|-- C_0010957245114062042836
C_0017759964713298103839 <|-- C_0010957245114062042836
C_0013350632773616302678 ..> C_0013393078277439680282
C_0014087955399074584137 <|-- C_0013350632773616302678
C_0017759964713298103839 <|-- C_0013350632773616302678
C_0015881931090842884611 ..> C_0013393078277439680282
C_0015881931090842884611 o-- C_0016351972983202413152 : #models
C_0016351972983202413152 <|-- C_0015881931090842884611
C_0015881931090842884611 <|-- C_0001410789567057647859
C_0015881931090842884611 <|-- C_0006288892608974306258
C_0005895723015084986588 <|-- C_0013562609546004646591
C_0009819322948617116148 --> C_0013562609546004646591 : #featureSelector
C_0015881931090842884611 <|-- C_0009819322948617116148
C_0003898187834670349177 ..> C_0013393078277439680282
C_0015881931090842884611 <|-- C_0003898187834670349177
C_0017759964713298103839 <|-- C_0003898187834670349177
C_0000272055465257861326 ..> C_0013393078277439680282
C_0009819322948617116148 <|-- C_0000272055465257861326
C_0002867772739198819061 ..> C_0013393078277439680282
C_0009819322948617116148 <|-- C_0002867772739198819061
C_0013562609546004646591 <|-- C_0000093018845530739957
C_0013562609546004646591 <|-- C_0001157456122733975432
C_0013562609546004646591 <|-- C_0000066148117395428429
'Generated with clang-uml, version 0.5.5
'LLVM version clang version 18.1.8 (Fedora 18.1.8-5.fc41)
@enduml @enduml

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 196 KiB

After

Width:  |  Height:  |  Size: 139 KiB

View File

@ -1,314 +1,128 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.1.0 (20240811.2233) <!-- Generated by graphviz version 8.1.0 (20230707.0739)
--> -->
<!-- Title: BayesNet Pages: 1 --> <!-- Title: BayesNet Pages: 1 -->
<svg width="3725pt" height="432pt" <svg width="1632pt" height="288pt"
viewBox="0.00 0.00 3724.84 431.80" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> viewBox="0.00 0.00 1631.95 287.80" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 427.8)"> <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 283.8)">
<title>BayesNet</title> <title>BayesNet</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-427.8 3720.84,-427.8 3720.84,4 -4,4"/> <polygon fill="white" stroke="none" points="-4,4 -4,-283.8 1627.95,-283.8 1627.95,4 -4,4"/>
<!-- node0 -->
<g id="node1" class="node">
<title>node0</title>
<polygon fill="none" stroke="black" points="1655.43,-398.35 1655.43,-413.26 1625.69,-423.8 1583.63,-423.8 1553.89,-413.26 1553.89,-398.35 1583.63,-387.8 1625.69,-387.8 1655.43,-398.35"/>
<text text-anchor="middle" x="1604.66" y="-401.53" font-family="Times,serif" font-size="12.00">BayesNet</text>
</g>
<!-- node1 --> <!-- node1 -->
<g id="node2" class="node"> <g id="node1" class="node">
<title>node1</title> <title>node1</title>
<polygon fill="none" stroke="black" points="413.32,-257.8 372.39,-273.03 206.66,-279.8 40.93,-273.03 0,-257.8 114.69,-245.59 298.64,-245.59 413.32,-257.8"/> <polygon fill="none" stroke="black" points="826.43,-254.35 826.43,-269.26 796.69,-279.8 754.63,-279.8 724.89,-269.26 724.89,-254.35 754.63,-243.8 796.69,-243.8 826.43,-254.35"/>
<text text-anchor="middle" x="206.66" y="-257.53" font-family="Times,serif" font-size="12.00">/home/rmontanana/Code/libtorch/lib/libc10.so</text> <text text-anchor="middle" x="775.66" y="-257.53" font-family="Times,serif" font-size="12.00">BayesNet</text>
</g>
<!-- node0&#45;&gt;node1 -->
<g id="edge1" class="edge">
<title>node0&#45;&gt;node1</title>
<path fill="none" stroke="black" d="M1553.59,-400.53C1451.65,-391.91 1215.69,-371.61 1017.66,-351.8 773.36,-327.37 488.07,-295.22 329.31,-277.01"/>
<polygon fill="black" stroke="black" points="329.93,-273.56 319.6,-275.89 329.14,-280.51 329.93,-273.56"/>
</g> </g>
<!-- node2 --> <!-- node2 -->
<g id="node3" class="node"> <g id="node2" class="node">
<title>node2</title> <title>node2</title>
<polygon fill="none" stroke="black" points="894.21,-257.8 848.35,-273.03 662.66,-279.8 476.98,-273.03 431.12,-257.8 559.61,-245.59 765.71,-245.59 894.21,-257.8"/> <polygon fill="none" stroke="black" points="413.32,-185.8 372.39,-201.03 206.66,-207.8 40.93,-201.03 0,-185.8 114.69,-173.59 298.64,-173.59 413.32,-185.8"/>
<text text-anchor="middle" x="662.66" y="-257.53" font-family="Times,serif" font-size="12.00">/home/rmontanana/Code/libtorch/lib/libc10_cuda.so</text> <text text-anchor="middle" x="206.66" y="-185.53" font-family="Times,serif" font-size="12.00">/home/rmontanana/Code/libtorch/lib/libc10.so</text>
</g> </g>
<!-- node0&#45;&gt;node2 --> <!-- node1&#45;&gt;node2 -->
<g id="edge2" class="edge"> <g id="edge1" class="edge">
<title>node0&#45;&gt;node2</title> <title>node1&#45;&gt;node2</title>
<path fill="none" stroke="black" d="M1555.34,-397.37C1408.12,-375.18 969.52,-309.06 767.13,-278.55"/> <path fill="none" stroke="black" d="M724.41,-254.5C634.7,-243.46 447.04,-220.38 324.01,-205.24"/>
<polygon fill="black" stroke="black" points="767.81,-275.12 757.4,-277.09 766.77,-282.04 767.81,-275.12"/> <polygon fill="black" stroke="black" points="324.77,-201.69 314.42,-203.94 323.92,-208.63 324.77,-201.69"/>
</g> </g>
<!-- node3 --> <!-- node3 -->
<g id="node4" class="node"> <g id="node3" class="node">
<title>node3</title> <title>node3</title>
<polygon fill="none" stroke="black" points="1338.68,-257.8 1296.49,-273.03 1125.66,-279.8 954.84,-273.03 912.65,-257.8 1030.86,-245.59 1220.46,-245.59 1338.68,-257.8"/> <polygon fill="none" stroke="black" points="857.68,-185.8 815.49,-201.03 644.66,-207.8 473.84,-201.03 431.65,-185.8 549.86,-173.59 739.46,-173.59 857.68,-185.8"/>
<text text-anchor="middle" x="1125.66" y="-257.53" font-family="Times,serif" font-size="12.00">/home/rmontanana/Code/libtorch/lib/libkineto.a</text> <text text-anchor="middle" x="644.66" y="-185.53" font-family="Times,serif" font-size="12.00">/home/rmontanana/Code/libtorch/lib/libkineto.a</text>
</g> </g>
<!-- node0&#45;&gt;node3 --> <!-- node1&#45;&gt;node3 -->
<g id="edge3" class="edge"> <g id="edge2" class="edge">
<title>node0&#45;&gt;node3</title> <title>node1&#45;&gt;node3</title>
<path fill="none" stroke="black" d="M1566.68,-393.54C1484.46,-369.17 1289.3,-311.32 1188.44,-281.41"/> <path fill="none" stroke="black" d="M747.56,-245.79C729.21,-235.98 704.97,-223.03 684.63,-212.16"/>
<polygon fill="black" stroke="black" points="1189.53,-278.09 1178.95,-278.6 1187.54,-284.8 1189.53,-278.09"/> <polygon fill="black" stroke="black" points="686.47,-208.64 676,-207.02 683.17,-214.82 686.47,-208.64"/>
</g> </g>
<!-- node4 --> <!-- node4 -->
<g id="node5" class="node"> <g id="node4" class="node">
<title>node4</title> <title>node4</title>
<polygon fill="none" stroke="black" points="1552.26,-257.8 1532.93,-273.03 1454.66,-279.8 1376.4,-273.03 1357.07,-257.8 1411.23,-245.59 1498.1,-245.59 1552.26,-257.8"/> <polygon fill="none" stroke="black" points="939.33,-182.35 939.33,-197.26 920.78,-207.8 894.54,-207.8 875.99,-197.26 875.99,-182.35 894.54,-171.8 920.78,-171.8 939.33,-182.35"/>
<text text-anchor="middle" x="1454.66" y="-257.53" font-family="Times,serif" font-size="12.00">/usr/lib64/libcuda.so</text> <text text-anchor="middle" x="907.66" y="-185.53" font-family="Times,serif" font-size="12.00">mdlp</text>
</g> </g>
<!-- node0&#45;&gt;node4 --> <!-- node1&#45;&gt;node4 -->
<g id="edge4" class="edge"> <g id="edge3" class="edge">
<title>node0&#45;&gt;node4</title> <title>node1&#45;&gt;node4</title>
<path fill="none" stroke="black" d="M1586.27,-387.39C1559.5,-362.05 1509.72,-314.92 1479.65,-286.46"/> <path fill="none" stroke="black" d="M803.66,-245.96C824.66,-234.82 853.45,-219.56 875.41,-207.91"/>
<polygon fill="black" stroke="black" points="1482.13,-283.99 1472.46,-279.65 1477.31,-289.07 1482.13,-283.99"/> <polygon fill="black" stroke="black" points="876.78,-210.61 883.97,-202.84 873.5,-204.43 876.78,-210.61"/>
</g>
<!-- node5 -->
<g id="node6" class="node">
<title>node5</title>
<polygon fill="none" stroke="black" points="1873.26,-257.8 1843.23,-273.03 1721.66,-279.8 1600.09,-273.03 1570.06,-257.8 1654.19,-245.59 1789.13,-245.59 1873.26,-257.8"/>
<text text-anchor="middle" x="1721.66" y="-257.53" font-family="Times,serif" font-size="12.00">/usr/local/cuda/lib64/libcudart.so</text>
</g>
<!-- node0&#45;&gt;node5 -->
<g id="edge5" class="edge">
<title>node0&#45;&gt;node5</title>
<path fill="none" stroke="black" d="M1619.76,-387.77C1628.83,-377.46 1640.53,-363.98 1650.66,-351.8 1668.32,-330.59 1687.84,-306.03 1701.94,-288.1"/>
<polygon fill="black" stroke="black" points="1704.43,-290.59 1707.84,-280.56 1698.92,-286.27 1704.43,-290.59"/>
</g>
<!-- node6 -->
<g id="node7" class="node">
<title>node6</title>
<polygon fill="none" stroke="black" points="2231.79,-257.8 2198.1,-273.03 2061.66,-279.8 1925.23,-273.03 1891.53,-257.8 1985.95,-245.59 2137.38,-245.59 2231.79,-257.8"/>
<text text-anchor="middle" x="2061.66" y="-257.53" font-family="Times,serif" font-size="12.00">/usr/local/cuda/lib64/libnvToolsExt.so</text>
</g>
<!-- node0&#45;&gt;node6 -->
<g id="edge6" class="edge">
<title>node0&#45;&gt;node6</title>
<path fill="none" stroke="black" d="M1642.06,-393.18C1721.31,-368.56 1906.71,-310.95 2002.32,-281.24"/>
<polygon fill="black" stroke="black" points="2003.28,-284.61 2011.79,-278.3 2001.21,-277.92 2003.28,-284.61"/>
</g>
<!-- node7 -->
<g id="node8" class="node">
<title>node7</title>
<polygon fill="none" stroke="black" points="2541.44,-257.8 2512.56,-273.03 2395.66,-279.8 2278.76,-273.03 2249.89,-257.8 2330.79,-245.59 2460.54,-245.59 2541.44,-257.8"/>
<text text-anchor="middle" x="2395.66" y="-257.53" font-family="Times,serif" font-size="12.00">/usr/local/cuda/lib64/libnvrtc.so</text>
</g>
<!-- node0&#45;&gt;node7 -->
<g id="edge7" class="edge">
<title>node0&#45;&gt;node7</title>
<path fill="none" stroke="black" d="M1651.19,-396.45C1780.36,-373.26 2144.76,-307.85 2311.05,-277.99"/>
<polygon fill="black" stroke="black" points="2311.47,-281.47 2320.7,-276.26 2310.24,-274.58 2311.47,-281.47"/>
</g>
<!-- node8 -->
<g id="node9" class="node">
<title>node8</title>
<polygon fill="none" stroke="black" points="1642.01,-326.35 1642.01,-341.26 1620.13,-351.8 1589.19,-351.8 1567.31,-341.26 1567.31,-326.35 1589.19,-315.8 1620.13,-315.8 1642.01,-326.35"/>
<text text-anchor="middle" x="1604.66" y="-329.53" font-family="Times,serif" font-size="12.00">fimdlp</text>
</g>
<!-- node0&#45;&gt;node8 -->
<g id="edge8" class="edge">
<title>node0&#45;&gt;node8</title>
<path fill="none" stroke="black" d="M1604.66,-387.5C1604.66,-380.21 1604.66,-371.53 1604.66,-363.34"/>
<polygon fill="black" stroke="black" points="1608.16,-363.42 1604.66,-353.42 1601.16,-363.42 1608.16,-363.42"/>
</g>
<!-- node19 -->
<g id="node10" class="node">
<title>node19</title>
<polygon fill="none" stroke="black" points="2709.74,-267.37 2634.66,-279.8 2559.58,-267.37 2588.26,-247.24 2681.06,-247.24 2709.74,-267.37"/>
<text text-anchor="middle" x="2634.66" y="-257.53" font-family="Times,serif" font-size="12.00">torch_library</text>
</g>
<!-- node0&#45;&gt;node19 -->
<g id="edge29" class="edge">
<title>node0&#45;&gt;node19</title>
<path fill="none" stroke="black" d="M1655.87,-399.32C1798.23,-383.79 2210.64,-336.94 2550.66,-279.8 2559.43,-278.33 2568.68,-276.62 2577.72,-274.86"/>
<polygon fill="black" stroke="black" points="2578.38,-278.3 2587.5,-272.92 2577.01,-271.43 2578.38,-278.3"/>
</g>
<!-- node8&#45;&gt;node1 -->
<g id="edge9" class="edge">
<title>node8&#45;&gt;node1</title>
<path fill="none" stroke="black" d="M1566.84,-331.58C1419.81,-326.72 872.06,-307.69 421.66,-279.8 401.07,-278.53 379.38,-277.02 358.03,-275.43"/>
<polygon fill="black" stroke="black" points="358.3,-271.94 348.06,-274.67 357.77,-278.92 358.3,-271.94"/>
</g>
<!-- node8&#45;&gt;node2 -->
<g id="edge10" class="edge">
<title>node8&#45;&gt;node2</title>
<path fill="none" stroke="black" d="M1566.86,-330C1445.11,-320.95 1057.97,-292.18 831.67,-275.36"/>
<polygon fill="black" stroke="black" points="832.09,-271.89 821.86,-274.63 831.57,-278.87 832.09,-271.89"/>
</g>
<!-- node8&#45;&gt;node3 -->
<g id="edge11" class="edge">
<title>node8&#45;&gt;node3</title>
<path fill="none" stroke="black" d="M1567.08,-327.31C1495.4,-316.84 1336.86,-293.67 1230.62,-278.14"/>
<polygon fill="black" stroke="black" points="1231.44,-274.72 1221.04,-276.74 1230.42,-281.65 1231.44,-274.72"/>
</g>
<!-- node8&#45;&gt;node4 -->
<g id="edge12" class="edge">
<title>node8&#45;&gt;node4</title>
<path fill="none" stroke="black" d="M1578.53,-320.61C1555.96,-310.08 1522.92,-294.66 1496.64,-282.4"/>
<polygon fill="black" stroke="black" points="1498.12,-279.22 1487.58,-278.17 1495.16,-285.57 1498.12,-279.22"/>
</g>
<!-- node8&#45;&gt;node5 -->
<g id="edge13" class="edge">
<title>node8&#45;&gt;node5</title>
<path fill="none" stroke="black" d="M1627.78,-318.97C1644.15,-309.18 1666.44,-295.84 1685.2,-284.62"/>
<polygon fill="black" stroke="black" points="1686.83,-287.73 1693.61,-279.59 1683.23,-281.72 1686.83,-287.73"/>
</g>
<!-- node8&#45;&gt;node6 -->
<g id="edge14" class="edge">
<title>node8&#45;&gt;node6</title>
<path fill="none" stroke="black" d="M1642.45,-327.02C1712.36,-316.31 1863.89,-293.1 1964.32,-277.71"/>
<polygon fill="black" stroke="black" points="1964.84,-281.18 1974.2,-276.2 1963.78,-274.26 1964.84,-281.18"/>
</g>
<!-- node8&#45;&gt;node7 -->
<g id="edge15" class="edge">
<title>node8&#45;&gt;node7</title>
<path fill="none" stroke="black" d="M1642.33,-330.01C1740.75,-322.64 2013.75,-301.7 2240.66,-279.8 2254.16,-278.5 2268.32,-277.06 2282.35,-275.58"/>
<polygon fill="black" stroke="black" points="2282.49,-279.08 2292.06,-274.54 2281.75,-272.12 2282.49,-279.08"/>
</g>
<!-- node8&#45;&gt;node19 -->
<g id="edge16" class="edge">
<title>node8&#45;&gt;node19</title>
<path fill="none" stroke="black" d="M1642.25,-332.63C1770.06,-331.64 2199.48,-324.94 2550.66,-279.8 2560.1,-278.59 2570.07,-276.92 2579.71,-275.1"/>
<polygon fill="black" stroke="black" points="2580.21,-278.57 2589.34,-273.21 2578.86,-271.7 2580.21,-278.57"/>
</g>
<!-- node20 -->
<g id="node11" class="node">
<title>node20</title>
<polygon fill="none" stroke="black" points="2606.81,-185.8 2533.89,-201.03 2238.66,-207.8 1943.43,-201.03 1870.52,-185.8 2074.82,-173.59 2402.5,-173.59 2606.81,-185.8"/>
<text text-anchor="middle" x="2238.66" y="-185.53" font-family="Times,serif" font-size="12.00">&#45;Wl,&#45;&#45;no&#45;as&#45;needed,&quot;/home/rmontanana/Code/libtorch/lib/libtorch.so&quot; &#45;Wl,&#45;&#45;as&#45;needed</text>
</g>
<!-- node19&#45;&gt;node20 -->
<g id="edge17" class="edge">
<title>node19&#45;&gt;node20</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2583.63,-250.21C2572.76,-248.03 2561.34,-245.79 2550.66,-243.8 2482.14,-231.05 2404.92,-217.93 2344.44,-207.93"/>
<polygon fill="black" stroke="black" points="2345.28,-204.52 2334.84,-206.34 2344.14,-211.42 2345.28,-204.52"/>
</g> </g>
<!-- node9 --> <!-- node9 -->
<g id="node12" class="node"> <g id="node5" class="node">
<title>node9</title> <title>node9</title>
<polygon fill="none" stroke="black" points="2542.56,-123.37 2445.66,-135.8 2348.77,-123.37 2385.78,-103.24 2505.55,-103.24 2542.56,-123.37"/> <polygon fill="none" stroke="black" points="1107.74,-195.37 1032.66,-207.8 957.58,-195.37 986.26,-175.24 1079.06,-175.24 1107.74,-195.37"/>
<text text-anchor="middle" x="2445.66" y="-113.53" font-family="Times,serif" font-size="12.00">torch_cpu_library</text> <text text-anchor="middle" x="1032.66" y="-185.53" font-family="Times,serif" font-size="12.00">torch_library</text>
</g> </g>
<!-- node19&#45;&gt;node9 --> <!-- node1&#45;&gt;node9 -->
<g id="edge18" class="edge"> <g id="edge4" class="edge">
<title>node19&#45;&gt;node9</title> <title>node1&#45;&gt;node9</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2635.72,-246.84C2636.4,-227.49 2634.61,-192.58 2615.66,-171.8 2601.13,-155.87 2551.93,-141.56 2510.18,-131.84"/> <path fill="none" stroke="black" d="M815.25,-250.02C860.25,-237.77 933.77,-217.74 982.68,-204.42"/>
<polygon fill="black" stroke="black" points="2511.2,-128.48 2500.67,-129.68 2509.65,-135.31 2511.2,-128.48"/> <polygon fill="black" stroke="black" points="983.3,-207.61 992.02,-201.6 981.46,-200.85 983.3,-207.61"/>
</g>
<!-- node13 -->
<g id="node16" class="node">
<title>node13</title>
<polygon fill="none" stroke="black" points="3056.45,-195.37 2953.66,-207.8 2850.87,-195.37 2890.13,-175.24 3017.19,-175.24 3056.45,-195.37"/>
<text text-anchor="middle" x="2953.66" y="-185.53" font-family="Times,serif" font-size="12.00">torch_cuda_library</text>
</g>
<!-- node19&#45;&gt;node13 -->
<g id="edge22" class="edge">
<title>node19&#45;&gt;node13</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2685.21,-249.71C2741.11,-237.45 2831.21,-217.67 2891.42,-204.46"/>
<polygon fill="black" stroke="black" points="2891.8,-207.96 2900.82,-202.4 2890.3,-201.13 2891.8,-207.96"/>
</g> </g>
<!-- node10 --> <!-- node10 -->
<g id="node13" class="node"> <g id="node6" class="node">
<title>node10</title> <title>node10</title>
<polygon fill="none" stroke="black" points="2362.4,-27.9 2285.6,-43.12 1974.66,-49.9 1663.72,-43.12 1586.93,-27.9 1802.1,-15.68 2147.22,-15.68 2362.4,-27.9"/> <polygon fill="none" stroke="black" points="1159.81,-113.8 1086.89,-129.03 791.66,-135.8 496.43,-129.03 423.52,-113.8 627.82,-101.59 955.5,-101.59 1159.81,-113.8"/>
<text text-anchor="middle" x="1974.66" y="-27.63" font-family="Times,serif" font-size="12.00">&#45;Wl,&#45;&#45;no&#45;as&#45;needed,&quot;/home/rmontanana/Code/libtorch/lib/libtorch_cpu.so&quot; &#45;Wl,&#45;&#45;as&#45;needed</text> <text text-anchor="middle" x="791.66" y="-113.53" font-family="Times,serif" font-size="12.00">&#45;Wl,&#45;&#45;no&#45;as&#45;needed,&quot;/home/rmontanana/Code/libtorch/lib/libtorch.so&quot; &#45;Wl,&#45;&#45;as&#45;needed</text>
</g> </g>
<!-- node9&#45;&gt;node10 --> <!-- node9&#45;&gt;node10 -->
<g id="edge19" class="edge"> <g id="edge5" class="edge">
<title>node9&#45;&gt;node10</title> <title>node9&#45;&gt;node10</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2381.16,-105.31C2301.63,-91.15 2165.65,-66.92 2073.05,-50.43"/> <path fill="none" stroke="black" stroke-dasharray="5,2" d="M985.62,-175.14C949.2,-164.56 898.31,-149.78 857.79,-138.01"/>
<polygon fill="black" stroke="black" points="2073.93,-47.03 2063.48,-48.72 2072.71,-53.92 2073.93,-47.03"/> <polygon fill="black" stroke="black" points="859.04,-134.44 848.46,-135.01 857.09,-141.16 859.04,-134.44"/>
</g> </g>
<!-- node11 --> <!-- node5 -->
<g id="node14" class="node"> <g id="node7" class="node">
<title>node11</title> <title>node5</title>
<polygon fill="none" stroke="black" points="2510.72,-37.46 2445.66,-49.9 2380.61,-37.46 2405.46,-17.34 2485.87,-17.34 2510.72,-37.46"/> <polygon fill="none" stroke="black" points="1371.56,-123.37 1274.66,-135.8 1177.77,-123.37 1214.78,-103.24 1334.55,-103.24 1371.56,-123.37"/>
<text text-anchor="middle" x="2445.66" y="-27.63" font-family="Times,serif" font-size="12.00">caffe2::mkl</text> <text text-anchor="middle" x="1274.66" y="-113.53" font-family="Times,serif" font-size="12.00">torch_cpu_library</text>
</g> </g>
<!-- node9&#45;&gt;node11 --> <!-- node9&#45;&gt;node5 -->
<g id="edge20" class="edge"> <g id="edge6" class="edge">
<title>node9&#45;&gt;node11</title> <title>node9&#45;&gt;node5</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2445.66,-102.95C2445.66,-91.68 2445.66,-75.4 2445.66,-61.37"/> <path fill="none" stroke="black" stroke-dasharray="5,2" d="M1079.61,-175.22C1120.66,-163.35 1180.2,-146.13 1222.68,-133.84"/>
<polygon fill="black" stroke="black" points="2449.16,-61.78 2445.66,-51.78 2442.16,-61.78 2449.16,-61.78"/> <polygon fill="black" stroke="black" points="1223.46,-136.97 1232.09,-130.83 1221.51,-130.24 1223.46,-136.97"/>
</g> </g>
<!-- node12 --> <!-- node6 -->
<g id="node15" class="node"> <g id="node8" class="node">
<title>node12</title> <title>node6</title>
<polygon fill="none" stroke="black" points="2794.95,-41.76 2661.66,-63.8 2528.37,-41.76 2579.28,-6.09 2744.04,-6.09 2794.95,-41.76"/> <polygon fill="none" stroke="black" points="1191.4,-27.9 1114.6,-43.12 803.66,-49.9 492.72,-43.12 415.93,-27.9 631.1,-15.68 976.22,-15.68 1191.4,-27.9"/>
<text text-anchor="middle" x="2661.66" y="-34.75" font-family="Times,serif" font-size="12.00">dummy</text> <text text-anchor="middle" x="803.66" y="-27.63" font-family="Times,serif" font-size="12.00">&#45;Wl,&#45;&#45;no&#45;as&#45;needed,&quot;/home/rmontanana/Code/libtorch/lib/libtorch_cpu.so&quot; &#45;Wl,&#45;&#45;as&#45;needed</text>
<text text-anchor="middle" x="2661.66" y="-20.5" font-family="Times,serif" font-size="12.00">(protobuf::libprotobuf)</text>
</g> </g>
<!-- node9&#45;&gt;node12 --> <!-- node5&#45;&gt;node6 -->
<g id="edge21" class="edge"> <g id="edge7" class="edge">
<title>node9&#45;&gt;node12</title> <title>node5&#45;&gt;node6</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2481.82,-102.76C2512.55,-90.82 2557.5,-73.36 2594.77,-58.89"/> <path fill="none" stroke="black" stroke-dasharray="5,2" d="M1210.16,-105.31C1130.55,-91.13 994.37,-66.87 901.77,-50.38"/>
<polygon fill="black" stroke="black" points="2595.6,-62.32 2603.65,-55.44 2593.06,-55.79 2595.6,-62.32"/> <polygon fill="black" stroke="black" points="902.44,-46.77 891.98,-48.46 901.22,-53.66 902.44,-46.77"/>
</g> </g>
<!-- node13&#45;&gt;node9 --> <!-- node7 -->
<g id="edge28" class="edge"> <g id="node9" class="node">
<title>node13&#45;&gt;node9</title> <title>node7</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2880.59,-179.79C2799.97,-169.71 2666.42,-152.57 2551.66,-135.8 2540.2,-134.13 2528.06,-132.27 2516.24,-130.41"/> <polygon fill="none" stroke="black" points="1339.72,-37.46 1274.66,-49.9 1209.61,-37.46 1234.46,-17.34 1314.87,-17.34 1339.72,-37.46"/>
<polygon fill="black" stroke="black" points="2516.96,-126.98 2506.54,-128.86 2515.87,-133.89 2516.96,-126.98"/> <text text-anchor="middle" x="1274.66" y="-27.63" font-family="Times,serif" font-size="12.00">caffe2::mkl</text>
</g> </g>
<!-- node14 --> <!-- node5&#45;&gt;node7 -->
<g id="node17" class="node"> <g id="edge8" class="edge">
<title>node14</title> <title>node5&#45;&gt;node7</title>
<polygon fill="none" stroke="black" points="3346.69,-113.8 3268.85,-129.03 2953.66,-135.8 2638.48,-129.03 2560.63,-113.8 2778.75,-101.59 3128.58,-101.59 3346.69,-113.8"/> <path fill="none" stroke="black" stroke-dasharray="5,2" d="M1274.66,-102.95C1274.66,-91.56 1274.66,-75.07 1274.66,-60.95"/>
<text text-anchor="middle" x="2953.66" y="-113.53" font-family="Times,serif" font-size="12.00">&#45;Wl,&#45;&#45;no&#45;as&#45;needed,&quot;/home/rmontanana/Code/libtorch/lib/libtorch_cuda.so&quot; &#45;Wl,&#45;&#45;as&#45;needed</text> <polygon fill="black" stroke="black" points="1278.16,-61.27 1274.66,-51.27 1271.16,-61.27 1278.16,-61.27"/>
</g> </g>
<!-- node13&#45;&gt;node14 --> <!-- node8 -->
<g id="edge23" class="edge"> <g id="node10" class="node">
<title>node13&#45;&gt;node14</title> <title>node8</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M2953.66,-174.97C2953.66,-167.13 2953.66,-157.01 2953.66,-147.53"/> <polygon fill="none" stroke="black" points="1623.95,-41.76 1490.66,-63.8 1357.37,-41.76 1408.28,-6.09 1573.04,-6.09 1623.95,-41.76"/>
<polygon fill="black" stroke="black" points="2957.16,-147.59 2953.66,-137.59 2950.16,-147.59 2957.16,-147.59"/> <text text-anchor="middle" x="1490.66" y="-34.75" font-family="Times,serif" font-size="12.00">dummy</text>
<text text-anchor="middle" x="1490.66" y="-20.5" font-family="Times,serif" font-size="12.00">(protobuf::libprotobuf)</text>
</g> </g>
<!-- node15 --> <!-- node5&#45;&gt;node8 -->
<g id="node18" class="node"> <g id="edge9" class="edge">
<title>node15</title> <title>node5&#45;&gt;node8</title>
<polygon fill="none" stroke="black" points="3514.74,-123.37 3439.66,-135.8 3364.58,-123.37 3393.26,-103.24 3486.06,-103.24 3514.74,-123.37"/> <path fill="none" stroke="black" stroke-dasharray="5,2" d="M1310.82,-102.76C1341.68,-90.77 1386.88,-73.21 1424.25,-58.7"/>
<text text-anchor="middle" x="3439.66" y="-113.53" font-family="Times,serif" font-size="12.00">torch::cudart</text> <polygon fill="black" stroke="black" points="1425.01,-61.77 1433.06,-54.89 1422.47,-55.25 1425.01,-61.77"/>
</g>
<!-- node13&#45;&gt;node15 -->
<g id="edge24" class="edge">
<title>node13&#45;&gt;node15</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M3028.35,-180.51C3109.24,-171.17 3241.96,-154.78 3355.66,-135.8 3364.43,-134.34 3373.69,-132.63 3382.72,-130.88"/>
<polygon fill="black" stroke="black" points="3383.38,-134.31 3392.51,-128.93 3382.02,-127.45 3383.38,-134.31"/>
</g>
<!-- node17 -->
<g id="node20" class="node">
<title>node17</title>
<polygon fill="none" stroke="black" points="3716.84,-123.37 3624.66,-135.8 3532.48,-123.37 3567.69,-103.24 3681.63,-103.24 3716.84,-123.37"/>
<text text-anchor="middle" x="3624.66" y="-113.53" font-family="Times,serif" font-size="12.00">torch::nvtoolsext</text>
</g>
<!-- node13&#45;&gt;node17 -->
<g id="edge26" class="edge">
<title>node13&#45;&gt;node17</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M3033.64,-183.25C3144.1,-175.14 3349.47,-158.53 3523.66,-135.8 3534.84,-134.35 3546.67,-132.57 3558.15,-130.72"/>
<polygon fill="black" stroke="black" points="3558.68,-134.18 3567.98,-129.1 3557.54,-127.27 3558.68,-134.18"/>
</g>
<!-- node16 -->
<g id="node19" class="node">
<title>node16</title>
<polygon fill="none" stroke="black" points="3510.78,-27.9 3496.7,-43.12 3439.66,-49.9 3382.63,-43.12 3368.54,-27.9 3408.01,-15.68 3471.31,-15.68 3510.78,-27.9"/>
<text text-anchor="middle" x="3439.66" y="-27.63" font-family="Times,serif" font-size="12.00">CUDA::cudart</text>
</g>
<!-- node15&#45;&gt;node16 -->
<g id="edge25" class="edge">
<title>node15&#45;&gt;node16</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M3439.66,-102.95C3439.66,-91.68 3439.66,-75.4 3439.66,-61.37"/>
<polygon fill="black" stroke="black" points="3443.16,-61.78 3439.66,-51.78 3436.16,-61.78 3443.16,-61.78"/>
</g>
<!-- node18 -->
<g id="node21" class="node">
<title>node18</title>
<polygon fill="none" stroke="black" points="3714.32,-27.9 3696.56,-43.12 3624.66,-49.9 3552.77,-43.12 3535.01,-27.9 3584.76,-15.68 3664.56,-15.68 3714.32,-27.9"/>
<text text-anchor="middle" x="3624.66" y="-27.63" font-family="Times,serif" font-size="12.00">CUDA::nvToolsExt</text>
</g>
<!-- node17&#45;&gt;node18 -->
<g id="edge27" class="edge">
<title>node17&#45;&gt;node18</title>
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M3624.66,-102.95C3624.66,-91.68 3624.66,-75.4 3624.66,-61.37"/>
<polygon fill="black" stroke="black" points="3628.16,-61.78 3624.66,-51.78 3621.16,-61.78 3628.16,-61.78"/>
</g> </g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

@ -1 +1 @@
Subproject commit 378e091795a70fced276cd882bd8a6a428668fe5 Subproject commit 960b763ecd144f156d05ec61f577b04107290137

@ -1 +1 @@
Subproject commit 7d62d6af4a6ca944a3bbde0b61f651fd4b2d3f57 Subproject commit 2db60e007d70da876379373c53b6421f281daeac

View File

@ -5,21 +5,15 @@ project(bayesnet_sample)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
find_package(Torch REQUIRED) find_package(Torch REQUIRED)
find_library(BayesNet NAMES libBayesNet BayesNet libBayesNet.a REQUIRED) find_library(BayesNet NAMES BayesNet.a libBayesNet.a REQUIRED)
find_path(Bayesnet_INCLUDE_DIRS REQUIRED NAMES bayesnet)
find_library(FImdlp NAMES libfimdlp.a PATHS REQUIRED)
message(STATUS "FImdlp=${FImdlp}")
message(STATUS "FImdlp_INCLUDE_DIRS=${FImdlp_INCLUDE_DIRS}")
message(STATUS "BayesNet=${BayesNet}")
message(STATUS "Bayesnet_INCLUDE_DIRS=${Bayesnet_INCLUDE_DIRS}")
include_directories( include_directories(
../tests/lib/Files ../tests/lib/Files
lib/mdlp
lib/json/include lib/json/include
/usr/local/include /usr/local/include
${FImdlp_INCLUDE_DIRS}
) )
add_subdirectory(lib/mdlp)
add_executable(bayesnet_sample sample.cc) add_executable(bayesnet_sample sample.cc)
target_link_libraries(bayesnet_sample fimdlp "${TORCH_LIBRARIES}" "${BayesNet}") target_link_libraries(bayesnet_sample mdlp "${TORCH_LIBRARIES}" "${BayesNet}")

View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.20)
project(mdlp)
if (POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif ()
set(CMAKE_CXX_STANDARD 11)
add_library(mdlp CPPFImdlp.cpp Metrics.cpp)

View File

@ -0,0 +1,222 @@
#include <numeric>
#include <algorithm>
#include <set>
#include <cmath>
#include "CPPFImdlp.h"
#include "Metrics.h"
namespace mdlp {
CPPFImdlp::CPPFImdlp(size_t min_length_, int max_depth_, float proposed) : min_length(min_length_),
max_depth(max_depth_),
proposed_cuts(proposed)
{
}
CPPFImdlp::CPPFImdlp() = default;
CPPFImdlp::~CPPFImdlp() = default;
size_t CPPFImdlp::compute_max_num_cut_points() const
{
// Set the actual maximum number of cut points as a number or as a percentage of the number of samples
if (proposed_cuts == 0) {
return numeric_limits<size_t>::max();
}
if (proposed_cuts < 0 || proposed_cuts > static_cast<float>(X.size())) {
throw invalid_argument("wrong proposed num_cuts value");
}
if (proposed_cuts < 1)
return static_cast<size_t>(round(static_cast<float>(X.size()) * proposed_cuts));
return static_cast<size_t>(proposed_cuts);
}
void CPPFImdlp::fit(samples_t& X_, labels_t& y_)
{
X = X_;
y = y_;
num_cut_points = compute_max_num_cut_points();
depth = 0;
discretizedData.clear();
cutPoints.clear();
if (X.size() != y.size()) {
throw invalid_argument("X and y must have the same size");
}
if (X.empty() || y.empty()) {
throw invalid_argument("X and y must have at least one element");
}
if (min_length < 3) {
throw invalid_argument("min_length must be greater than 2");
}
if (max_depth < 1) {
throw invalid_argument("max_depth must be greater than 0");
}
indices = sortIndices(X_, y_);
metrics.setData(y, indices);
computeCutPoints(0, X.size(), 1);
sort(cutPoints.begin(), cutPoints.end());
if (num_cut_points > 0) {
// Select the best (with lower entropy) cut points
while (cutPoints.size() > num_cut_points) {
resizeCutPoints();
}
}
}
pair<precision_t, size_t> CPPFImdlp::valueCutPoint(size_t start, size_t cut, size_t end)
{
size_t n;
size_t m;
size_t idxPrev = cut - 1 >= start ? cut - 1 : cut;
size_t idxNext = cut + 1 < end ? cut + 1 : cut;
bool backWall; // true if duplicates reach beginning of the interval
precision_t previous;
precision_t actual;
precision_t next;
previous = X[indices[idxPrev]];
actual = X[indices[cut]];
next = X[indices[idxNext]];
// definition 2 of the paper => X[t-1] < X[t]
// get the first equal value of X in the interval
while (idxPrev > start && actual == previous) {
previous = X[indices[--idxPrev]];
}
backWall = idxPrev == start && actual == previous;
// get the last equal value of X in the interval
while (idxNext < end - 1 && actual == next) {
next = X[indices[++idxNext]];
}
// # of duplicates before cutpoint
n = cut - 1 - idxPrev;
// # of duplicates after cutpoint
m = idxNext - cut - 1;
// Decide which values to use
cut = cut + (backWall ? m + 1 : -n);
actual = X[indices[cut]];
return { (actual + previous) / 2, cut };
}
void CPPFImdlp::computeCutPoints(size_t start, size_t end, int depth_)
{
size_t cut;
pair<precision_t, size_t> result;
// Check if the interval length and the depth are Ok
if (end - start < min_length || depth_ > max_depth)
return;
depth = depth_ > depth ? depth_ : depth;
cut = getCandidate(start, end);
if (cut == numeric_limits<size_t>::max())
return;
if (mdlp(start, cut, end)) {
result = valueCutPoint(start, cut, end);
cut = result.second;
cutPoints.push_back(result.first);
computeCutPoints(start, cut, depth_ + 1);
computeCutPoints(cut, end, depth_ + 1);
}
}
size_t CPPFImdlp::getCandidate(size_t start, size_t end)
{
/* Definition 1: A binary discretization for A is determined by selecting the cut point TA for which
E(A, TA; S) is minimal amongst all the candidate cut points. */
size_t candidate = numeric_limits<size_t>::max();
size_t elements = end - start;
bool sameValues = true;
precision_t entropy_left;
precision_t entropy_right;
precision_t minEntropy;
// Check if all the values of the variable in the interval are the same
for (size_t idx = start + 1; idx < end; idx++) {
if (X[indices[idx]] != X[indices[start]]) {
sameValues = false;
break;
}
}
if (sameValues)
return candidate;
minEntropy = metrics.entropy(start, end);
for (size_t idx = start + 1; idx < end; idx++) {
// Cutpoints are always on boundaries (definition 2)
if (y[indices[idx]] == y[indices[idx - 1]])
continue;
entropy_left = precision_t(idx - start) / static_cast<precision_t>(elements) * metrics.entropy(start, idx);
entropy_right = precision_t(end - idx) / static_cast<precision_t>(elements) * metrics.entropy(idx, end);
if (entropy_left + entropy_right < minEntropy) {
minEntropy = entropy_left + entropy_right;
candidate = idx;
}
}
return candidate;
}
bool CPPFImdlp::mdlp(size_t start, size_t cut, size_t end)
{
int k;
int k1;
int k2;
precision_t ig;
precision_t delta;
precision_t ent;
precision_t ent1;
precision_t ent2;
auto N = precision_t(end - start);
k = metrics.computeNumClasses(start, end);
k1 = metrics.computeNumClasses(start, cut);
k2 = metrics.computeNumClasses(cut, end);
ent = metrics.entropy(start, end);
ent1 = metrics.entropy(start, cut);
ent2 = metrics.entropy(cut, end);
ig = metrics.informationGain(start, cut, end);
delta = static_cast<precision_t>(log2(pow(3, precision_t(k)) - 2) -
(precision_t(k) * ent - precision_t(k1) * ent1 - precision_t(k2) * ent2));
precision_t term = 1 / N * (log2(N - 1) + delta);
return ig > term;
}
// Argsort from https://stackoverflow.com/questions/1577475/c-sorting-and-keeping-track-of-indexes
indices_t CPPFImdlp::sortIndices(samples_t& X_, labels_t& y_)
{
indices_t idx(X_.size());
iota(idx.begin(), idx.end(), 0);
stable_sort(idx.begin(), idx.end(), [&X_, &y_](size_t i1, size_t i2) {
if (X_[i1] == X_[i2])
return y_[i1] < y_[i2];
else
return X_[i1] < X_[i2];
});
return idx;
}
void CPPFImdlp::resizeCutPoints()
{
//Compute entropy of each of the whole cutpoint set and discards the biggest value
precision_t maxEntropy = 0;
precision_t entropy;
size_t maxEntropyIdx = 0;
size_t begin = 0;
size_t end;
for (size_t idx = 0; idx < cutPoints.size(); idx++) {
end = begin;
while (X[indices[end]] < cutPoints[idx] && end < X.size())
end++;
entropy = metrics.entropy(begin, end);
if (entropy > maxEntropy) {
maxEntropy = entropy;
maxEntropyIdx = idx;
}
begin = end;
}
cutPoints.erase(cutPoints.begin() + static_cast<long>(maxEntropyIdx));
}
labels_t& CPPFImdlp::transform(const samples_t& data)
{
discretizedData.clear();
discretizedData.reserve(data.size());
for (const precision_t& item : data) {
auto upper = upper_bound(cutPoints.begin(), cutPoints.end(), item);
discretizedData.push_back(upper - cutPoints.begin());
}
return discretizedData;
}
}

View File

@ -0,0 +1,51 @@
// ***************************************************************
// SPDX-FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX-FileType: SOURCE
// SPDX-License-Identifier: MIT
// ***************************************************************
#ifndef CPPFIMDLP_H
#define CPPFIMDLP_H
#include "typesFImdlp.h"
#include "Metrics.h"
#include <limits>
#include <utility>
#include <string>
namespace mdlp {
class CPPFImdlp {
protected:
size_t min_length = 3;
int depth = 0;
int max_depth = numeric_limits<int>::max();
float proposed_cuts = 0;
indices_t indices = indices_t();
samples_t X = samples_t();
labels_t y = labels_t();
Metrics metrics = Metrics(y, indices);
cutPoints_t cutPoints;
size_t num_cut_points = numeric_limits<size_t>::max();
labels_t discretizedData = labels_t();
static indices_t sortIndices(samples_t&, labels_t&);
void computeCutPoints(size_t, size_t, int);
void resizeCutPoints();
bool mdlp(size_t, size_t, size_t);
size_t getCandidate(size_t, size_t);
size_t compute_max_num_cut_points() const;
pair<precision_t, size_t> valueCutPoint(size_t, size_t, size_t);
public:
CPPFImdlp();
CPPFImdlp(size_t, int, float);
~CPPFImdlp();
void fit(samples_t&, labels_t&);
inline cutPoints_t getCutPoints() const { return cutPoints; };
labels_t& transform(const samples_t&);
inline int get_depth() const { return depth; };
static inline string version() { return "1.1.2"; };
};
}
#endif

21
sample/lib/mdlp/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Ricardo Montañana Gómez
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,78 @@
#include "Metrics.h"
#include <set>
#include <cmath>
using namespace std;
namespace mdlp {
Metrics::Metrics(labels_t& y_, indices_t& indices_): y(y_), indices(indices_),
numClasses(computeNumClasses(0, indices.size()))
{
}
int Metrics::computeNumClasses(size_t start, size_t end)
{
set<int> nClasses;
for (auto i = start; i < end; ++i) {
nClasses.insert(y[indices[i]]);
}
return static_cast<int>(nClasses.size());
}
void Metrics::setData(const labels_t& y_, const indices_t& indices_)
{
indices = indices_;
y = y_;
numClasses = computeNumClasses(0, indices.size());
entropyCache.clear();
igCache.clear();
}
precision_t Metrics::entropy(size_t start, size_t end)
{
precision_t p;
precision_t ventropy = 0;
int nElements = 0;
labels_t counts(numClasses + 1, 0);
if (end - start < 2)
return 0;
if (entropyCache.find({ start, end }) != entropyCache.end()) {
return entropyCache[{start, end}];
}
for (auto i = &indices[start]; i != &indices[end]; ++i) {
counts[y[*i]]++;
nElements++;
}
for (auto count : counts) {
if (count > 0) {
p = static_cast<precision_t>(count) / static_cast<precision_t>(nElements);
ventropy -= p * log2(p);
}
}
entropyCache[{start, end}] = ventropy;
return ventropy;
}
precision_t Metrics::informationGain(size_t start, size_t cut, size_t end)
{
precision_t iGain;
precision_t entropyInterval;
precision_t entropyLeft;
precision_t entropyRight;
size_t nElementsLeft = cut - start;
size_t nElementsRight = end - cut;
size_t nElements = end - start;
if (igCache.find(make_tuple(start, cut, end)) != igCache.end()) {
return igCache[make_tuple(start, cut, end)];
}
entropyInterval = entropy(start, end);
entropyLeft = entropy(start, cut);
entropyRight = entropy(cut, end);
iGain = entropyInterval -
(static_cast<precision_t>(nElementsLeft) * entropyLeft +
static_cast<precision_t>(nElementsRight) * entropyRight) /
static_cast<precision_t>(nElements);
igCache[make_tuple(start, cut, end)] = iGain;
return iGain;
}
}

28
sample/lib/mdlp/Metrics.h Normal file
View File

@ -0,0 +1,28 @@
// ***************************************************************
// SPDX-FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX-FileType: SOURCE
// SPDX-License-Identifier: MIT
// ***************************************************************
#ifndef CCMETRICS_H
#define CCMETRICS_H
#include "typesFImdlp.h"
namespace mdlp {
class Metrics {
protected:
labels_t& y;
indices_t& indices;
int numClasses;
cacheEnt_t entropyCache = cacheEnt_t();
cacheIg_t igCache = cacheIg_t();
public:
Metrics(labels_t&, indices_t&);
void setData(const labels_t&, const indices_t&);
int computeNumClasses(size_t, size_t);
precision_t entropy(size_t, size_t);
precision_t informationGain(size_t, size_t, size_t);
};
}
#endif

41
sample/lib/mdlp/README.md Normal file
View File

@ -0,0 +1,41 @@
[![Build](https://github.com/rmontanana/mdlp/actions/workflows/build.yml/badge.svg)](https://github.com/rmontanana/mdlp/actions/workflows/build.yml)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=rmontanana_mdlp&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=rmontanana_mdlp)
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=rmontanana_mdlp&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=rmontanana_mdlp)
# mdlp
Discretization algorithm based on the paper by Fayyad &amp; Irani [Multi-Interval Discretization of Continuous-Valued Attributes for Classification Learning](https://www.ijcai.org/Proceedings/93-2/Papers/022.pdf)
The implementation tries to mitigate the problem of different label values with the same value of the variable:
- Sorts the values of the variable using the label values as a tie-breaker
- Once found a valid candidate for the split, it checks if the previous value is the same as actual one, and tries to get previous one, or next if the former is not possible.
Other features:
- Intervals with the same value of the variable are not taken into account for cutpoints.
- Intervals have to have more than two examples to be evaluated.
The algorithm returns the cut points for the variable.
## Sample
To run the sample, just execute the following commands:
```bash
cd sample
cmake -B build
cd build
make
./sample -f iris -m 2
./sample -h
```
## Test
To run the tests and see coverage (llvm & gcovr have to be installed), execute the following commands:
```bash
cd tests
./test
```

View File

@ -0,0 +1,24 @@
// ***************************************************************
// SPDX-FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX-FileType: SOURCE
// SPDX-License-Identifier: MIT
// ***************************************************************
#ifndef TYPES_H
#define TYPES_H
#include <vector>
#include <map>
#include <stdexcept>
using namespace std;
namespace mdlp {
typedef float precision_t;
typedef vector<precision_t> samples_t;
typedef vector<int> labels_t;
typedef vector<size_t> indices_t;
typedef vector<precision_t> cutPoints_t;
typedef map<pair<int, int>, precision_t> cacheEnt_t;
typedef map<tuple<int, int, int>, precision_t> cacheIg_t;
}
#endif

View File

@ -7,6 +7,7 @@
#include <ArffFiles.hpp> #include <ArffFiles.hpp>
#include <CPPFImdlp.h> #include <CPPFImdlp.h>
#include <bayesnet/ensembles/BoostAODE.h> #include <bayesnet/ensembles/BoostAODE.h>
#include <torch/torch.h>
std::vector<mdlp::labels_t> discretizeDataset(std::vector<mdlp::samples_t>& X, mdlp::labels_t& y) std::vector<mdlp::labels_t> discretizeDataset(std::vector<mdlp::samples_t>& X, mdlp::labels_t& y)
{ {
@ -19,7 +20,8 @@ std::vector<mdlp::labels_t> discretizeDataset(std::vector<mdlp::samples_t>& X, m
} }
return Xd; return Xd;
} }
tuple<torch::Tensor, torch::Tensor, std::vector<std::string>, std::string, map<std::string, std::vector<int>>> loadDataset(const std::string& name, bool class_last)
tuple<torch::Tensor, torch::Tensor, std::vector<std::string>, std::string, map<std::string, std::vector<int>>> loadDataset(const std::string& name, bool class_last, torch::Device device)
{ {
auto handler = ArffFiles(); auto handler = ArffFiles();
handler.load(name, class_last); handler.load(name, class_last);
@ -34,16 +36,16 @@ tuple<torch::Tensor, torch::Tensor, std::vector<std::string>, std::string, map<s
torch::Tensor Xd; torch::Tensor Xd;
auto states = map<std::string, std::vector<int>>(); auto states = map<std::string, std::vector<int>>();
auto Xr = discretizeDataset(X, y); auto Xr = discretizeDataset(X, y);
Xd = torch::zeros({ static_cast<int>(Xr.size()), static_cast<int>(Xr[0].size()) }, torch::kInt32); Xd = torch::zeros({ static_cast<int>(Xr.size()), static_cast<int>(Xr[0].size()) }, torch::kInt32).to(device);
for (int i = 0; i < features.size(); ++i) { for (int i = 0; i < features.size(); ++i) {
states[features[i]] = std::vector<int>(*max_element(Xr[i].begin(), Xr[i].end()) + 1); states[features[i]] = std::vector<int>(*max_element(Xr[i].begin(), Xr[i].end()) + 1);
auto item = states.at(features[i]); auto item = states.at(features[i]);
iota(begin(item), end(item), 0); iota(begin(item), end(item), 0);
Xd.index_put_({ i, "..." }, torch::tensor(Xr[i], torch::kInt32)); Xd.index_put_({ i, "..." }, torch::tensor(Xr[i], torch::kInt32).to(device));
} }
states[className] = std::vector<int>(*max_element(y.begin(), y.end()) + 1); states[className] = std::vector<int>(*max_element(y.begin(), y.end()) + 1);
iota(begin(states.at(className)), end(states.at(className)), 0); iota(begin(states.at(className)), end(states.at(className)), 0);
return { Xd, torch::tensor(y, torch::kInt32), features, className, states }; return { Xd, torch::tensor(y, torch::kInt32).to(device), features, className, states };
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[])
@ -53,16 +55,22 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
std::string file_name = argv[1]; std::string file_name = argv[1];
torch::Device device(torch::kCPU);
if (torch::cuda::is_available()) {
device = torch::Device(torch::kCUDA);
std::cout << "CUDA is available! Using GPU." << std::endl;
} else {
std::cout << "CUDA is not available. Using CPU." << std::endl;
}
torch::Tensor X, y; torch::Tensor X, y;
std::vector<std::string> features; std::vector<std::string> features;
std::string className; std::string className;
map<std::string, std::vector<int>> states; map<std::string, std::vector<int>> states;
auto clf = bayesnet::BoostAODE(false); // false for not using voting in predict auto clf = bayesnet::BoostAODE(false); // false for not using voting in predict
std::cout << "Library version: " << clf.getVersion() << std::endl; std::cout << "Library version: " << clf.getVersion() << std::endl;
tie(X, y, features, className, states) = loadDataset(file_name, true); tie(X, y, features, className, states) = loadDataset(file_name, true, device);
clf.fit(X, y, features, className, states, bayesnet::Smoothing_t::LAPLACE); clf.fit(X, y, features, className, states, bayesnet::Smoothing_t::LAPLACE);
auto score = clf.score(X, y); auto score = clf.score(X, y);
std::cout << "File: " << file_name << " Model: BoostAODE score: " << score << std::endl; std::cout << "File: " << file_name << " Model: BoostAODE score: " << score << std::endl;
return 0; return 0;
} }

View File

@ -10,8 +10,8 @@ if(ENABLE_TESTING)
file(GLOB_RECURSE BayesNet_SOURCES "${BayesNet_SOURCE_DIR}/bayesnet/*.cc") file(GLOB_RECURSE BayesNet_SOURCES "${BayesNet_SOURCE_DIR}/bayesnet/*.cc")
add_executable(TestBayesNet TestBayesNetwork.cc TestBayesNode.cc TestBayesClassifier.cc add_executable(TestBayesNet TestBayesNetwork.cc TestBayesNode.cc TestBayesClassifier.cc
TestBayesModels.cc TestBayesMetrics.cc TestFeatureSelection.cc TestBoostAODE.cc TestA2DE.cc TestBayesModels.cc TestBayesMetrics.cc TestFeatureSelection.cc TestBoostAODE.cc TestA2DE.cc
TestUtils.cc TestBayesEnsemble.cc TestModulesVersions.cc TestBoostA2DE.cc TestMST.cc ${BayesNet_SOURCES}) TestUtils.cc TestBayesEnsemble.cc TestModulesVersions.cc TestBoostA2DE.cc ${BayesNet_SOURCES})
target_link_libraries(TestBayesNet PUBLIC "${TORCH_LIBRARIES}" fimdlp PRIVATE Catch2::Catch2WithMain) target_link_libraries(TestBayesNet PUBLIC "${TORCH_LIBRARIES}" mdlp PRIVATE Catch2::Catch2WithMain)
add_test(NAME BayesNetworkTest COMMAND TestBayesNet) add_test(NAME BayesNetworkTest COMMAND TestBayesNet)
add_test(NAME A2DE COMMAND TestBayesNet "[A2DE]") add_test(NAME A2DE COMMAND TestBayesNet "[A2DE]")
add_test(NAME BoostA2DE COMMAND TestBayesNet "[BoostA2DE]") add_test(NAME BoostA2DE COMMAND TestBayesNet "[BoostA2DE]")
@ -24,5 +24,4 @@ if(ENABLE_TESTING)
add_test(NAME Modules COMMAND TestBayesNet "[Modules]") add_test(NAME Modules COMMAND TestBayesNet "[Modules]")
add_test(NAME Network COMMAND TestBayesNet "[Network]") add_test(NAME Network COMMAND TestBayesNet "[Network]")
add_test(NAME Node COMMAND TestBayesNet "[Node]") add_test(NAME Node COMMAND TestBayesNet "[Node]")
add_test(NAME MST COMMAND TestBayesNet "[MST]")
endif(ENABLE_TESTING) endif(ENABLE_TESTING)

View File

@ -45,5 +45,5 @@ TEST_CASE("Test graph", "[A2DE]")
auto graph = clf.graph(); auto graph = clf.graph();
REQUIRE(graph.size() == 78); REQUIRE(graph.size() == 78);
REQUIRE(graph[0] == "digraph BayesNet {\nlabel=<BayesNet A2DE_0>\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n"); REQUIRE(graph[0] == "digraph BayesNet {\nlabel=<BayesNet A2DE_0>\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n");
REQUIRE(graph[1] == "\"class\" [shape=circle, fontcolor=red, fillcolor=lightblue, style=filled ] \n"); REQUIRE(graph[1] == "class [shape=circle, fontcolor=red, fillcolor=lightblue, style=filled ] \n");
} }

View File

@ -85,7 +85,7 @@ TEST_CASE("Dump_cpt", "[Classifier]")
auto raw = RawDatasets("iris", true); auto raw = RawDatasets("iris", true);
model.fit(raw.Xt, raw.yt, raw.features, raw.className, raw.states, raw.smoothing); model.fit(raw.Xt, raw.yt, raw.features, raw.className, raw.states, raw.smoothing);
auto cpt = model.dump_cpt(); auto cpt = model.dump_cpt();
REQUIRE(cpt.size() == 1718); REQUIRE(cpt.size() == 1713);
} }
TEST_CASE("Not fitted model", "[Classifier]") TEST_CASE("Not fitted model", "[Classifier]")
{ {

View File

@ -27,13 +27,13 @@ TEST_CASE("Test Bayesian Classifiers score & version", "[Models]")
map <pair<std::string, std::string>, float> scores{ map <pair<std::string, std::string>, float> scores{
// Diabetes // Diabetes
{{"diabetes", "AODE"}, 0.82161}, {{"diabetes", "KDB"}, 0.852865}, {{"diabetes", "SPODE"}, 0.802083}, {{"diabetes", "TAN"}, 0.821615}, {{"diabetes", "AODE"}, 0.82161}, {{"diabetes", "KDB"}, 0.852865}, {{"diabetes", "SPODE"}, 0.802083}, {{"diabetes", "TAN"}, 0.821615},
{{"diabetes", "AODELd"}, 0.8125f}, {{"diabetes", "KDBLd"}, 0.80208f}, {{"diabetes", "SPODELd"}, 0.7890625f}, {{"diabetes", "TANLd"}, 0.803385437f}, {{"diabetes", "BoostAODE"}, 0.83984f}, {{"diabetes", "AODELd"}, 0.8138f}, {{"diabetes", "KDBLd"}, 0.80208f}, {{"diabetes", "SPODELd"}, 0.78646f}, {{"diabetes", "TANLd"}, 0.8099f}, {{"diabetes", "BoostAODE"}, 0.83984f},
// Ecoli // Ecoli
{{"ecoli", "AODE"}, 0.889881}, {{"ecoli", "KDB"}, 0.889881}, {{"ecoli", "SPODE"}, 0.880952}, {{"ecoli", "TAN"}, 0.892857}, {{"ecoli", "AODE"}, 0.889881}, {{"ecoli", "KDB"}, 0.889881}, {{"ecoli", "SPODE"}, 0.880952}, {{"ecoli", "TAN"}, 0.892857},
{{"ecoli", "AODELd"}, 0.875f}, {{"ecoli", "KDBLd"}, 0.880952358f}, {{"ecoli", "SPODELd"}, 0.839285731f}, {{"ecoli", "TANLd"}, 0.848214269f}, {{"ecoli", "BoostAODE"}, 0.89583f}, {{"ecoli", "AODELd"}, 0.8869f}, {{"ecoli", "KDBLd"}, 0.875f}, {{"ecoli", "SPODELd"}, 0.84226f}, {{"ecoli", "TANLd"}, 0.86905f}, {{"ecoli", "BoostAODE"}, 0.89583f},
// Glass // Glass
{{"glass", "AODE"}, 0.79439}, {{"glass", "KDB"}, 0.827103}, {{"glass", "SPODE"}, 0.775701}, {{"glass", "TAN"}, 0.827103}, {{"glass", "AODE"}, 0.79439}, {{"glass", "KDB"}, 0.827103}, {{"glass", "SPODE"}, 0.775701}, {{"glass", "TAN"}, 0.827103},
{{"glass", "AODELd"}, 0.799065411f}, {{"glass", "KDBLd"}, 0.82710278f}, {{"glass", "SPODELd"}, 0.780373812f}, {{"glass", "TANLd"}, 0.869158864f}, {{"glass", "BoostAODE"}, 0.84579f}, {{"glass", "AODELd"}, 0.79439f}, {{"glass", "KDBLd"}, 0.85047f}, {{"glass", "SPODELd"}, 0.79439f}, {{"glass", "TANLd"}, 0.86449f}, {{"glass", "BoostAODE"}, 0.84579f},
// Iris // Iris
{{"iris", "AODE"}, 0.973333}, {{"iris", "KDB"}, 0.973333}, {{"iris", "SPODE"}, 0.973333}, {{"iris", "TAN"}, 0.973333}, {{"iris", "AODE"}, 0.973333}, {{"iris", "KDB"}, 0.973333}, {{"iris", "SPODE"}, 0.973333}, {{"iris", "TAN"}, 0.973333},
{{"iris", "AODELd"}, 0.973333}, {{"iris", "KDBLd"}, 0.973333}, {{"iris", "SPODELd"}, 0.96f}, {{"iris", "TANLd"}, 0.97333f}, {{"iris", "BoostAODE"}, 0.98f} {{"iris", "AODELd"}, 0.973333}, {{"iris", "KDBLd"}, 0.973333}, {{"iris", "SPODELd"}, 0.96f}, {{"iris", "TANLd"}, 0.97333f}, {{"iris", "BoostAODE"}, 0.98f}
@ -71,10 +71,10 @@ TEST_CASE("Test Bayesian Classifiers score & version", "[Models]")
TEST_CASE("Models features & Graph", "[Models]") TEST_CASE("Models features & Graph", "[Models]")
{ {
auto graph = std::vector<std::string>({ "digraph BayesNet {\nlabel=<BayesNet Test>\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n", auto graph = std::vector<std::string>({ "digraph BayesNet {\nlabel=<BayesNet Test>\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n",
"\"class\" [shape=circle, fontcolor=red, fillcolor=lightblue, style=filled ] \n", "class [shape=circle, fontcolor=red, fillcolor=lightblue, style=filled ] \n",
"\"class\" -> \"sepallength\"", "\"class\" -> \"sepalwidth\"", "\"class\" -> \"petallength\"", "\"class\" -> \"petalwidth\"", "\"petallength\" [shape=circle] \n", "class -> sepallength", "class -> sepalwidth", "class -> petallength", "class -> petalwidth", "petallength [shape=circle] \n",
"\"petallength\" -> \"sepallength\"", "\"petalwidth\" [shape=circle] \n", "\"sepallength\" [shape=circle] \n", "petallength -> sepallength", "petalwidth [shape=circle] \n", "sepallength [shape=circle] \n",
"\"sepallength\" -> \"sepalwidth\"", "\"sepalwidth\" [shape=circle] \n", "\"sepalwidth\" -> \"petalwidth\"", "}\n" "sepallength -> sepalwidth", "sepalwidth [shape=circle] \n", "sepalwidth -> petalwidth", "}\n"
} }
); );
SECTION("Test TAN") SECTION("Test TAN")
@ -96,7 +96,7 @@ TEST_CASE("Models features & Graph", "[Models]")
clf.fit(raw.Xt, raw.yt, raw.features, raw.className, raw.states, raw.smoothing); clf.fit(raw.Xt, raw.yt, raw.features, raw.className, raw.states, raw.smoothing);
REQUIRE(clf.getNumberOfNodes() == 5); REQUIRE(clf.getNumberOfNodes() == 5);
REQUIRE(clf.getNumberOfEdges() == 7); REQUIRE(clf.getNumberOfEdges() == 7);
REQUIRE(clf.getNumberOfStates() == 27); REQUIRE(clf.getNumberOfStates() == 19);
REQUIRE(clf.getClassNumStates() == 3); REQUIRE(clf.getClassNumStates() == 3);
REQUIRE(clf.show() == std::vector<std::string>{"class -> sepallength, sepalwidth, petallength, petalwidth, ", "petallength -> sepallength, ", "petalwidth -> ", "sepallength -> sepalwidth, ", "sepalwidth -> petalwidth, "}); REQUIRE(clf.show() == std::vector<std::string>{"class -> sepallength, sepalwidth, petallength, petalwidth, ", "petallength -> sepallength, ", "petalwidth -> ", "sepallength -> sepalwidth, ", "sepalwidth -> petalwidth, "});
REQUIRE(clf.graph("Test") == graph); REQUIRE(clf.graph("Test") == graph);

View File

@ -186,11 +186,11 @@ TEST_CASE("Test Bayesian Network", "[Network]")
auto str = net.graph("Test Graph"); auto str = net.graph("Test Graph");
REQUIRE(str.size() == 7); REQUIRE(str.size() == 7);
REQUIRE(str[0] == "digraph BayesNet {\nlabel=<BayesNet Test Graph>\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n"); REQUIRE(str[0] == "digraph BayesNet {\nlabel=<BayesNet Test Graph>\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n");
REQUIRE(str[1] == "\"A\" [shape=circle] \n"); REQUIRE(str[1] == "A [shape=circle] \n");
REQUIRE(str[2] == "\"A\" -> \"B\""); REQUIRE(str[2] == "A -> B");
REQUIRE(str[3] == "\"A\" -> \"C\""); REQUIRE(str[3] == "A -> C");
REQUIRE(str[4] == "\"B\" [shape=circle] \n"); REQUIRE(str[4] == "B [shape=circle] \n");
REQUIRE(str[5] == "\"C\" [shape=circle] \n"); REQUIRE(str[5] == "C [shape=circle] \n");
REQUIRE(str[6] == "}\n"); REQUIRE(str[6] == "}\n");
} }
SECTION("Test predict") SECTION("Test predict")
@ -257,9 +257,9 @@ TEST_CASE("Test Bayesian Network", "[Network]")
REQUIRE(node->getCPT().equal(node2->getCPT())); REQUIRE(node->getCPT().equal(node2->getCPT()));
} }
} }
SECTION("Network oddities") SECTION("Test oddities")
{ {
INFO("Network oddities"); INFO("Test oddities");
buildModel(net, raw.features, raw.className); buildModel(net, raw.features, raw.className);
// predict without fitting // predict without fitting
std::vector<std::vector<int>> test = { {1, 2, 0, 1, 1}, {0, 1, 2, 0, 1}, {0, 0, 0, 0, 1}, {2, 2, 2, 2, 1} }; std::vector<std::vector<int>> test = { {1, 2, 0, 1, 1}, {0, 1, 2, 0, 1}, {0, 0, 0, 0, 1}, {2, 2, 2, 2, 1} };
@ -329,14 +329,6 @@ TEST_CASE("Test Bayesian Network", "[Network]")
std::string invalid_state = "Feature sepallength not found in states"; std::string invalid_state = "Feature sepallength not found in states";
REQUIRE_THROWS_AS(net4.fit(raw.Xv, raw.yv, raw.weightsv, raw.features, raw.className, std::map<std::string, std::vector<int>>(), raw.smoothing), std::invalid_argument); REQUIRE_THROWS_AS(net4.fit(raw.Xv, raw.yv, raw.weightsv, raw.features, raw.className, std::map<std::string, std::vector<int>>(), raw.smoothing), std::invalid_argument);
REQUIRE_THROWS_WITH(net4.fit(raw.Xv, raw.yv, raw.weightsv, raw.features, raw.className, std::map<std::string, std::vector<int>>(), raw.smoothing), invalid_state); REQUIRE_THROWS_WITH(net4.fit(raw.Xv, raw.yv, raw.weightsv, raw.features, raw.className, std::map<std::string, std::vector<int>>(), raw.smoothing), invalid_state);
// Try to add node or edge to a fitted network
auto net5 = bayesnet::Network();
buildModel(net5, raw.features, raw.className);
net5.fit(raw.Xv, raw.yv, raw.weightsv, raw.features, raw.className, raw.states, raw.smoothing);
REQUIRE_THROWS_AS(net5.addNode("A"), std::logic_error);
REQUIRE_THROWS_WITH(net5.addNode("A"), "Cannot add node to a fitted network. Initialize first.");
REQUIRE_THROWS_AS(net5.addEdge("A", "B"), std::logic_error);
REQUIRE_THROWS_WITH(net5.addEdge("A", "B"), "Cannot add edge to a fitted network. Initialize first.");
} }
} }
@ -381,7 +373,7 @@ TEST_CASE("Dump CPT", "[Network]")
0.3333 0.3333
0.3333 0.3333
0.3333 0.3333
[ CPUDoubleType{3} ] [ CPUFloatType{3} ]
* petallength: (4) : [4, 3, 3] * petallength: (4) : [4, 3, 3]
(1,.,.) = (1,.,.) =
0.9388 0.1000 0.2000 0.9388 0.1000 0.2000
@ -402,7 +394,7 @@ TEST_CASE("Dump CPT", "[Network]")
0.0204 0.1000 0.2000 0.0204 0.1000 0.2000
0.1250 0.0526 0.1667 0.1250 0.0526 0.1667
0.2000 0.0606 0.8235 0.2000 0.0606 0.8235
[ CPUDoubleType{4,3,3} ] [ CPUFloatType{4,3,3} ]
* petalwidth: (3) : [3, 6, 3] * petalwidth: (3) : [3, 6, 3]
(1,.,.) = (1,.,.) =
0.5000 0.0417 0.0714 0.5000 0.0417 0.0714
@ -427,12 +419,12 @@ TEST_CASE("Dump CPT", "[Network]")
0.1111 0.0909 0.8000 0.1111 0.0909 0.8000
0.0667 0.2000 0.8667 0.0667 0.2000 0.8667
0.0303 0.2500 0.7500 0.0303 0.2500 0.7500
[ CPUDoubleType{3,6,3} ] [ CPUFloatType{3,6,3} ]
* sepallength: (3) : [3, 3] * sepallength: (3) : [3, 3]
0.8679 0.1321 0.0377 0.8679 0.1321 0.0377
0.0943 0.3019 0.0566 0.0943 0.3019 0.0566
0.0377 0.5660 0.9057 0.0377 0.5660 0.9057
[ CPUDoubleType{3,3} ] [ CPUFloatType{3,3} ]
* sepalwidth: (6) : [6, 3, 3] * sepalwidth: (6) : [6, 3, 3]
(1,.,.) = (1,.,.) =
0.0392 0.5000 0.2857 0.0392 0.5000 0.2857
@ -463,7 +455,7 @@ TEST_CASE("Dump CPT", "[Network]")
0.5098 0.0833 0.1429 0.5098 0.0833 0.1429
0.5000 0.0476 0.1250 0.5000 0.0476 0.1250
0.2857 0.0571 0.1132 0.2857 0.0571 0.1132
[ CPUDoubleType{6,3,3} ] [ CPUFloatType{6,3,3} ]
)"; )";
REQUIRE(res == expected); REQUIRE(res == expected);
} }
@ -533,7 +525,6 @@ TEST_CASE("Test Smoothing A", "[Network]")
} }
} }
} }
TEST_CASE("Test Smoothing B", "[Network]") TEST_CASE("Test Smoothing B", "[Network]")
{ {
auto net = bayesnet::Network(); auto net = bayesnet::Network();
@ -558,41 +549,19 @@ TEST_CASE("Test Smoothing B", "[Network]")
{ "C", {0, 1} } { "C", {0, 1} }
}; };
auto weights = std::vector<double>(C.size(), 1); auto weights = std::vector<double>(C.size(), 1);
// See https://www.overleaf.com/read/tfnhpfysfkfx#2d576c example for calculations // Simple
INFO("Test Smoothing B - Laplace"); std::cout << "LAPLACE\n";
net.fit(Data, C, weights, { "X", "Y", "Z" }, "C", states, bayesnet::Smoothing_t::LAPLACE); net.fit(Data, C, weights, { "X", "Y", "Z" }, "C", states, bayesnet::Smoothing_t::LAPLACE);
auto laplace_values = std::vector<std::vector<float>>({ {0.377418, 0.622582}, {0.217821, 0.782179} }); std::cout << net.dump_cpt();
auto laplace_score = net.predict_proba({ {0, 1}, {1, 2}, {2, 3} }); std::cout << "Predict proba of {0, 1, 2} y {1, 2, 3} = " << net.predict_proba({ {0, 1}, {1, 2}, {2, 3} }) << std::endl;
for (auto i = 0; i < 2; ++i) { std::cout << "ORIGINAL\n";
for (auto j = 0; j < 2; ++j) {
REQUIRE(laplace_score.at(i).at(j) == Catch::Approx(laplace_values.at(i).at(j)).margin(threshold));
}
}
INFO("Test Smoothing B - Original");
net.fit(Data, C, weights, { "X", "Y", "Z" }, "C", states, bayesnet::Smoothing_t::ORIGINAL); net.fit(Data, C, weights, { "X", "Y", "Z" }, "C", states, bayesnet::Smoothing_t::ORIGINAL);
auto original_values = std::vector<std::vector<float>>({ {0.344769, 0.655231}, {0.0421263, 0.957874} }); std::cout << net.dump_cpt();
auto original_score = net.predict_proba({ {0, 1}, {1, 2}, {2, 3} }); std::cout << "Predict proba of {0, 1, 2} y {1, 2, 3} = " << net.predict_proba({ {0, 1}, {1, 2}, {2, 3} }) << std::endl;
for (auto i = 0; i < 2; ++i) { std::cout << "CESTNIK\n";
for (auto j = 0; j < 2; ++j) {
REQUIRE(original_score.at(i).at(j) == Catch::Approx(original_values.at(i).at(j)).margin(threshold));
}
}
INFO("Test Smoothing B - Cestnik");
net.fit(Data, C, weights, { "X", "Y", "Z" }, "C", states, bayesnet::Smoothing_t::CESTNIK); net.fit(Data, C, weights, { "X", "Y", "Z" }, "C", states, bayesnet::Smoothing_t::CESTNIK);
auto cestnik_values = std::vector<std::vector<float>>({ {0.353422, 0.646578}, {0.12364, 0.87636} }); std::cout << net.dump_cpt();
auto cestnik_score = net.predict_proba({ {0, 1}, {1, 2}, {2, 3} }); std::cout << "Predict proba of {0, 1, 2} y {1, 2, 3} = " << net.predict_proba({ {0, 1}, {1, 2}, {2, 3} }) << std::endl;
for (auto i = 0; i < 2; ++i) {
for (auto j = 0; j < 2; ++j) {
REQUIRE(cestnik_score.at(i).at(j) == Catch::Approx(cestnik_values.at(i).at(j)).margin(threshold)); }
}
}
INFO("Test Smoothing B - No smoothing");
net.fit(Data, C, weights, { "X", "Y", "Z" }, "C", states, bayesnet::Smoothing_t::NONE);
auto nosmooth_values = std::vector<std::vector<float>>({ {0.342465753, 0.65753424}, {0.0, 1.0} });
auto nosmooth_score = net.predict_proba({ {0, 1}, {1, 2}, {2, 3} });
for (auto i = 0; i < 2; ++i) {
for (auto j = 0; j < 2; ++j) {
REQUIRE(nosmooth_score.at(i).at(j) == Catch::Approx(nosmooth_values.at(i).at(j)).margin(threshold));
}
}
}

View File

@ -62,17 +62,15 @@ TEST_CASE("Test Node computeCPT", "[Node]")
// Create a vector with the names of the classes // Create a vector with the names of the classes
auto className = std::string("Class"); auto className = std::string("Class");
// weights // weights
auto weights = torch::tensor({ 1.0, 1.0, 1.0, 1.0 }, torch::kDouble); auto weights = torch::tensor({ 1.0, 1.0, 1.0, 1.0 });
std::vector<bayesnet::Node> nodes; std::vector<bayesnet::Node> nodes;
for (int i = 0; i < features.size(); i++) { for (int i = 0; i < features.size(); i++) {
auto node = bayesnet::Node(features[i]); auto node = bayesnet::Node(features[i]);
node.setNumStates(states[i]); node.setNumStates(states[i]);
nodes.push_back(node); nodes.push_back(node);
} }
// Create node class with 2 states
nodes.push_back(bayesnet::Node(className)); nodes.push_back(bayesnet::Node(className));
nodes[features.size()].setNumStates(2); nodes[features.size()].setNumStates(2);
// The network is c->f1, f2, f3 y f1->f2, f3
for (int i = 0; i < features.size(); i++) { for (int i = 0; i < features.size(); i++) {
// Add class node as parent of all feature nodes // Add class node as parent of all feature nodes
nodes[i].addParent(&nodes[features.size()]); nodes[i].addParent(&nodes[features.size()]);

View File

@ -27,192 +27,189 @@ TEST_CASE("Build basic model", "[BoostA2DE]")
auto score = clf.score(raw.Xv, raw.yv); auto score = clf.score(raw.Xv, raw.yv);
REQUIRE(score == Catch::Approx(0.919271).epsilon(raw.epsilon)); REQUIRE(score == Catch::Approx(0.919271).epsilon(raw.epsilon));
} }
TEST_CASE("Feature_select IWSS", "[BoostA2DE]") // TEST_CASE("Feature_select IWSS", "[BoostAODE]")
{ // {
auto raw = RawDatasets("glass", true); // auto raw = RawDatasets("glass", true);
auto clf = bayesnet::BoostA2DE(); // auto clf = bayesnet::BoostAODE();
clf.setHyperparameters({ {"select_features", "IWSS"}, {"threshold", 0.5 } }); // clf.setHyperparameters({ {"select_features", "IWSS"}, {"threshold", 0.5 } });
clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing); // clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing);
REQUIRE(clf.getNumberOfNodes() == 140); // REQUIRE(clf.getNumberOfNodes() == 90);
REQUIRE(clf.getNumberOfEdges() == 294); // REQUIRE(clf.getNumberOfEdges() == 153);
REQUIRE(clf.getNotes().size() == 4); // REQUIRE(clf.getNotes().size() == 2);
REQUIRE(clf.getNotes()[0] == "Used features in initialization: 4 of 9 with IWSS"); // REQUIRE(clf.getNotes()[0] == "Used features in initialization: 4 of 9 with IWSS");
REQUIRE(clf.getNotes()[1] == "Convergence threshold reached & 15 models eliminated"); // REQUIRE(clf.getNotes()[1] == "Number of models: 9");
REQUIRE(clf.getNotes()[2] == "Pairs not used in train: 2"); // }
REQUIRE(clf.getNotes()[3] == "Number of models: 14"); // TEST_CASE("Feature_select FCBF", "[BoostAODE]")
} // {
TEST_CASE("Feature_select FCBF", "[BoostA2DE]") // auto raw = RawDatasets("glass", true);
{ // auto clf = bayesnet::BoostAODE();
auto raw = RawDatasets("glass", true); // clf.setHyperparameters({ {"select_features", "FCBF"}, {"threshold", 1e-7 } });
auto clf = bayesnet::BoostA2DE(); // clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing);
clf.setHyperparameters({ {"select_features", "FCBF"}, {"threshold", 1e-7 } }); // REQUIRE(clf.getNumberOfNodes() == 90);
clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing); // REQUIRE(clf.getNumberOfEdges() == 153);
REQUIRE(clf.getNumberOfNodes() == 110); // REQUIRE(clf.getNotes().size() == 2);
REQUIRE(clf.getNumberOfEdges() == 231); // REQUIRE(clf.getNotes()[0] == "Used features in initialization: 4 of 9 with FCBF");
REQUIRE(clf.getNotes()[0] == "Used features in initialization: 4 of 9 with FCBF"); // REQUIRE(clf.getNotes()[1] == "Number of models: 9");
REQUIRE(clf.getNotes()[1] == "Convergence threshold reached & 15 models eliminated"); // }
REQUIRE(clf.getNotes()[2] == "Pairs not used in train: 2"); // TEST_CASE("Test used features in train note and score", "[BoostAODE]")
REQUIRE(clf.getNotes()[3] == "Number of models: 11"); // {
} // auto raw = RawDatasets("diabetes", true);
TEST_CASE("Test used features in train note and score", "[BoostA2DE]") // auto clf = bayesnet::BoostAODE(true);
{ // clf.setHyperparameters({
auto raw = RawDatasets("diabetes", true); // {"order", "asc"},
auto clf = bayesnet::BoostA2DE(true); // {"convergence", true},
clf.setHyperparameters({ // {"select_features","CFS"},
{"order", "asc"}, // });
{"convergence", true}, // clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing);
{"select_features","CFS"}, // REQUIRE(clf.getNumberOfNodes() == 72);
}); // REQUIRE(clf.getNumberOfEdges() == 120);
clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing); // REQUIRE(clf.getNotes().size() == 2);
REQUIRE(clf.getNumberOfNodes() == 144); // REQUIRE(clf.getNotes()[0] == "Used features in initialization: 6 of 8 with CFS");
REQUIRE(clf.getNumberOfEdges() == 288); // REQUIRE(clf.getNotes()[1] == "Number of models: 8");
REQUIRE(clf.getNotes().size() == 2); // auto score = clf.score(raw.Xv, raw.yv);
REQUIRE(clf.getNotes()[0] == "Used features in initialization: 6 of 8 with CFS"); // auto scoret = clf.score(raw.Xt, raw.yt);
REQUIRE(clf.getNotes()[1] == "Number of models: 16"); // REQUIRE(score == Catch::Approx(0.809895813).epsilon(raw.epsilon));
auto score = clf.score(raw.Xv, raw.yv); // REQUIRE(scoret == Catch::Approx(0.809895813).epsilon(raw.epsilon));
auto scoret = clf.score(raw.Xt, raw.yt); // }
REQUIRE(score == Catch::Approx(0.856771).epsilon(raw.epsilon)); // TEST_CASE("Voting vs proba", "[BoostAODE]")
REQUIRE(scoret == Catch::Approx(0.856771).epsilon(raw.epsilon)); // {
} // auto raw = RawDatasets("iris", true);
TEST_CASE("Voting vs proba", "[BoostA2DE]") // auto clf = bayesnet::BoostAODE(false);
{ // clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing);
auto raw = RawDatasets("iris", true); // auto score_proba = clf.score(raw.Xv, raw.yv);
auto clf = bayesnet::BoostA2DE(false); // auto pred_proba = clf.predict_proba(raw.Xv);
clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing); // clf.setHyperparameters({
auto score_proba = clf.score(raw.Xv, raw.yv); // {"predict_voting",true},
auto pred_proba = clf.predict_proba(raw.Xv); // });
clf.setHyperparameters({ // auto score_voting = clf.score(raw.Xv, raw.yv);
{"predict_voting",true}, // auto pred_voting = clf.predict_proba(raw.Xv);
}); // REQUIRE(score_proba == Catch::Approx(0.97333).epsilon(raw.epsilon));
auto score_voting = clf.score(raw.Xv, raw.yv); // REQUIRE(score_voting == Catch::Approx(0.98).epsilon(raw.epsilon));
auto pred_voting = clf.predict_proba(raw.Xv); // REQUIRE(pred_voting[83][2] == Catch::Approx(1.0).epsilon(raw.epsilon));
REQUIRE(score_proba == Catch::Approx(0.98).epsilon(raw.epsilon)); // REQUIRE(pred_proba[83][2] == Catch::Approx(0.86121525).epsilon(raw.epsilon));
REQUIRE(score_voting == Catch::Approx(0.946667).epsilon(raw.epsilon)); // REQUIRE(clf.dump_cpt() == "");
REQUIRE(pred_voting[83][2] == Catch::Approx(0.53508).epsilon(raw.epsilon)); // REQUIRE(clf.topological_order() == std::vector<std::string>());
REQUIRE(pred_proba[83][2] == Catch::Approx(0.48394).epsilon(raw.epsilon)); // }
REQUIRE(clf.dump_cpt() == ""); // TEST_CASE("Order asc, desc & random", "[BoostAODE]")
REQUIRE(clf.topological_order() == std::vector<std::string>()); // {
} // auto raw = RawDatasets("glass", true);
TEST_CASE("Order asc, desc & random", "[BoostA2DE]") // std::map<std::string, double> scores{
{ // {"asc", 0.83645f }, { "desc", 0.84579f }, { "rand", 0.84112 }
auto raw = RawDatasets("glass", true); // };
std::map<std::string, double> scores{ // for (const std::string& order : { "asc", "desc", "rand" }) {
{"asc", 0.752336f }, { "desc", 0.813084f }, { "rand", 0.850467 } // auto clf = bayesnet::BoostAODE();
}; // clf.setHyperparameters({
for (const std::string& order : { "asc", "desc", "rand" }) { // {"order", order},
auto clf = bayesnet::BoostA2DE(); // {"bisection", false},
clf.setHyperparameters({ // {"maxTolerance", 1},
{"order", order}, // {"convergence", false},
{"bisection", false}, // });
{"maxTolerance", 1}, // clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing);
{"convergence", false}, // auto score = clf.score(raw.Xv, raw.yv);
}); // auto scoret = clf.score(raw.Xt, raw.yt);
clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing); // INFO("BoostAODE order: " + order);
auto score = clf.score(raw.Xv, raw.yv); // REQUIRE(score == Catch::Approx(scores[order]).epsilon(raw.epsilon));
auto scoret = clf.score(raw.Xt, raw.yt); // REQUIRE(scoret == Catch::Approx(scores[order]).epsilon(raw.epsilon));
INFO("BoostA2DE order: " + order); // }
REQUIRE(score == Catch::Approx(scores[order]).epsilon(raw.epsilon)); // }
REQUIRE(scoret == Catch::Approx(scores[order]).epsilon(raw.epsilon)); // TEST_CASE("Oddities", "[BoostAODE]")
} // {
} // auto clf = bayesnet::BoostAODE();
TEST_CASE("Oddities2", "[BoostA2DE]") // auto raw = RawDatasets("iris", true);
{ // auto bad_hyper = nlohmann::json{
auto clf = bayesnet::BoostA2DE(); // { { "order", "duck" } },
auto raw = RawDatasets("iris", true); // { { "select_features", "duck" } },
auto bad_hyper = nlohmann::json{ // { { "maxTolerance", 0 } },
{ { "order", "duck" } }, // { { "maxTolerance", 5 } },
{ { "select_features", "duck" } }, // };
{ { "maxTolerance", 0 } }, // for (const auto& hyper : bad_hyper.items()) {
{ { "maxTolerance", 5 } }, // INFO("BoostAODE hyper: " + hyper.value().dump());
}; // REQUIRE_THROWS_AS(clf.setHyperparameters(hyper.value()), std::invalid_argument);
for (const auto& hyper : bad_hyper.items()) { // }
INFO("BoostA2DE hyper: " + hyper.value().dump()); // REQUIRE_THROWS_AS(clf.setHyperparameters({ {"maxTolerance", 0 } }), std::invalid_argument);
REQUIRE_THROWS_AS(clf.setHyperparameters(hyper.value()), std::invalid_argument); // auto bad_hyper_fit = nlohmann::json{
} // { { "select_features","IWSS" }, { "threshold", -0.01 } },
REQUIRE_THROWS_AS(clf.setHyperparameters({ {"maxTolerance", 0 } }), std::invalid_argument); // { { "select_features","IWSS" }, { "threshold", 0.51 } },
auto bad_hyper_fit = nlohmann::json{ // { { "select_features","FCBF" }, { "threshold", 1e-8 } },
{ { "select_features","IWSS" }, { "threshold", -0.01 } }, // { { "select_features","FCBF" }, { "threshold", 1.01 } },
{ { "select_features","IWSS" }, { "threshold", 0.51 } }, // };
{ { "select_features","FCBF" }, { "threshold", 1e-8 } }, // for (const auto& hyper : bad_hyper_fit.items()) {
{ { "select_features","FCBF" }, { "threshold", 1.01 } }, // INFO("BoostAODE hyper: " + hyper.value().dump());
}; // clf.setHyperparameters(hyper.value());
for (const auto& hyper : bad_hyper_fit.items()) { // REQUIRE_THROWS_AS(clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing, std::invalid_argument);
INFO("BoostA2DE hyper: " + hyper.value().dump()); // }
clf.setHyperparameters(hyper.value()); // }
REQUIRE_THROWS_AS(clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing), std::invalid_argument);
} // TEST_CASE("Bisection Best", "[BoostAODE]")
} // {
TEST_CASE("No features selected", "[BoostA2DE]") // auto clf = bayesnet::BoostAODE();
{ // auto raw = RawDatasets("kdd_JapaneseVowels", true, 1200, true, false);
// Check that the note "No features selected in initialization" is added // clf.setHyperparameters({
// // {"bisection", true},
auto raw = RawDatasets("iris", true); // {"maxTolerance", 3},
auto clf = bayesnet::BoostA2DE(); // {"convergence", true},
clf.setHyperparameters({ {"select_features","FCBF"}, {"threshold", 1 } }); // {"block_update", false},
clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing); // {"convergence_best", false},
REQUIRE(clf.getNotes().size() == 1); // });
REQUIRE(clf.getNotes()[0] == "No features selected in initialization"); // clf.fit(raw.X_train, raw.y_train, raw.features, raw.className, raw.states, raw.smoothing);
} // REQUIRE(clf.getNumberOfNodes() == 210);
TEST_CASE("Bisection Best", "[BoostA2DE]") // REQUIRE(clf.getNumberOfEdges() == 378);
{ // REQUIRE(clf.getNotes().size() == 1);
auto clf = bayesnet::BoostA2DE(); // REQUIRE(clf.getNotes().at(0) == "Number of models: 14");
auto raw = RawDatasets("kdd_JapaneseVowels", true, 1200, true, false); // auto score = clf.score(raw.X_test, raw.y_test);
clf.setHyperparameters({ // auto scoret = clf.score(raw.X_test, raw.y_test);
{"bisection", true}, // REQUIRE(score == Catch::Approx(0.991666675f).epsilon(raw.epsilon));
{"maxTolerance", 3}, // REQUIRE(scoret == Catch::Approx(0.991666675f).epsilon(raw.epsilon));
{"convergence", true}, // }
{"block_update", false}, // TEST_CASE("Bisection Best vs Last", "[BoostAODE]")
{"convergence_best", false}, // {
}); // auto raw = RawDatasets("kdd_JapaneseVowels", true, 1500, true, false);
clf.fit(raw.X_train, raw.y_train, raw.features, raw.className, raw.states, raw.smoothing); // auto clf = bayesnet::BoostAODE(true);
REQUIRE(clf.getNumberOfNodes() == 480); // auto hyperparameters = nlohmann::json{
REQUIRE(clf.getNumberOfEdges() == 1152); // {"bisection", true},
REQUIRE(clf.getNotes().size() == 3); // {"maxTolerance", 3},
REQUIRE(clf.getNotes().at(0) == "Convergence threshold reached & 15 models eliminated"); // {"convergence", true},
REQUIRE(clf.getNotes().at(1) == "Pairs not used in train: 83"); // {"convergence_best", true},
REQUIRE(clf.getNotes().at(2) == "Number of models: 32"); // };
auto score = clf.score(raw.X_test, raw.y_test); // clf.setHyperparameters(hyperparameters);
auto scoret = clf.score(raw.X_test, raw.y_test); // clf.fit(raw.X_train, raw.y_train, raw.features, raw.className, raw.states, raw.smoothing);
REQUIRE(score == Catch::Approx(0.966667f).epsilon(raw.epsilon)); // auto score_best = clf.score(raw.X_test, raw.y_test);
REQUIRE(scoret == Catch::Approx(0.966667f).epsilon(raw.epsilon)); // REQUIRE(score_best == Catch::Approx(0.980000019f).epsilon(raw.epsilon));
} // // Now we will set the hyperparameter to use the last accuracy
TEST_CASE("Block Update", "[BoostA2DE]") // hyperparameters["convergence_best"] = false;
{ // clf.setHyperparameters(hyperparameters);
auto clf = bayesnet::BoostA2DE(); // clf.fit(raw.X_train, raw.y_train, raw.features, raw.className, raw.states, raw.smoothing);
auto raw = RawDatasets("spambase", true, 500); // auto score_last = clf.score(raw.X_test, raw.y_test);
clf.setHyperparameters({ // REQUIRE(score_last == Catch::Approx(0.976666689f).epsilon(raw.epsilon));
{"bisection", true}, // }
{"block_update", true},
{"maxTolerance", 3}, // TEST_CASE("Block Update", "[BoostAODE]")
{"convergence", true}, // {
}); // auto clf = bayesnet::BoostAODE();
clf.fit(raw.X_train, raw.y_train, raw.features, raw.className, raw.states, raw.smoothing); // auto raw = RawDatasets("mfeat-factors", true, 500);
REQUIRE(clf.getNumberOfNodes() == 58); // clf.setHyperparameters({
REQUIRE(clf.getNumberOfEdges() == 165); // {"bisection", true},
REQUIRE(clf.getNotes().size() == 3); // {"block_update", true},
REQUIRE(clf.getNotes()[0] == "Convergence threshold reached & 15 models eliminated"); // {"maxTolerance", 3},
REQUIRE(clf.getNotes()[1] == "Pairs not used in train: 1588"); // {"convergence", true},
REQUIRE(clf.getNotes()[2] == "Number of models: 1"); // });
auto score = clf.score(raw.X_test, raw.y_test); // clf.fit(raw.X_train, raw.y_train, raw.features, raw.className, raw.states, raw.smoothing);
auto scoret = clf.score(raw.X_test, raw.y_test); // REQUIRE(clf.getNumberOfNodes() == 868);
REQUIRE(score == Catch::Approx(1.0f).epsilon(raw.epsilon)); // REQUIRE(clf.getNumberOfEdges() == 1724);
REQUIRE(scoret == Catch::Approx(1.0f).epsilon(raw.epsilon)); // REQUIRE(clf.getNotes().size() == 3);
// // REQUIRE(clf.getNotes()[0] == "Convergence threshold reached & 15 models eliminated");
// std::cout << "Number of nodes " << clf.getNumberOfNodes() << std::endl; // REQUIRE(clf.getNotes()[1] == "Used features in train: 19 of 216");
// std::cout << "Number of edges " << clf.getNumberOfEdges() << std::endl; // REQUIRE(clf.getNotes()[2] == "Number of models: 4");
// std::cout << "Notes size " << clf.getNotes().size() << std::endl; // auto score = clf.score(raw.X_test, raw.y_test);
// for (auto note : clf.getNotes()) { // auto scoret = clf.score(raw.X_test, raw.y_test);
// std::cout << note << std::endl; // REQUIRE(score == Catch::Approx(0.99f).epsilon(raw.epsilon));
// } // REQUIRE(scoret == Catch::Approx(0.99f).epsilon(raw.epsilon));
// std::cout << "Score " << score << std::endl; // //
} // // std::cout << "Number of nodes " << clf.getNumberOfNodes() << std::endl;
TEST_CASE("Test graph b2a2de", "[BoostA2DE]") // // std::cout << "Number of edges " << clf.getNumberOfEdges() << std::endl;
{ // // std::cout << "Notes size " << clf.getNotes().size() << std::endl;
auto raw = RawDatasets("iris", true); // // for (auto note : clf.getNotes()) {
auto clf = bayesnet::BoostA2DE(); // // std::cout << note << std::endl;
clf.fit(raw.Xv, raw.yv, raw.features, raw.className, raw.states, raw.smoothing); // // }
auto graph = clf.graph(); // // std::cout << "Score " << score << std::endl;
REQUIRE(graph.size() == 26); // }
REQUIRE(graph[0] == "digraph BayesNet {\nlabel=<BayesNet BoostA2DE_0>\nfontsize=30\nfontcolor=blue\nlabelloc=t\nlayout=circo\n");
REQUIRE(graph[1] == "\"class\" [shape=circle, fontcolor=red, fillcolor=lightblue, style=filled ] \n");
}

View File

@ -1,72 +0,0 @@
// ***************************************************************
// SPDX-FileCopyrightText: Copyright 2024 Ricardo Montañana Gómez
// SPDX-FileType: SOURCE
// SPDX-License-Identifier: MIT
// ***************************************************************
#include <catch2/catch_test_macros.hpp>
#include <catch2/catch_approx.hpp>
#include <catch2/generators/catch_generators.hpp>
#include <catch2/matchers/catch_matchers.hpp>
#include <string>
#include <vector>
#include "TestUtils.h"
#include "bayesnet/utils/Mst.h"
TEST_CASE("MST::insertElement tests", "[MST]")
{
bayesnet::MST mst({}, torch::tensor({}), 0);
SECTION("Insert into an empty list")
{
std::list<int> variables;
mst.insertElement(variables, 5);
REQUIRE(variables == std::list<int>{5});
}
SECTION("Insert a non-duplicate element")
{
std::list<int> variables = { 1, 2, 3 };
mst.insertElement(variables, 4);
REQUIRE(variables == std::list<int>{4, 1, 2, 3});
}
SECTION("Insert a duplicate element")
{
std::list<int> variables = { 1, 2, 3 };
mst.insertElement(variables, 2);
REQUIRE(variables == std::list<int>{1, 2, 3});
}
}
TEST_CASE("MST::reorder tests", "[MST]")
{
bayesnet::MST mst({}, torch::tensor({}), 0);
SECTION("Reorder simple graph")
{
std::vector<std::pair<float, std::pair<int, int>>> T = { {2.0, {1, 2}}, {1.0, {0, 1}} };
auto result = mst.reorder(T, 0);
REQUIRE(result == std::vector<std::pair<int, int>>{{0, 1}, { 1, 2 }});
}
SECTION("Reorder with disconnected graph")
{
std::vector<std::pair<float, std::pair<int, int>>> T = { {2.0, {2, 3}}, {1.0, {0, 1}} };
auto result = mst.reorder(T, 0);
REQUIRE(result == std::vector<std::pair<int, int>>{{0, 1}, { 2, 3 }});
}
}
TEST_CASE("MST::maximumSpanningTree tests", "[MST]")
{
std::vector<std::string> features = { "A", "B", "C" };
auto weights = torch::tensor({
{0.0, 1.0, 2.0},
{1.0, 0.0, 3.0},
{2.0, 3.0, 0.0}
});
bayesnet::MST mst(features, weights, 0);
SECTION("MST of a complete graph")
{
auto result = mst.maximumSpanningTree();
REQUIRE(result.size() == 2); // Un MST para 3 nodos tiene 2 aristas
}
}

View File

@ -16,7 +16,7 @@
#include "TestUtils.h" #include "TestUtils.h"
std::map<std::string, std::string> modules = { std::map<std::string, std::string> modules = {
{ "mdlp", "2.0.1" }, { "mdlp", "2.0.0" },
{ "Folding", "1.1.0" }, { "Folding", "1.1.0" },
{ "json", "3.11" }, { "json", "3.11" },
{ "ArffFiles", "1.1.0" } { "ArffFiles", "1.1.0" }

File diff suppressed because it is too large Load Diff

@ -1 +1 @@
Subproject commit a4329f5f9dfdb18ee3faa63bd5b665f2f253b8d2 Subproject commit a5316928d408266aa425f64131ab0f592b010a8d

@ -1 +1 @@
Subproject commit 506276c59217429c93abd2fe9507c7f45eb81072 Subproject commit 4e8d92bf02f7d1c8006a0e7a5ecabd8e62d98502