Compare commits
10 Commits
xlsx
...
solveexcep
Author | SHA1 | Date | |
---|---|---|---|
c35030f137
|
|||
182b07ed90
|
|||
7806f961e2
|
|||
7c3e315ae7
|
|||
284ef6dfd1
|
|||
1c6af619b5
|
|||
86ffdfd6f3
|
|||
d82148079d
|
|||
067430fd1b
|
|||
f5d0d16365 |
31
.clang-uml
Normal file
31
.clang-uml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
compilation_database_dir: build
|
||||||
|
output_directory: puml
|
||||||
|
diagrams:
|
||||||
|
BayesNet:
|
||||||
|
type: class
|
||||||
|
glob:
|
||||||
|
- src/BayesNet/*.cc
|
||||||
|
- src/Platform/*.cc
|
||||||
|
using_namespace: bayesnet
|
||||||
|
include:
|
||||||
|
namespaces:
|
||||||
|
- bayesnet
|
||||||
|
- platform
|
||||||
|
plantuml:
|
||||||
|
after:
|
||||||
|
- "note left of {{ alias(\"MyProjectMain\") }}: Main class of myproject library."
|
||||||
|
sequence:
|
||||||
|
type: sequence
|
||||||
|
glob:
|
||||||
|
- src/Platform/main.cc
|
||||||
|
combine_free_functions_into_file_participants: true
|
||||||
|
using_namespace:
|
||||||
|
- std
|
||||||
|
- bayesnet
|
||||||
|
- platform
|
||||||
|
include:
|
||||||
|
paths:
|
||||||
|
- src/BayesNet
|
||||||
|
- src/Platform
|
||||||
|
start_from:
|
||||||
|
- function: main(int,const char **)
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -35,3 +35,4 @@ build/
|
|||||||
*.dSYM/**
|
*.dSYM/**
|
||||||
cmake-build*/**
|
cmake-build*/**
|
||||||
.idea
|
.idea
|
||||||
|
puml/**
|
||||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -10,3 +10,6 @@
|
|||||||
[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
|
||||||
|
[submodule "lib/openXLSX"]
|
||||||
|
path = lib/openXLSX
|
||||||
|
url = https://github.com/troldal/OpenXLSX.git
|
||||||
|
16
.vscode/launch.json
vendored
16
.vscode/launch.json
vendored
@@ -10,7 +10,7 @@
|
|||||||
"-d",
|
"-d",
|
||||||
"iris",
|
"iris",
|
||||||
"-m",
|
"-m",
|
||||||
"KDB",
|
"TANLd",
|
||||||
"-s",
|
"-s",
|
||||||
"271",
|
"271",
|
||||||
"-p",
|
"-p",
|
||||||
@@ -25,17 +25,17 @@
|
|||||||
"program": "${workspaceFolder}/build/src/Platform/main",
|
"program": "${workspaceFolder}/build/src/Platform/main",
|
||||||
"args": [
|
"args": [
|
||||||
"-m",
|
"-m",
|
||||||
"BoostAODE",
|
"AODE",
|
||||||
"-p",
|
"-p",
|
||||||
"/Users/rmontanana/Code/discretizbench/datasets",
|
"/home/rmontanana/Code/discretizbench/datasets",
|
||||||
"--discretize",
|
|
||||||
"--stratified",
|
"--stratified",
|
||||||
"-d",
|
"-d",
|
||||||
"glass",
|
"mfeat-morphological",
|
||||||
"--hyperparameters",
|
"--discretize"
|
||||||
"{\"repeatSparent\": true, \"maxModels\": 12}"
|
// "--hyperparameters",
|
||||||
|
// "{\"repeatSparent\": true, \"maxModels\": 12}"
|
||||||
],
|
],
|
||||||
"cwd": "/Users/rmontanana/Code/discretizbench",
|
"cwd": "/home/rmontanana/Code/discretizbench",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
project(BayesNet
|
project(BayesNet
|
||||||
VERSION 0.1.0
|
VERSION 0.2.0
|
||||||
DESCRIPTION "Bayesian Network and basic classifiers Library."
|
DESCRIPTION "Bayesian Network and basic classifiers Library."
|
||||||
HOMEPAGE_URL "https://github.com/rmontanana/bayesnet"
|
HOMEPAGE_URL "https://github.com/rmontanana/bayesnet"
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
@@ -30,7 +30,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
|
|||||||
option(ENABLE_CLANG_TIDY "Enable to add clang tidy." OFF)
|
option(ENABLE_CLANG_TIDY "Enable to add clang tidy." OFF)
|
||||||
option(ENABLE_TESTING "Unit testing build" OFF)
|
option(ENABLE_TESTING "Unit testing build" OFF)
|
||||||
option(CODE_COVERAGE "Collect coverage from test library" OFF)
|
option(CODE_COVERAGE "Collect coverage from test library" OFF)
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||||
# CMakes modules
|
# CMakes modules
|
||||||
# --------------
|
# --------------
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
|
||||||
@@ -40,8 +40,7 @@ if (CODE_COVERAGE)
|
|||||||
enable_testing()
|
enable_testing()
|
||||||
include(CodeCoverage)
|
include(CodeCoverage)
|
||||||
MESSAGE("Code coverage enabled")
|
MESSAGE("Code coverage enabled")
|
||||||
set(CMAKE_C_FLAGS " ${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -O0")
|
||||||
set(CMAKE_CXX_FLAGS " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
|
||||||
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)
|
||||||
|
|
||||||
|
3
Makefile
3
Makefile
@@ -32,6 +32,9 @@ clean: ## Clean the debug info
|
|||||||
find . -name "*.gcda" -print0 | xargs -0 rm
|
find . -name "*.gcda" -print0 | xargs -0 rm
|
||||||
@echo ">>> Done";
|
@echo ">>> Done";
|
||||||
|
|
||||||
|
clang-uml: ## Create uml class and sequence diagrams
|
||||||
|
clang-uml -p --add-compile-flag -I /usr/lib/gcc/x86_64-redhat-linux/8/include/
|
||||||
|
|
||||||
debug: ## Build a debug version of the project
|
debug: ## Build a debug version of the project
|
||||||
@echo ">>> Building Debug BayesNet ...";
|
@echo ">>> Building Debug BayesNet ...";
|
||||||
@if [ -d ./build ]; then rm -rf ./build; fi
|
@if [ -d ./build ]; then rm -rf ./build; fi
|
||||||
|
12
TAN_iris.dot
12
TAN_iris.dot
@@ -1,12 +0,0 @@
|
|||||||
digraph BayesNet {
|
|
||||||
label=<BayesNet >
|
|
||||||
fontsize=30
|
|
||||||
fontcolor=blue
|
|
||||||
labelloc=t
|
|
||||||
layout=circo
|
|
||||||
class [shape=circle, fontcolor=red, fillcolor=lightblue, style=filled ]
|
|
||||||
class -> sepallength class -> sepalwidth class -> petallength class -> petalwidth petallength [shape=circle]
|
|
||||||
petallength -> sepallength petalwidth [shape=circle]
|
|
||||||
sepallength [shape=circle]
|
|
||||||
sepallength -> sepalwidth sepalwidth [shape=circle]
|
|
||||||
sepalwidth -> petalwidth }
|
|
@@ -1 +0,0 @@
|
|||||||
null
|
|
BIN
diagrams/BayesNet.pdf
Executable file
BIN
diagrams/BayesNet.pdf
Executable file
Binary file not shown.
@@ -10,7 +10,7 @@
|
|||||||
#include "Folding.h"
|
#include "Folding.h"
|
||||||
#include "Models.h"
|
#include "Models.h"
|
||||||
#include "modelRegister.h"
|
#include "modelRegister.h"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@@ -195,11 +195,11 @@ int main(int argc, char** argv)
|
|||||||
Xt.index_put_({ i, "..." }, torch::tensor(Xd[i], torch::kInt32));
|
Xt.index_put_({ i, "..." }, torch::tensor(Xd[i], torch::kInt32));
|
||||||
}
|
}
|
||||||
float total_score = 0, total_score_train = 0, score_train, score_test;
|
float total_score = 0, total_score_train = 0, score_train, score_test;
|
||||||
Fold* fold;
|
platform::Fold* fold;
|
||||||
if (stratified)
|
if (stratified)
|
||||||
fold = new StratifiedKFold(nFolds, y, seed);
|
fold = new platform::StratifiedKFold(nFolds, y, seed);
|
||||||
else
|
else
|
||||||
fold = new KFold(nFolds, y.size(), seed);
|
fold = new platform::KFold(nFolds, y.size(), seed);
|
||||||
for (auto i = 0; i < nFolds; ++i) {
|
for (auto i = 0; i < nFolds; ++i) {
|
||||||
auto [train, test] = fold->getFold(i);
|
auto [train, test] = fold->getFold(i);
|
||||||
cout << "Fold: " << i + 1 << endl;
|
cout << "Fold: " << i + 1 << endl;
|
||||||
|
@@ -10,7 +10,6 @@ namespace bayesnet {
|
|||||||
AODE();
|
AODE();
|
||||||
virtual ~AODE() {};
|
virtual ~AODE() {};
|
||||||
vector<string> graph(const string& title = "AODE") const override;
|
vector<string> graph(const string& title = "AODE") const override;
|
||||||
void setHyperparameters(nlohmann::json& hyperparameters) override {};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@@ -4,9 +4,9 @@
|
|||||||
namespace bayesnet {
|
namespace bayesnet {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
AODELd::AODELd() : Ensemble(), Proposal(dataset, features, className) {}
|
AODELd::AODELd() : Ensemble(), Proposal(dataset, features, className) {}
|
||||||
AODELd& AODELd::fit(torch::Tensor& X_, torch::Tensor& y_, vector<string>& features_, string className_, map<string, vector<int>>& states_)
|
AODELd& AODELd::fit(torch::Tensor& X_, torch::Tensor& y_, const vector<string>& features_, const string& className_, map<string, vector<int>>& states_)
|
||||||
{
|
{
|
||||||
// This first part should go in a Classifier method called fit_local_discretization o fit_float...
|
checkInput(X_, y_);
|
||||||
features = features_;
|
features = features_;
|
||||||
className = className_;
|
className = className_;
|
||||||
Xf = X_;
|
Xf = X_;
|
||||||
@@ -26,6 +26,7 @@ namespace bayesnet {
|
|||||||
models.push_back(std::make_unique<SPODELd>(i));
|
models.push_back(std::make_unique<SPODELd>(i));
|
||||||
}
|
}
|
||||||
n_models = models.size();
|
n_models = models.size();
|
||||||
|
significanceModels = vector<double>(n_models, 1.0);
|
||||||
}
|
}
|
||||||
void AODELd::trainModel(const torch::Tensor& weights)
|
void AODELd::trainModel(const torch::Tensor& weights)
|
||||||
{
|
{
|
||||||
|
@@ -12,11 +12,10 @@ namespace bayesnet {
|
|||||||
void buildModel(const torch::Tensor& weights) override;
|
void buildModel(const torch::Tensor& weights) override;
|
||||||
public:
|
public:
|
||||||
AODELd();
|
AODELd();
|
||||||
AODELd& fit(torch::Tensor& X_, torch::Tensor& y_, vector<string>& features_, string className_, map<string, vector<int>>& states_) override;
|
AODELd& fit(torch::Tensor& X_, torch::Tensor& y_, const vector<string>& features_, const string& className_, map<string, vector<int>>& states_) override;
|
||||||
virtual ~AODELd() = default;
|
virtual ~AODELd() = default;
|
||||||
vector<string> graph(const string& name = "AODE") const override;
|
vector<string> graph(const string& name = "AODELd") const override;
|
||||||
static inline string version() { return "0.0.1"; };
|
static inline string version() { return "0.0.1"; };
|
||||||
void setHyperparameters(nlohmann::json& hyperparameters) override {};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // !AODELD_H
|
#endif // !AODELD_H
|
@@ -10,11 +10,11 @@ namespace bayesnet {
|
|||||||
virtual void trainModel(const torch::Tensor& weights) = 0;
|
virtual void trainModel(const torch::Tensor& weights) = 0;
|
||||||
public:
|
public:
|
||||||
// X is nxm vector, y is nx1 vector
|
// X is nxm vector, y is nx1 vector
|
||||||
virtual BaseClassifier& fit(vector<vector<int>>& X, vector<int>& y, vector<string>& features, string className, map<string, vector<int>>& states) = 0;
|
virtual BaseClassifier& fit(vector<vector<int>>& X, vector<int>& y, const vector<string>& features, const string& className, map<string, vector<int>>& states) = 0;
|
||||||
// X is nxm tensor, y is nx1 tensor
|
// X is nxm tensor, y is nx1 tensor
|
||||||
virtual BaseClassifier& fit(torch::Tensor& X, torch::Tensor& y, vector<string>& features, string className, map<string, vector<int>>& states) = 0;
|
virtual BaseClassifier& fit(torch::Tensor& X, torch::Tensor& y, const vector<string>& features, const string& className, map<string, vector<int>>& states) = 0;
|
||||||
virtual BaseClassifier& fit(torch::Tensor& dataset, vector<string>& features, string className, map<string, vector<int>>& states) = 0;
|
virtual BaseClassifier& fit(torch::Tensor& dataset, const vector<string>& features, const string& className, map<string, vector<int>>& states) = 0;
|
||||||
virtual BaseClassifier& fit(torch::Tensor& dataset, vector<string>& features, string className, map<string, vector<int>>& states, const torch::Tensor& weights) = 0;
|
virtual BaseClassifier& fit(torch::Tensor& dataset, const vector<string>& features, const string& className, map<string, vector<int>>& states, const torch::Tensor& weights) = 0;
|
||||||
virtual ~BaseClassifier() = default;
|
virtual ~BaseClassifier() = default;
|
||||||
torch::Tensor virtual predict(torch::Tensor& X) = 0;
|
torch::Tensor virtual predict(torch::Tensor& X) = 0;
|
||||||
vector<int> virtual predict(vector<vector<int>>& X) = 0;
|
vector<int> virtual predict(vector<vector<int>>& X) = 0;
|
||||||
@@ -25,7 +25,7 @@ namespace bayesnet {
|
|||||||
int virtual getNumberOfStates() const = 0;
|
int virtual getNumberOfStates() const = 0;
|
||||||
vector<string> virtual show() const = 0;
|
vector<string> virtual show() const = 0;
|
||||||
vector<string> virtual graph(const string& title = "") const = 0;
|
vector<string> virtual graph(const string& title = "") const = 0;
|
||||||
const string inline getVersion() const { return "0.1.0"; };
|
const string inline getVersion() const { return "0.2.0"; };
|
||||||
vector<string> virtual topological_order() = 0;
|
vector<string> virtual topological_order() = 0;
|
||||||
void virtual dump_cpt()const = 0;
|
void virtual dump_cpt()const = 0;
|
||||||
virtual void setHyperparameters(nlohmann::json& hyperparameters) = 0;
|
virtual void setHyperparameters(nlohmann::json& hyperparameters) = 0;
|
||||||
|
@@ -77,7 +77,6 @@ namespace bayesnet {
|
|||||||
auto source = vector<string>(features);
|
auto source = vector<string>(features);
|
||||||
source.push_back(className);
|
source.push_back(className);
|
||||||
auto combinations = doCombinations(source);
|
auto combinations = doCombinations(source);
|
||||||
double totalWeight = weights.sum().item<double>();
|
|
||||||
// Compute class prior
|
// Compute class prior
|
||||||
auto margin = torch::zeros({ classNumStates }, torch::kFloat);
|
auto margin = torch::zeros({ classNumStates }, torch::kFloat);
|
||||||
for (int value = 0; value < classNumStates; ++value) {
|
for (int value = 0; value < classNumStates; ++value) {
|
||||||
|
@@ -37,7 +37,6 @@ namespace bayesnet {
|
|||||||
// Step 0: Set the finish condition
|
// Step 0: Set the finish condition
|
||||||
// if not repeatSparent a finish condition is run out of features
|
// if not repeatSparent a finish condition is run out of features
|
||||||
// n_models == maxModels
|
// n_models == maxModels
|
||||||
int numClasses = states[className].size();
|
|
||||||
while (!exitCondition) {
|
while (!exitCondition) {
|
||||||
// Step 1: Build ranking with mutual information
|
// Step 1: Build ranking with mutual information
|
||||||
auto featureSelection = metrics.SelectKBestWeighted(weights_, ascending, n); // Get all the features sorted
|
auto featureSelection = metrics.SelectKBestWeighted(weights_, ascending, n); // Get all the features sorted
|
||||||
|
@@ -5,7 +5,7 @@ namespace bayesnet {
|
|||||||
using namespace torch;
|
using namespace torch;
|
||||||
|
|
||||||
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) {}
|
||||||
Classifier& Classifier::build(vector<string>& features, string className, map<string, vector<int>>& states, const torch::Tensor& weights)
|
Classifier& Classifier::build(const vector<string>& features, const string& className, map<string, vector<int>>& states, const torch::Tensor& weights)
|
||||||
{
|
{
|
||||||
this->features = features;
|
this->features = features;
|
||||||
this->className = className;
|
this->className = className;
|
||||||
@@ -13,7 +13,7 @@ namespace bayesnet {
|
|||||||
m = dataset.size(1);
|
m = dataset.size(1);
|
||||||
n = dataset.size(0) - 1;
|
n = dataset.size(0) - 1;
|
||||||
checkFitParameters();
|
checkFitParameters();
|
||||||
auto n_classes = states[className].size();
|
auto n_classes = states.at(className).size();
|
||||||
metrics = Metrics(dataset, features, className, n_classes);
|
metrics = Metrics(dataset, features, className, n_classes);
|
||||||
model.initialize();
|
model.initialize();
|
||||||
buildModel(weights);
|
buildModel(weights);
|
||||||
@@ -39,7 +39,7 @@ namespace bayesnet {
|
|||||||
model.fit(dataset, weights, features, className, states);
|
model.fit(dataset, weights, features, className, states);
|
||||||
}
|
}
|
||||||
// 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
|
||||||
Classifier& Classifier::fit(torch::Tensor& X, torch::Tensor& y, vector<string>& features, string className, map<string, vector<int>>& states)
|
Classifier& Classifier::fit(torch::Tensor& X, torch::Tensor& y, const vector<string>& features, const string& className, map<string, vector<int>>& states)
|
||||||
{
|
{
|
||||||
dataset = X;
|
dataset = X;
|
||||||
buildDataset(y);
|
buildDataset(y);
|
||||||
@@ -47,7 +47,7 @@ namespace bayesnet {
|
|||||||
return build(features, className, states, weights);
|
return build(features, className, states, weights);
|
||||||
}
|
}
|
||||||
// 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
|
||||||
Classifier& Classifier::fit(vector<vector<int>>& X, vector<int>& y, vector<string>& features, string className, map<string, vector<int>>& states)
|
Classifier& Classifier::fit(vector<vector<int>>& X, vector<int>& y, const vector<string>& features, const string& className, map<string, vector<int>>& states)
|
||||||
{
|
{
|
||||||
dataset = torch::zeros({ static_cast<int>(X.size()), static_cast<int>(X[0].size()) }, kInt32);
|
dataset = torch::zeros({ static_cast<int>(X.size()), static_cast<int>(X[0].size()) }, kInt32);
|
||||||
for (int i = 0; i < X.size(); ++i) {
|
for (int i = 0; i < X.size(); ++i) {
|
||||||
@@ -58,19 +58,22 @@ namespace bayesnet {
|
|||||||
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);
|
||||||
return build(features, className, states, weights);
|
return build(features, className, states, weights);
|
||||||
}
|
}
|
||||||
Classifier& Classifier::fit(torch::Tensor& dataset, vector<string>& features, string className, map<string, vector<int>>& states)
|
Classifier& Classifier::fit(torch::Tensor& dataset, const vector<string>& features, const string& className, map<string, vector<int>>& states)
|
||||||
{
|
{
|
||||||
this->dataset = dataset;
|
this->dataset = dataset;
|
||||||
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);
|
||||||
return build(features, className, states, weights);
|
return build(features, className, states, weights);
|
||||||
}
|
}
|
||||||
Classifier& Classifier::fit(torch::Tensor& dataset, vector<string>& features, string className, map<string, vector<int>>& states, const torch::Tensor& weights)
|
Classifier& Classifier::fit(torch::Tensor& dataset, const vector<string>& features, const string& className, map<string, vector<int>>& states, const torch::Tensor& weights)
|
||||||
{
|
{
|
||||||
this->dataset = dataset;
|
this->dataset = dataset;
|
||||||
return build(features, className, states, weights);
|
return build(features, className, states, weights);
|
||||||
}
|
}
|
||||||
void Classifier::checkFitParameters()
|
void Classifier::checkFitParameters()
|
||||||
{
|
{
|
||||||
|
if (torch::is_floating_point(dataset)) {
|
||||||
|
throw invalid_argument("dataset (X, y) must be of type Integer");
|
||||||
|
}
|
||||||
if (n != features.size()) {
|
if (n != features.size()) {
|
||||||
throw invalid_argument("X " + to_string(n) + " and features " + to_string(features.size()) + " must have the same number of features");
|
throw invalid_argument("X " + to_string(n) + " and features " + to_string(features.size()) + " must have the same number of features");
|
||||||
}
|
}
|
||||||
@@ -160,4 +163,10 @@ namespace bayesnet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void Classifier::setHyperparameters(nlohmann::json& hyperparameters)
|
||||||
|
{
|
||||||
|
// Check if hyperparameters are valid, default is no hyperparameters
|
||||||
|
const vector<string> validKeys = { };
|
||||||
|
checkHyperparameters(validKeys, hyperparameters);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -11,7 +11,7 @@ namespace bayesnet {
|
|||||||
class Classifier : public BaseClassifier {
|
class Classifier : public BaseClassifier {
|
||||||
private:
|
private:
|
||||||
void buildDataset(torch::Tensor& y);
|
void buildDataset(torch::Tensor& y);
|
||||||
Classifier& build(vector<string>& features, string className, map<string, vector<int>>& states, const torch::Tensor& weights);
|
Classifier& build(const vector<string>& features, const string& className, map<string, vector<int>>& states, const torch::Tensor& weights);
|
||||||
protected:
|
protected:
|
||||||
bool fitted;
|
bool fitted;
|
||||||
int m, n; // m: number of samples, n: number of features
|
int m, n; // m: number of samples, n: number of features
|
||||||
@@ -28,10 +28,10 @@ namespace bayesnet {
|
|||||||
public:
|
public:
|
||||||
Classifier(Network model);
|
Classifier(Network model);
|
||||||
virtual ~Classifier() = default;
|
virtual ~Classifier() = default;
|
||||||
Classifier& fit(vector<vector<int>>& X, vector<int>& y, vector<string>& features, string className, map<string, vector<int>>& states) override;
|
Classifier& fit(vector<vector<int>>& X, vector<int>& y, const vector<string>& features, const string& className, map<string, vector<int>>& states) override;
|
||||||
Classifier& fit(torch::Tensor& X, torch::Tensor& y, vector<string>& features, string className, map<string, vector<int>>& states) override;
|
Classifier& fit(torch::Tensor& X, torch::Tensor& y, const vector<string>& features, const string& className, map<string, vector<int>>& states) override;
|
||||||
Classifier& fit(torch::Tensor& dataset, vector<string>& features, string className, map<string, vector<int>>& states) override;
|
Classifier& fit(torch::Tensor& dataset, const vector<string>& features, const string& className, map<string, vector<int>>& states) override;
|
||||||
Classifier& fit(torch::Tensor& dataset, vector<string>& features, string className, map<string, vector<int>>& states, const torch::Tensor& weights) override;
|
Classifier& fit(torch::Tensor& dataset, const vector<string>& features, const string& className, map<string, vector<int>>& states, const torch::Tensor& weights) override;
|
||||||
void addNodes();
|
void addNodes();
|
||||||
int getNumberOfNodes() const override;
|
int getNumberOfNodes() const override;
|
||||||
int getNumberOfEdges() const override;
|
int getNumberOfEdges() const override;
|
||||||
@@ -43,6 +43,7 @@ namespace bayesnet {
|
|||||||
vector<string> show() const override;
|
vector<string> show() const override;
|
||||||
vector<string> topological_order() override;
|
vector<string> topological_order() override;
|
||||||
void dump_cpt() const override;
|
void dump_cpt() const override;
|
||||||
|
void setHyperparameters(nlohmann::json& hyperparameters) override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace bayesnet {
|
namespace bayesnet {
|
||||||
using namespace torch;
|
using namespace torch;
|
||||||
|
|
||||||
Ensemble::Ensemble() : Classifier(Network()) {}
|
Ensemble::Ensemble() : Classifier(Network()), n_models(0) {}
|
||||||
|
|
||||||
void Ensemble::trainModel(const torch::Tensor& weights)
|
void Ensemble::trainModel(const torch::Tensor& weights)
|
||||||
{
|
{
|
||||||
@@ -17,9 +17,13 @@ namespace bayesnet {
|
|||||||
{
|
{
|
||||||
auto y_pred_ = y_pred.accessor<int, 2>();
|
auto y_pred_ = y_pred.accessor<int, 2>();
|
||||||
vector<int> y_pred_final;
|
vector<int> y_pred_final;
|
||||||
|
int numClasses = states.at(className).size();
|
||||||
|
// y_pred is m x n_models with the prediction of every model for each sample
|
||||||
for (int i = 0; i < y_pred.size(0); ++i) {
|
for (int i = 0; i < y_pred.size(0); ++i) {
|
||||||
vector<double> votes(y_pred.size(1), 0);
|
// votes store in each index (value of class) the significance added by each model
|
||||||
for (int j = 0; j < y_pred.size(1); ++j) {
|
// i.e. votes[0] contains how much value has the value 0 of class. That value is generated by the models predictions
|
||||||
|
vector<double> votes(numClasses, 0.0);
|
||||||
|
for (int j = 0; j < n_models; ++j) {
|
||||||
votes[y_pred_[i][j]] += significanceModels[j];
|
votes[y_pred_[i][j]] += significanceModels[j];
|
||||||
}
|
}
|
||||||
// argsort in descending order
|
// argsort in descending order
|
||||||
@@ -34,7 +38,6 @@ namespace bayesnet {
|
|||||||
throw logic_error("Ensemble has not been fitted");
|
throw logic_error("Ensemble has not been fitted");
|
||||||
}
|
}
|
||||||
Tensor y_pred = torch::zeros({ X.size(1), n_models }, kInt32);
|
Tensor y_pred = torch::zeros({ X.size(1), n_models }, kInt32);
|
||||||
//Create a threadpool
|
|
||||||
auto threads{ vector<thread>() };
|
auto threads{ vector<thread>() };
|
||||||
mutex mtx;
|
mutex mtx;
|
||||||
for (auto i = 0; i < n_models; ++i) {
|
for (auto i = 0; i < n_models; ++i) {
|
||||||
|
@@ -4,6 +4,18 @@ namespace bayesnet {
|
|||||||
using namespace torch;
|
using namespace torch;
|
||||||
|
|
||||||
KDB::KDB(int k, float theta) : Classifier(Network()), k(k), theta(theta) {}
|
KDB::KDB(int k, float theta) : Classifier(Network()), k(k), theta(theta) {}
|
||||||
|
void KDB::setHyperparameters(nlohmann::json& hyperparameters)
|
||||||
|
{
|
||||||
|
// Check if hyperparameters are valid
|
||||||
|
const vector<string> validKeys = { "k", "theta" };
|
||||||
|
checkHyperparameters(validKeys, hyperparameters);
|
||||||
|
if (hyperparameters.contains("k")) {
|
||||||
|
k = hyperparameters["k"];
|
||||||
|
}
|
||||||
|
if (hyperparameters.contains("theta")) {
|
||||||
|
theta = hyperparameters["theta"];
|
||||||
|
}
|
||||||
|
}
|
||||||
void KDB::buildModel(const torch::Tensor& weights)
|
void KDB::buildModel(const torch::Tensor& weights)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@@ -16,7 +16,7 @@ namespace bayesnet {
|
|||||||
public:
|
public:
|
||||||
explicit KDB(int k, float theta = 0.03);
|
explicit KDB(int k, float theta = 0.03);
|
||||||
virtual ~KDB() {};
|
virtual ~KDB() {};
|
||||||
void setHyperparameters(nlohmann::json& hyperparameters) override {};
|
void setHyperparameters(nlohmann::json& hyperparameters) override;
|
||||||
vector<string> graph(const string& name = "KDB") const override;
|
vector<string> graph(const string& name = "KDB") const override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -3,9 +3,9 @@
|
|||||||
namespace bayesnet {
|
namespace bayesnet {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
KDBLd::KDBLd(int k) : KDB(k), Proposal(dataset, features, className) {}
|
KDBLd::KDBLd(int k) : KDB(k), Proposal(dataset, features, className) {}
|
||||||
KDBLd& KDBLd::fit(torch::Tensor& X_, torch::Tensor& y_, vector<string>& features_, string className_, map<string, vector<int>>& states_)
|
KDBLd& KDBLd::fit(torch::Tensor& X_, torch::Tensor& y_, const vector<string>& features_, const string& className_, map<string, vector<int>>& states_)
|
||||||
{
|
{
|
||||||
// This first part should go in a Classifier method called fit_local_discretization o fit_float...
|
checkInput(X_, y_);
|
||||||
features = features_;
|
features = features_;
|
||||||
className = className_;
|
className = className_;
|
||||||
Xf = X_;
|
Xf = X_;
|
||||||
|
@@ -10,10 +10,9 @@ namespace bayesnet {
|
|||||||
public:
|
public:
|
||||||
explicit KDBLd(int k);
|
explicit KDBLd(int k);
|
||||||
virtual ~KDBLd() = default;
|
virtual ~KDBLd() = default;
|
||||||
KDBLd& fit(torch::Tensor& X, torch::Tensor& y, vector<string>& features, string className, map<string, vector<int>>& states) override;
|
KDBLd& fit(torch::Tensor& X, torch::Tensor& y, const vector<string>& features, const string& className, map<string, vector<int>>& states) override;
|
||||||
vector<string> graph(const string& name = "KDB") const override;
|
vector<string> graph(const string& name = "KDB") const override;
|
||||||
Tensor predict(Tensor& X) override;
|
Tensor predict(Tensor& X) override;
|
||||||
void setHyperparameters(nlohmann::json& hyperparameters) override {};
|
|
||||||
static inline string version() { return "0.0.1"; };
|
static inline string version() { return "0.0.1"; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
#include "Network.h"
|
#include "Network.h"
|
||||||
#include "bayesnetUtils.h"
|
#include "bayesnetUtils.h"
|
||||||
namespace bayesnet {
|
namespace bayesnet {
|
||||||
Network::Network() : features(vector<string>()), className(""), classNumStates(0), fitted(false) {}
|
Network::Network() : features(vector<string>()), className(""), classNumStates(0), fitted(false), laplaceSmoothing(0) {}
|
||||||
Network::Network(float maxT) : features(vector<string>()), className(""), classNumStates(0), maxThreads(maxT), fitted(false) {}
|
Network::Network(float maxT) : features(vector<string>()), className(""), classNumStates(0), maxThreads(maxT), fitted(false), laplaceSmoothing(0) {}
|
||||||
Network::Network(Network& other) : laplaceSmoothing(other.laplaceSmoothing), features(other.features), className(other.className), classNumStates(other.getClassNumStates()), maxThreads(other.
|
Network::Network(Network& other) : laplaceSmoothing(other.laplaceSmoothing), features(other.features), className(other.className), classNumStates(other.getClassNumStates()), maxThreads(other.
|
||||||
getmaxThreads()), fitted(other.fitted)
|
getmaxThreads()), fitted(other.fitted)
|
||||||
{
|
{
|
||||||
@@ -174,43 +174,11 @@ namespace bayesnet {
|
|||||||
{
|
{
|
||||||
setStates(states);
|
setStates(states);
|
||||||
laplaceSmoothing = 1.0 / samples.size(1); // To use in CPT computation
|
laplaceSmoothing = 1.0 / samples.size(1); // To use in CPT computation
|
||||||
int maxThreadsRunning = static_cast<int>(std::thread::hardware_concurrency() * maxThreads);
|
for (auto& node : nodes) {
|
||||||
if (maxThreadsRunning < 1) {
|
node.second->computeCPT(samples, features, laplaceSmoothing, weights);
|
||||||
maxThreadsRunning = 1;
|
|
||||||
}
|
|
||||||
vector<thread> threads;
|
|
||||||
mutex mtx;
|
|
||||||
condition_variable cv;
|
|
||||||
int activeThreads = 0;
|
|
||||||
int nextNodeIndex = 0;
|
|
||||||
while (nextNodeIndex < nodes.size()) {
|
|
||||||
unique_lock<mutex> lock(mtx);
|
|
||||||
cv.wait(lock, [&activeThreads, &maxThreadsRunning]() { return activeThreads < maxThreadsRunning; });
|
|
||||||
threads.emplace_back([this, &nextNodeIndex, &mtx, &cv, &activeThreads, &weights]() {
|
|
||||||
while (true) {
|
|
||||||
unique_lock<mutex> lock(mtx);
|
|
||||||
if (nextNodeIndex >= nodes.size()) {
|
|
||||||
break; // No more work remaining
|
|
||||||
}
|
|
||||||
auto& pair = *std::next(nodes.begin(), nextNodeIndex);
|
|
||||||
++nextNodeIndex;
|
|
||||||
lock.unlock();
|
|
||||||
pair.second->computeCPT(samples, features, laplaceSmoothing, weights);
|
|
||||||
lock.lock();
|
|
||||||
nodes[pair.first] = std::move(pair.second);
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
lock_guard<mutex> lock(mtx);
|
|
||||||
--activeThreads;
|
|
||||||
cv.notify_one();
|
|
||||||
});
|
|
||||||
++activeThreads;
|
|
||||||
}
|
|
||||||
for (auto& thread : threads) {
|
|
||||||
thread.join();
|
|
||||||
}
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
if (!fitted) {
|
if (!fitted) {
|
||||||
@@ -399,7 +367,6 @@ namespace bayesnet {
|
|||||||
auto result = features;
|
auto result = features;
|
||||||
result.erase(remove(result.begin(), result.end(), className), result.end());
|
result.erase(remove(result.begin(), result.end(), className), result.end());
|
||||||
bool ending{ false };
|
bool ending{ false };
|
||||||
int idx = 0;
|
|
||||||
while (!ending) {
|
while (!ending) {
|
||||||
ending = true;
|
ending = true;
|
||||||
for (auto feature : features) {
|
for (auto feature : features) {
|
||||||
|
@@ -27,6 +27,7 @@ namespace bayesnet {
|
|||||||
Network();
|
Network();
|
||||||
explicit Network(float);
|
explicit Network(float);
|
||||||
explicit Network(Network&);
|
explicit Network(Network&);
|
||||||
|
~Network() = default;
|
||||||
torch::Tensor& getSamples();
|
torch::Tensor& getSamples();
|
||||||
float getmaxThreads();
|
float getmaxThreads();
|
||||||
void addNode(const string&);
|
void addNode(const string&);
|
||||||
@@ -52,7 +53,7 @@ namespace bayesnet {
|
|||||||
vector<string> graph(const string& title) const; // Returns a vector of strings representing the graph in graphviz format
|
vector<string> graph(const string& title) const; // Returns a vector of strings representing the graph in graphviz format
|
||||||
void initialize();
|
void initialize();
|
||||||
void dump_cpt() const;
|
void dump_cpt() const;
|
||||||
inline string version() { return "0.1.0"; }
|
inline string version() { return "0.2.0"; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@@ -100,7 +100,7 @@ namespace bayesnet {
|
|||||||
}
|
}
|
||||||
int name_index = pos - features.begin();
|
int name_index = pos - features.begin();
|
||||||
for (int n_sample = 0; n_sample < dataset.size(1); ++n_sample) {
|
for (int n_sample = 0; n_sample < dataset.size(1); ++n_sample) {
|
||||||
torch::List<c10::optional<torch::Tensor>> coordinates;
|
c10::List<c10::optional<at::Tensor>> coordinates;
|
||||||
coordinates.push_back(dataset.index({ name_index, n_sample }));
|
coordinates.push_back(dataset.index({ name_index, n_sample }));
|
||||||
for (auto parent : parents) {
|
for (auto parent : parents) {
|
||||||
pos = find(features.begin(), features.end(), parent->getName());
|
pos = find(features.begin(), features.end(), parent->getName());
|
||||||
@@ -118,10 +118,10 @@ namespace bayesnet {
|
|||||||
}
|
}
|
||||||
float Node::getFactorValue(map<string, int>& evidence)
|
float Node::getFactorValue(map<string, int>& evidence)
|
||||||
{
|
{
|
||||||
torch::List<c10::optional<torch::Tensor>> coordinates;
|
c10::List<c10::optional<at::Tensor>> coordinates;
|
||||||
// following predetermined order of indices in the cpTable (see Node.h)
|
// following predetermined order of indices in the cpTable (see Node.h)
|
||||||
coordinates.push_back(torch::tensor(evidence[name]));
|
coordinates.push_back(at::tensor(evidence[name]));
|
||||||
transform(parents.begin(), parents.end(), back_inserter(coordinates), [&evidence](const auto& parent) { return torch::tensor(evidence[parent->getName()]); });
|
transform(parents.begin(), parents.end(), back_inserter(coordinates), [&evidence](const auto& parent) { return at::tensor(evidence[parent->getName()]); });
|
||||||
return cpTable.index({ coordinates }).item<float>();
|
return cpTable.index({ coordinates }).item<float>();
|
||||||
}
|
}
|
||||||
vector<string> Node::graph(const string& className)
|
vector<string> Node::graph(const string& className)
|
||||||
|
@@ -9,6 +9,15 @@ namespace bayesnet {
|
|||||||
delete value;
|
delete value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void Proposal::checkInput(const torch::Tensor& X, const torch::Tensor& y)
|
||||||
|
{
|
||||||
|
if (!torch::is_floating_point(X)) {
|
||||||
|
throw std::invalid_argument("X must be a floating point tensor");
|
||||||
|
}
|
||||||
|
if (torch::is_floating_point(y)) {
|
||||||
|
throw std::invalid_argument("y must be an integer tensor");
|
||||||
|
}
|
||||||
|
}
|
||||||
map<string, vector<int>> Proposal::localDiscretizationProposal(const map<string, vector<int>>& oldStates, Network& model)
|
map<string, vector<int>> Proposal::localDiscretizationProposal(const map<string, vector<int>>& oldStates, Network& model)
|
||||||
{
|
{
|
||||||
// order of local discretization is important. no good 0, 1, 2...
|
// order of local discretization is important. no good 0, 1, 2...
|
||||||
@@ -44,15 +53,6 @@ namespace bayesnet {
|
|||||||
auto xvf_ptr = Xf.index({ index }).data_ptr<float>();
|
auto xvf_ptr = Xf.index({ index }).data_ptr<float>();
|
||||||
auto xvf = vector<mdlp::precision_t>(xvf_ptr, xvf_ptr + Xf.size(1));
|
auto xvf = vector<mdlp::precision_t>(xvf_ptr, xvf_ptr + Xf.size(1));
|
||||||
discretizers[feature]->fit(xvf, yxv);
|
discretizers[feature]->fit(xvf, yxv);
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// auto tmp = discretizers[feature]->transform(xvf);
|
|
||||||
// Xv[index] = tmp;
|
|
||||||
// auto xStates = vector<int>(discretizers[pFeatures[index]]->getCutPoints().size() + 1);
|
|
||||||
// iota(xStates.begin(), xStates.end(), 0);
|
|
||||||
// //Update new states of the feature/node
|
|
||||||
// states[feature] = xStates;
|
|
||||||
}
|
}
|
||||||
if (upgrade) {
|
if (upgrade) {
|
||||||
// Discretize again X (only the affected indices) with the new fitted discretizers
|
// Discretize again X (only the affected indices) with the new fitted discretizers
|
||||||
|
@@ -13,6 +13,7 @@ namespace bayesnet {
|
|||||||
Proposal(torch::Tensor& pDataset, vector<string>& features_, string& className_);
|
Proposal(torch::Tensor& pDataset, vector<string>& features_, string& className_);
|
||||||
virtual ~Proposal();
|
virtual ~Proposal();
|
||||||
protected:
|
protected:
|
||||||
|
void checkInput(const torch::Tensor& X, const torch::Tensor& y);
|
||||||
torch::Tensor prepareX(torch::Tensor& X);
|
torch::Tensor prepareX(torch::Tensor& X);
|
||||||
map<string, vector<int>> localDiscretizationProposal(const map<string, vector<int>>& states, Network& model);
|
map<string, vector<int>> localDiscretizationProposal(const map<string, vector<int>>& states, Network& model);
|
||||||
map<string, vector<int>> fit_local_discretization(const torch::Tensor& y);
|
map<string, vector<int>> fit_local_discretization(const torch::Tensor& y);
|
||||||
|
@@ -12,7 +12,6 @@ namespace bayesnet {
|
|||||||
explicit SPODE(int root);
|
explicit SPODE(int root);
|
||||||
virtual ~SPODE() {};
|
virtual ~SPODE() {};
|
||||||
vector<string> graph(const string& name = "SPODE") const override;
|
vector<string> graph(const string& name = "SPODE") const override;
|
||||||
void setHyperparameters(nlohmann::json& hyperparameters) override {};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@@ -3,9 +3,9 @@
|
|||||||
namespace bayesnet {
|
namespace bayesnet {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
SPODELd::SPODELd(int root) : SPODE(root), Proposal(dataset, features, className) {}
|
SPODELd::SPODELd(int root) : SPODE(root), Proposal(dataset, features, className) {}
|
||||||
SPODELd& SPODELd::fit(torch::Tensor& X_, torch::Tensor& y_, vector<string>& features_, string className_, map<string, vector<int>>& states_)
|
SPODELd& SPODELd::fit(torch::Tensor& X_, torch::Tensor& y_, const vector<string>& features_, const string& className_, map<string, vector<int>>& states_)
|
||||||
{
|
{
|
||||||
// This first part should go in a Classifier method called fit_local_discretization o fit_float...
|
checkInput(X_, y_);
|
||||||
features = features_;
|
features = features_;
|
||||||
className = className_;
|
className = className_;
|
||||||
Xf = X_;
|
Xf = X_;
|
||||||
@@ -18,11 +18,13 @@ namespace bayesnet {
|
|||||||
states = localDiscretizationProposal(states, model);
|
states = localDiscretizationProposal(states, model);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
SPODELd& SPODELd::fit(torch::Tensor& dataset, vector<string>& features_, string className_, map<string, vector<int>>& states_)
|
SPODELd& SPODELd::fit(torch::Tensor& dataset, const vector<string>& features_, const string& className_, map<string, vector<int>>& states_)
|
||||||
{
|
{
|
||||||
|
if (!torch::is_floating_point(dataset)) {
|
||||||
|
throw std::runtime_error("Dataset must be a floating point tensor");
|
||||||
|
}
|
||||||
Xf = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), "..." }).clone();
|
Xf = dataset.index({ torch::indexing::Slice(0, dataset.size(0) - 1), "..." }).clone();
|
||||||
y = dataset.index({ -1, "..." }).clone();
|
y = dataset.index({ -1, "..." }).clone();
|
||||||
// This first part should go in a Classifier method called fit_local_discretization o fit_float...
|
|
||||||
features = features_;
|
features = features_;
|
||||||
className = className_;
|
className = className_;
|
||||||
// Fills vectors Xv & yv with the data from tensors X_ (discretized) & y
|
// Fills vectors Xv & yv with the data from tensors X_ (discretized) & y
|
||||||
|
@@ -9,11 +9,10 @@ namespace bayesnet {
|
|||||||
public:
|
public:
|
||||||
explicit SPODELd(int root);
|
explicit SPODELd(int root);
|
||||||
virtual ~SPODELd() = default;
|
virtual ~SPODELd() = default;
|
||||||
SPODELd& fit(torch::Tensor& X, torch::Tensor& y, vector<string>& features, string className, map<string, vector<int>>& states) override;
|
SPODELd& fit(torch::Tensor& X, torch::Tensor& y, const vector<string>& features, const string& className, map<string, vector<int>>& states) override;
|
||||||
SPODELd& fit(torch::Tensor& dataset, vector<string>& features, string className, map<string, vector<int>>& states) override;
|
SPODELd& fit(torch::Tensor& dataset, const vector<string>& features, const string& className, map<string, vector<int>>& states) override;
|
||||||
vector<string> graph(const string& name = "SPODE") const override;
|
vector<string> graph(const string& name = "SPODE") const override;
|
||||||
Tensor predict(Tensor& X) override;
|
Tensor predict(Tensor& X) override;
|
||||||
void setHyperparameters(nlohmann::json& hyperparameters) override {};
|
|
||||||
static inline string version() { return "0.0.1"; };
|
static inline string version() { return "0.0.1"; };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,6 @@ namespace bayesnet {
|
|||||||
TAN();
|
TAN();
|
||||||
virtual ~TAN() {};
|
virtual ~TAN() {};
|
||||||
vector<string> graph(const string& name = "TAN") const override;
|
vector<string> graph(const string& name = "TAN") const override;
|
||||||
void setHyperparameters(nlohmann::json& hyperparameters) override {};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@@ -3,9 +3,9 @@
|
|||||||
namespace bayesnet {
|
namespace bayesnet {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
TANLd::TANLd() : TAN(), Proposal(dataset, features, className) {}
|
TANLd::TANLd() : TAN(), Proposal(dataset, features, className) {}
|
||||||
TANLd& TANLd::fit(torch::Tensor& X_, torch::Tensor& y_, vector<string>& features_, string className_, map<string, vector<int>>& states_)
|
TANLd& TANLd::fit(torch::Tensor& X_, torch::Tensor& y_, const vector<string>& features_, const string& className_, map<string, vector<int>>& states_)
|
||||||
{
|
{
|
||||||
// This first part should go in a Classifier method called fit_local_discretization o fit_float...
|
checkInput(X_, y_);
|
||||||
features = features_;
|
features = features_;
|
||||||
className = className_;
|
className = className_;
|
||||||
Xf = X_;
|
Xf = X_;
|
||||||
|
@@ -10,11 +10,10 @@ namespace bayesnet {
|
|||||||
public:
|
public:
|
||||||
TANLd();
|
TANLd();
|
||||||
virtual ~TANLd() = default;
|
virtual ~TANLd() = default;
|
||||||
TANLd& fit(torch::Tensor& X, torch::Tensor& y, vector<string>& features, string className, map<string, vector<int>>& states) override;
|
TANLd& fit(torch::Tensor& X, torch::Tensor& y, const vector<string>& features, const string& className, map<string, vector<int>>& states) override;
|
||||||
vector<string> graph(const string& name = "TAN") const override;
|
vector<string> graph(const string& name = "TAN") const override;
|
||||||
Tensor predict(Tensor& X) override;
|
Tensor predict(Tensor& X) override;
|
||||||
static inline string version() { return "0.0.1"; };
|
static inline string version() { return "0.0.1"; };
|
||||||
void setHyperparameters(nlohmann::json& hyperparameters) override {};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // !TANLD_H
|
#endif // !TANLD_H
|
@@ -1,6 +1,7 @@
|
|||||||
#include "Datasets.h"
|
#include "Datasets.h"
|
||||||
#include "platformUtils.h"
|
#include "platformUtils.h"
|
||||||
#include "ArffFiles.h"
|
#include "ArffFiles.h"
|
||||||
|
#include <fstream>
|
||||||
namespace platform {
|
namespace platform {
|
||||||
void Datasets::load()
|
void Datasets::load()
|
||||||
{
|
{
|
||||||
@@ -212,10 +213,11 @@ namespace platform {
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < features.size(); ++i) {
|
for (int i = 0; i < features.size(); ++i) {
|
||||||
states[features[i]] = vector<int>(*max_element(Xd[i].begin(), Xd[i].end()) + 1);
|
states[features[i]] = vector<int>(*max_element(Xd[i].begin(), Xd[i].end()) + 1);
|
||||||
iota(begin(states[features[i]]), end(states[features[i]]), 0);
|
auto item = states.at(features[i]);
|
||||||
|
iota(begin(item), end(item), 0);
|
||||||
}
|
}
|
||||||
states[className] = vector<int>(*max_element(yv.begin(), yv.end()) + 1);
|
states[className] = vector<int>(*max_element(yv.begin(), yv.end()) + 1);
|
||||||
iota(begin(states[className]), end(states[className]), 0);
|
iota(begin(states.at(className)), end(states.at(className)), 0);
|
||||||
}
|
}
|
||||||
void Dataset::load_arff()
|
void Dataset::load_arff()
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
#include "Datasets.h"
|
#include "Datasets.h"
|
||||||
#include "Models.h"
|
#include "Models.h"
|
||||||
#include "ReportConsole.h"
|
#include "ReportConsole.h"
|
||||||
|
#include <fstream>
|
||||||
namespace platform {
|
namespace platform {
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
string get_date()
|
string get_date()
|
||||||
@@ -179,8 +179,10 @@ namespace platform {
|
|||||||
result.addTimeTrain(train_time[item].item<double>());
|
result.addTimeTrain(train_time[item].item<double>());
|
||||||
result.addTimeTest(test_time[item].item<double>());
|
result.addTimeTest(test_time[item].item<double>());
|
||||||
item++;
|
item++;
|
||||||
|
clf.reset();
|
||||||
}
|
}
|
||||||
cout << "end. " << flush;
|
cout << "end. " << flush;
|
||||||
|
delete fold;
|
||||||
}
|
}
|
||||||
result.setScoreTest(torch::mean(accuracy_test).item<double>()).setScoreTrain(torch::mean(accuracy_train).item<double>());
|
result.setScoreTest(torch::mean(accuracy_test).item<double>()).setScoreTrain(torch::mean(accuracy_train).item<double>());
|
||||||
result.setScoreTestStd(torch::std(accuracy_test).item<double>()).setScoreTrainStd(torch::std(accuracy_train).item<double>());
|
result.setScoreTestStd(torch::std(accuracy_test).item<double>()).setScoreTrainStd(torch::std(accuracy_train).item<double>());
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "Folding.h"
|
#include "Folding.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
namespace platform {
|
||||||
Fold::Fold(int k, int n, int seed) : k(k), n(n), seed(seed)
|
Fold::Fold(int k, int n, int seed) : k(k), n(n), seed(seed)
|
||||||
{
|
{
|
||||||
random_device rd;
|
random_device rd;
|
||||||
@@ -93,3 +94,4 @@ pair<vector<int>, vector<int>> StratifiedKFold::getFold(int nFold)
|
|||||||
}
|
}
|
||||||
return { train_indices, test_indices };
|
return { train_indices, test_indices };
|
||||||
}
|
}
|
||||||
|
}
|
@@ -4,7 +4,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <random>
|
#include <random>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
namespace platform {
|
||||||
class Fold {
|
class Fold {
|
||||||
protected:
|
protected:
|
||||||
int k;
|
int k;
|
||||||
@@ -34,4 +34,5 @@ public:
|
|||||||
StratifiedKFold(int k, torch::Tensor& y, int seed = -1);
|
StratifiedKFold(int k, torch::Tensor& y, int seed = -1);
|
||||||
pair<vector<int>, vector<int>> getFold(int nFold) override;
|
pair<vector<int>, vector<int>> getFold(int nFold) override;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
@@ -26,7 +26,7 @@ namespace platform {
|
|||||||
instance = it->second();
|
instance = it->second();
|
||||||
// wrap instance in a shared ptr and return
|
// wrap instance in a shared ptr and return
|
||||||
if (instance != nullptr)
|
if (instance != nullptr)
|
||||||
return shared_ptr<bayesnet::BaseClassifier>(instance);
|
return unique_ptr<bayesnet::BaseClassifier>(instance);
|
||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@@ -47,11 +47,11 @@ namespace platform {
|
|||||||
|
|
||||||
void ReportExcel::body()
|
void ReportExcel::body()
|
||||||
{
|
{
|
||||||
auto header = vector<string>(
|
auto head = vector<string>(
|
||||||
{ "Dataset", "Samples", "Features", "Classes", "Nodes", "Edges", "States", "Score", "Score Std.", "Time",
|
{ "Dataset", "Samples", "Features", "Classes", "Nodes", "Edges", "States", "Score", "Score Std.", "Time",
|
||||||
"Time Std.", "Hyperparameters" });
|
"Time Std.", "Hyperparameters" });
|
||||||
int col = 1;
|
int col = 1;
|
||||||
for (const auto& item : header) {
|
for (const auto& item : head) {
|
||||||
wks.cell(8, col++).value() = item;
|
wks.cell(8, col++).value() = item;
|
||||||
}
|
}
|
||||||
int row = 9;
|
int row = 9;
|
||||||
|
@@ -100,11 +100,11 @@ namespace platform {
|
|||||||
cout << Colors::YELLOW() << "Reporting " << files.at(index).getFilename() << endl;
|
cout << Colors::YELLOW() << "Reporting " << files.at(index).getFilename() << endl;
|
||||||
auto data = files.at(index).load();
|
auto data = files.at(index).load();
|
||||||
if (excelReport) {
|
if (excelReport) {
|
||||||
ReportExcel report(data);
|
ReportExcel reporter(data);
|
||||||
report.show();
|
reporter.show();
|
||||||
} else {
|
} else {
|
||||||
ReportConsole report(data);
|
ReportConsole reporter(data);
|
||||||
report.show();
|
reporter.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Results::menu()
|
void Results::menu()
|
||||||
|
@@ -69,11 +69,12 @@ tuple<Tensor, Tensor, vector<string>, string, map<string, vector<int>>> loadData
|
|||||||
Xd = torch::zeros({ static_cast<int>(Xr[0].size()), static_cast<int>(Xr.size()) }, torch::kInt32);
|
Xd = torch::zeros({ static_cast<int>(Xr[0].size()), static_cast<int>(Xr.size()) }, torch::kInt32);
|
||||||
for (int i = 0; i < features.size(); ++i) {
|
for (int i = 0; i < features.size(); ++i) {
|
||||||
states[features[i]] = vector<int>(*max_element(Xr[i].begin(), Xr[i].end()) + 1);
|
states[features[i]] = vector<int>(*max_element(Xr[i].begin(), Xr[i].end()) + 1);
|
||||||
iota(begin(states[features[i]]), end(states[features[i]]), 0);
|
auto item = states.at(features[i]);
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
states[className] = vector<int>(*max_element(y.begin(), y.end()) + 1);
|
states[className] = vector<int>(*max_element(y.begin(), y.end()) + 1);
|
||||||
iota(begin(states[className]), end(states[className]), 0);
|
iota(begin(states.at(className)), end(states.at(className)), 0);
|
||||||
} else {
|
} else {
|
||||||
Xd = torch::zeros({ static_cast<int>(X[0].size()), static_cast<int>(X.size()) }, torch::kFloat32);
|
Xd = torch::zeros({ static_cast<int>(X[0].size()), static_cast<int>(X.size()) }, torch::kFloat32);
|
||||||
for (int i = 0; i < features.size(); ++i) {
|
for (int i = 0; i < features.size(); ++i) {
|
||||||
|
Reference in New Issue
Block a user