Compare commits

..

26 Commits

Author SHA1 Message Date
f94e2d6a27 Add quiet parameter 2023-11-24 21:16:20 +01:00
2121ba9b98 Refactor input grid parameters to json file 2023-11-24 09:57:29 +01:00
8b7b59d42b Complete first step 2023-11-23 12:59:21 +01:00
bbe5302ab1 Add info to output 2023-11-22 16:38:50 +01:00
c2eb727fc7 Complete output interface of gridsearch 2023-11-22 16:30:04 +01:00
fb347ed5b9 Begin gridsearch implementation 2023-11-22 12:22:30 +01:00
b657762c0c Generate combinations sample 2023-11-22 00:18:24 +01:00
495d8a8528 Begin implementing grid combinations 2023-11-21 13:11:14 +01:00
4628e48d3c Build gridsearch structure 2023-11-20 23:32:34 +01:00
5876be4b24 Add more install instructions of Boost to README 2023-11-20 20:39:22 +01:00
dc3400197f Add coment todo impelemt number of nodes 2023-11-20 01:14:13 +01:00
26d3a57782 Add info to invalid hyperparameter exception 2023-11-19 23:02:28 +01:00
4f3a04058f Refactor Hyperparameters management 2023-11-19 22:36:27 +01:00
89c4613591 Implement hyperparameters with json file 2023-11-18 11:56:10 +01:00
28f3d87e32 Add Python Classifiers
Add STree, Odte, SVC & RandomForest Classifiers
Remove using namespace ... in project
2023-11-17 11:11:05 +01:00
e8d2c9fc0b Set intolerant convergence 2023-11-17 10:26:25 +01:00
d3cb580387 Remove n_jobs from STree 2023-11-17 10:10:31 +01:00
f088df14fd Restore the Creation model position in experiment 2023-11-17 01:10:46 +01:00
e2249eace7 Disable Warning messages in python clfs
Disable removing Python env
2023-11-16 22:38:46 +01:00
64f5a7f14a Fix header in example 2023-11-16 17:03:40 +01:00
408db2aad5 Mark override fit funtcion 2023-11-14 18:59:41 +01:00
e03efb5f63 set tolerance=0 if feature selection in BoostAODE 2023-11-14 10:12:02 +01:00
f617886133 Add new models to example 2023-11-14 09:12:25 +01:00
69ad660040 Refactor version method in PyClassifier 2023-11-13 13:59:06 +01:00
431b3a3aa5 Fit PyWrap into BayesNet 2023-11-13 11:13:32 +01:00
6a23e2cc26 Add CMakelist integration 2023-11-12 22:14:29 +01:00
49 changed files with 1659 additions and 203 deletions

3
.gitignore vendored
View File

@@ -32,8 +32,7 @@
*.out *.out
*.app *.app
build/** build/**
build_debug/** build_*/**
build_release/**
*.dSYM/** *.dSYM/**
cmake-build*/** cmake-build*/**
.idea .idea

49
.vscode/launch.json vendored
View File

@@ -5,7 +5,7 @@
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",
"name": "sample", "name": "sample",
"program": "${workspaceFolder}/build/sample/BayesNetSample", "program": "${workspaceFolder}/build_debug/sample/BayesNetSample",
"args": [ "args": [
"-d", "-d",
"iris", "iris",
@@ -14,32 +14,49 @@
"-s", "-s",
"271", "271",
"-p", "-p",
"/Users/rmontanana/Code/discretizbench/datasets/", "/home/rmontanana/Code/discretizbench/datasets/",
], ],
//"cwd": "${workspaceFolder}/build/sample/", //"cwd": "${workspaceFolder}/build/sample/",
}, },
{ {
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",
"name": "experiment", "name": "experimentPy",
"program": "${workspaceFolder}/build/src/Platform/b_main", "program": "${workspaceFolder}/build_debug/src/Platform/b_main",
"args": [
"-m",
"STree",
"--stratified",
"-d",
"iris",
//"--discretize"
// "--hyperparameters",
// "{\"repeatSparent\": true, \"maxModels\": 12}"
],
"cwd": "/home/rmontanana/Code/discretizbench",
},
{
"type": "lldb",
"request": "launch",
"name": "experimentBayes",
"program": "${workspaceFolder}/build_debug/src/Platform/b_main",
"args": [ "args": [
"-m", "-m",
"TAN", "TAN",
"--stratified", "--stratified",
"--discretize",
"-d", "-d",
"zoo", "iris",
"--discretize" "--hyperparameters",
// "--hyperparameters", "{\"repeatSparent\": true, \"maxModels\": 12}"
// "{\"repeatSparent\": true, \"maxModels\": 12}"
], ],
"cwd": "/Users/rmontanana/Code/odtebench", "cwd": "/home/rmontanana/Code/discretizbench",
}, },
{ {
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",
"name": "best", "name": "best",
"program": "${workspaceFolder}/build/src/Platform/b_best", "program": "${workspaceFolder}/build_debug/src/Platform/b_best",
"args": [ "args": [
"-m", "-m",
"BoostAODE", "BoostAODE",
@@ -47,24 +64,24 @@
"accuracy", "accuracy",
"--build", "--build",
], ],
"cwd": "/Users/rmontanana/Code/discretizbench", "cwd": "/home/rmontanana/Code/discretizbench",
}, },
{ {
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",
"name": "manage", "name": "manage",
"program": "${workspaceFolder}/build/src/Platform/b_manage", "program": "${workspaceFolder}/build_debug/src/Platform/b_manage",
"args": [ "args": [
"-n", "-n",
"20" "20"
], ],
"cwd": "/Users/rmontanana/Code/discretizbench", "cwd": "/home/rmontanana/Code/discretizbench",
}, },
{ {
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",
"name": "list", "name": "list",
"program": "${workspaceFolder}/build/src/Platform/b_list", "program": "${workspaceFolder}/build_debug/src/Platform/b_list",
"args": [], "args": [],
//"cwd": "/Users/rmontanana/Code/discretizbench", //"cwd": "/Users/rmontanana/Code/discretizbench",
"cwd": "/home/rmontanana/Code/covbench", "cwd": "/home/rmontanana/Code/covbench",
@@ -73,7 +90,7 @@
"type": "lldb", "type": "lldb",
"request": "launch", "request": "launch",
"name": "test", "name": "test",
"program": "${workspaceFolder}/build/tests/unit_tests", "program": "${workspaceFolder}/build_debug/tests/unit_tests",
"args": [ "args": [
"-c=\"Metrics Test\"", "-c=\"Metrics Test\"",
// "-s", // "-s",
@@ -84,7 +101,7 @@
"name": "Build & debug active file", "name": "Build & debug active file",
"type": "cppdbg", "type": "cppdbg",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/build/bayesnet", "program": "${workspaceFolder}/build_debug/bayesnet",
"args": [], "args": [],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",

View File

@@ -36,12 +36,16 @@ option(CODE_COVERAGE "Collect coverage from test library" OFF)
set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON) set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF) set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.66.0 REQUIRED) find_package(Boost 1.66.0 REQUIRED COMPONENTS python3 numpy3)
if(Boost_FOUND) if(Boost_FOUND)
message("Boost_INCLUDE_DIRS=${Boost_INCLUDE_DIRS}") message("Boost_INCLUDE_DIRS=${Boost_INCLUDE_DIRS}")
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
endif() endif()
# Python
find_package(Python3 3.11...3.11.9 COMPONENTS Interpreter Development REQUIRED)
message("Python3_LIBRARIES=${Python3_LIBRARIES}")
# 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})
@@ -77,6 +81,7 @@ add_subdirectory(config)
add_subdirectory(lib/Files) add_subdirectory(lib/Files)
add_subdirectory(src/BayesNet) add_subdirectory(src/BayesNet)
add_subdirectory(src/Platform) add_subdirectory(src/Platform)
add_subdirectory(src/PyClassifiers)
add_subdirectory(sample) add_subdirectory(sample)
file(GLOB BayesNet_HEADERS CONFIGURE_DEPENDS ${BayesNet_SOURCE_DIR}/src/BayesNet/*.h ${BayesNet_SOURCE_DIR}/BayesNet/*.h) file(GLOB BayesNet_HEADERS CONFIGURE_DEPENDS ${BayesNet_SOURCE_DIR}/src/BayesNet/*.h ${BayesNet_SOURCE_DIR}/BayesNet/*.h)

View File

@@ -4,7 +4,7 @@ SHELL := /bin/bash
f_release = build_release f_release = build_release
f_debug = build_debug f_debug = build_debug
app_targets = b_best b_list b_main b_manage app_targets = b_best b_list b_main b_manage b_grid
test_targets = unit_tests_bayesnet unit_tests_platform test_targets = unit_tests_bayesnet unit_tests_platform
n_procs = -j 16 n_procs = -j 16
@@ -35,11 +35,13 @@ dest ?= ${HOME}/bin
install: ## Copy binary files to bin folder install: ## Copy binary files to bin folder
@echo "Destination folder: $(dest)" @echo "Destination folder: $(dest)"
make buildr make buildr
@echo "*******************************************"
@echo ">>> Copying files to $(dest)" @echo ">>> Copying files to $(dest)"
@cp $(f_release)/src/Platform/b_main $(dest) @echo "*******************************************"
@cp $(f_release)/src/Platform/b_list $(dest) @for item in $(app_targets); do \
@cp $(f_release)/src/Platform/b_manage $(dest) echo ">>> Copying $$item" ; \
@cp $(f_release)/src/Platform/b_best $(dest) cp $(f_release)/src/Platform/$$item $(dest) ; \
done
dependency: ## Create a dependency graph diagram of the project (build/dependency.png) dependency: ## Create a dependency graph diagram of the project (build/dependency.png)
@echo ">>> Creating dependency graph diagram of the project..."; @echo ">>> Creating dependency graph diagram of the project...";

View File

@@ -18,12 +18,24 @@ The best option is install the packages that the Linux distribution have in its
sudo dnf install boost-devel sudo dnf install boost-devel
``` ```
If this is not possible and the compressed packaged is installed, the following environment variable has to be set: If this is not possible and the compressed packaged is installed, the following environment variable has to be set pointing to the folder where it was unzipped to:
```bash ```bash
export BOOST_ROOT=/path/to/library/ export BOOST_ROOT=/path/to/library/
``` ```
In some cases, it is needed to build the library, to do so:
```bash
cd /path/to/library
mkdir own
./bootstrap.sh --prefix=/path/to/library/own
./b2 install
export BOOST_ROOT=/path/to/library/own/
```
Don't forget to add the export BOOST_ROOT statement to .bashrc or wherever it is meant to be.
### libxlswriter ### libxlswriter
```bash ```bash

162
grid_stree.json Normal file
View File

@@ -0,0 +1,162 @@
{
"balance-scale": {
"C": 10000.0,
"gamma": 0.1,
"kernel": "rbf",
"max_iter": 10000
},
"balloons": {
"C": 7,
"gamma": 0.1,
"kernel": "rbf",
"max_iter": 10000
},
"breast-cancer-wisc-diag": {
"C": 0.2,
"max_iter": 10000
},
"breast-cancer-wisc-prog": {
"C": 0.2,
"max_iter": 10000
},
"breast-cancer-wisc": {},
"breast-cancer": {},
"cardiotocography-10clases": {},
"cardiotocography-3clases": {},
"conn-bench-sonar-mines-rocks": {},
"cylinder-bands": {},
"dermatology": {
"C": 55,
"max_iter": 10000
},
"echocardiogram": {
"C": 7,
"gamma": 0.1,
"kernel": "poly",
"max_features": "auto",
"max_iter": 10000
},
"fertility": {
"C": 0.05,
"max_features": "auto",
"max_iter": 10000
},
"haberman-survival": {},
"heart-hungarian": {
"C": 0.05,
"max_iter": 10000
},
"hepatitis": {
"C": 7,
"gamma": 0.1,
"kernel": "rbf",
"max_iter": 10000
},
"ilpd-indian-liver": {},
"ionosphere": {
"C": 7,
"gamma": 0.1,
"kernel": "rbf",
"max_iter": 10000
},
"iris": {},
"led-display": {},
"libras": {
"C": 0.08,
"max_iter": 10000
},
"low-res-spect": {
"C": 0.05,
"max_iter": 10000
},
"lymphography": {
"C": 0.05,
"max_iter": 10000
},
"mammographic": {},
"molec-biol-promoter": {
"C": 0.05,
"gamma": 0.1,
"kernel": "poly",
"max_iter": 10000
},
"musk-1": {
"C": 0.05,
"gamma": 0.1,
"kernel": "poly",
"max_iter": 10000
},
"oocytes_merluccius_nucleus_4d": {
"C": 8.25,
"gamma": 0.1,
"kernel": "poly"
},
"oocytes_merluccius_states_2f": {},
"oocytes_trisopterus_nucleus_2f": {},
"oocytes_trisopterus_states_5b": {
"C": 0.11,
"max_iter": 10000
},
"parkinsons": {},
"pima": {},
"pittsburg-bridges-MATERIAL": {
"C": 7,
"gamma": 0.1,
"kernel": "rbf",
"max_iter": 10000
},
"pittsburg-bridges-REL-L": {},
"pittsburg-bridges-SPAN": {
"C": 0.05,
"max_iter": 10000
},
"pittsburg-bridges-T-OR-D": {},
"planning": {
"C": 7,
"gamma": 10.0,
"kernel": "rbf",
"max_iter": 10000
},
"post-operative": {
"C": 55,
"degree": 5,
"gamma": 0.1,
"kernel": "poly",
"max_iter": 10000
},
"seeds": {
"C": 10000.0,
"max_iter": 10000
},
"statlog-australian-credit": {
"C": 0.05,
"max_features": "auto",
"max_iter": 10000
},
"statlog-german-credit": {},
"statlog-heart": {},
"statlog-image": {
"C": 7,
"max_iter": 10000
},
"statlog-vehicle": {},
"synthetic-control": {
"C": 0.55,
"max_iter": 10000
},
"tic-tac-toe": {
"C": 0.2,
"gamma": 0.1,
"kernel": "poly",
"max_iter": 10000
},
"vertebral-column-2clases": {},
"wine": {
"C": 0.55,
"max_iter": 10000
},
"zoo": {
"C": 0.1,
"max_iter": 10000
}
}

View File

@@ -1,10 +1,10 @@
#include <iostream> #include <iostream>
#include <torch/torch.h> #include <torch/torch.h>
#include <std::string> #include <string>
#include <map> #include <map>
#include <argparse/argparse.hpp> #include <argparse/argparse.hpp>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "ArffFiles.h"v #include "ArffFiles.h"
#include "BayesMetrics.h" #include "BayesMetrics.h"
#include "CPPFImdlp.h" #include "CPPFImdlp.h"
#include "Folding.h" #include "Folding.h"

View File

@@ -1,5 +1,4 @@
#include "AODELd.h" #include "AODELd.h"
#include "Models.h"
namespace bayesnet { namespace bayesnet {
AODELd::AODELd() : Ensemble(), Proposal(dataset, features, className) {} AODELd::AODELd() : Ensemble(), Proposal(dataset, features, className) {}

View File

@@ -6,8 +6,6 @@
namespace bayesnet { namespace bayesnet {
enum status_t { NORMAL, WARNING, ERROR }; enum status_t { NORMAL, WARNING, ERROR };
class BaseClassifier { class BaseClassifier {
protected:
virtual void trainModel(const torch::Tensor& weights) = 0;
public: public:
// X is nxm std::vector, y is nx1 std::vector // X is nxm std::vector, y is nx1 std::vector
virtual BaseClassifier& 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; virtual BaseClassifier& 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;
@@ -26,10 +24,14 @@ namespace bayesnet {
int virtual getNumberOfStates() const = 0; int virtual getNumberOfStates() const = 0;
std::vector<std::string> virtual show() const = 0; std::vector<std::string> virtual show() const = 0;
std::vector<std::string> virtual graph(const std::string& title = "") const = 0; std::vector<std::string> virtual graph(const std::string& title = "") const = 0;
const std::string inline getVersion() const { return "0.2.0"; }; virtual std::string getVersion() = 0;
std::vector<std::string> virtual topological_order() = 0; std::vector<std::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(const nlohmann::json& hyperparameters) = 0;
std::vector<std::string>& getValidHyperparameters() { return validHyperparameters; }
protected:
virtual void trainModel(const torch::Tensor& weights) = 0;
std::vector<std::string> validHyperparameters;
}; };
} }
#endif #endif

View File

@@ -10,7 +10,11 @@
#include "IWSS.h" #include "IWSS.h"
namespace bayesnet { namespace bayesnet {
BoostAODE::BoostAODE() : Ensemble() {} BoostAODE::BoostAODE() : Ensemble()
{
validHyperparameters = { "repeatSparent", "maxModels", "ascending", "convergence", "threshold", "select_features" };
}
void BoostAODE::buildModel(const torch::Tensor& weights) void BoostAODE::buildModel(const torch::Tensor& weights)
{ {
// Models shall be built in trainModel // Models shall be built in trainModel
@@ -43,11 +47,8 @@ namespace bayesnet {
y_train = y_; y_train = y_;
} }
} }
void BoostAODE::setHyperparameters(nlohmann::json& hyperparameters) void BoostAODE::setHyperparameters(const nlohmann::json& hyperparameters)
{ {
// Check if hyperparameters are valid
const std::vector<std::string> validKeys = { "repeatSparent", "maxModels", "ascending", "convergence", "threshold", "select_features" };
checkHyperparameters(validKeys, hyperparameters);
if (hyperparameters.contains("repeatSparent")) { if (hyperparameters.contains("repeatSparent")) {
repeatSparent = hyperparameters["repeatSparent"]; repeatSparent = hyperparameters["repeatSparent"];
} }
@@ -108,8 +109,10 @@ namespace bayesnet {
void BoostAODE::trainModel(const torch::Tensor& weights) void BoostAODE::trainModel(const torch::Tensor& weights)
{ {
std::unordered_set<int> featuresUsed; std::unordered_set<int> featuresUsed;
int tolerance = 5; // number of times the accuracy can be lower than the threshold
if (selectFeatures) { if (selectFeatures) {
featuresUsed = initializeModels(); featuresUsed = initializeModels();
tolerance = 0; // Remove tolerance if features are selected
} }
if (maxModels == 0) if (maxModels == 0)
maxModels = .1 * n > 10 ? .1 * n : n; maxModels = .1 * n > 10 ? .1 * n : n;
@@ -119,7 +122,6 @@ namespace bayesnet {
double priorAccuracy = 0.0; double priorAccuracy = 0.0;
double delta = 1.0; double delta = 1.0;
double threshold = 1e-4; double threshold = 1e-4;
int tolerance = 5; // number of times the accuracy can be lower than the threshold
int count = 0; // number of times the accuracy is lower than the threshold int count = 0; // number of times the accuracy is lower than the threshold
fitted = true; // to enable predict fitted = true; // to enable predict
// Step 0: Set the finish condition // Step 0: Set the finish condition

View File

@@ -8,9 +8,9 @@ namespace bayesnet {
class BoostAODE : public Ensemble { class BoostAODE : public Ensemble {
public: public:
BoostAODE(); BoostAODE();
virtual ~BoostAODE() {}; virtual ~BoostAODE() = default;
std::vector<std::string> graph(const std::string& title = "BoostAODE") const override; std::vector<std::string> graph(const std::string& title = "BoostAODE") const override;
void setHyperparameters(nlohmann::json& hyperparameters) override; void setHyperparameters(const nlohmann::json& hyperparameters) override;
protected: protected:
void buildModel(const torch::Tensor& weights) override; void buildModel(const torch::Tensor& weights) override;
void trainModel(const torch::Tensor& weights) override; void trainModel(const torch::Tensor& weights) override;

View File

@@ -3,6 +3,9 @@ include_directories(${BayesNet_SOURCE_DIR}/lib/Files)
include_directories(${BayesNet_SOURCE_DIR}/lib/json/include) include_directories(${BayesNet_SOURCE_DIR}/lib/json/include)
include_directories(${BayesNet_SOURCE_DIR}/src/BayesNet) include_directories(${BayesNet_SOURCE_DIR}/src/BayesNet)
include_directories(${BayesNet_SOURCE_DIR}/src/Platform) include_directories(${BayesNet_SOURCE_DIR}/src/Platform)
include_directories(${BayesNet_SOURCE_DIR}/src/PyClassifiers)
include_directories(${Python3_INCLUDE_DIRS})
add_library(BayesNet bayesnetUtils.cc Network.cc Node.cc BayesMetrics.cc Classifier.cc add_library(BayesNet bayesnetUtils.cc Network.cc Node.cc BayesMetrics.cc Classifier.cc
KDB.cc TAN.cc SPODE.cc Ensemble.cc AODE.cc TANLd.cc KDBLd.cc SPODELd.cc AODELd.cc BoostAODE.cc KDB.cc TAN.cc SPODE.cc Ensemble.cc AODE.cc TANLd.cc KDBLd.cc SPODELd.cc AODELd.cc BoostAODE.cc
Mst.cc Proposal.cc CFS.cc FCBF.cc IWSS.cc FeatureSelect.cc ${BayesNet_SOURCE_DIR}/src/Platform/Models.cc) Mst.cc Proposal.cc CFS.cc FCBF.cc IWSS.cc FeatureSelect.cc ${BayesNet_SOURCE_DIR}/src/Platform/Models.cc)

View File

@@ -153,18 +153,8 @@ namespace bayesnet {
{ {
model.dump_cpt(); model.dump_cpt();
} }
void Classifier::checkHyperparameters(const std::vector<std::string>& validKeys, nlohmann::json& hyperparameters) void Classifier::setHyperparameters(const nlohmann::json& hyperparameters)
{ {
for (const auto& item : hyperparameters.items()) { //For classifiers that don't have hyperparameters
if (find(validKeys.begin(), validKeys.end(), item.key()) == validKeys.end()) {
throw std::invalid_argument("Hyperparameter " + item.key() + " is not valid");
}
}
}
void Classifier::setHyperparameters(nlohmann::json& hyperparameters)
{
// Check if hyperparameters are valid, default is no hyperparameters
const std::vector<std::string> validKeys = { };
checkHyperparameters(validKeys, hyperparameters);
} }
} }

View File

@@ -22,7 +22,6 @@ namespace bayesnet {
void checkFitParameters(); void checkFitParameters();
virtual void buildModel(const torch::Tensor& weights) = 0; virtual void buildModel(const torch::Tensor& weights) = 0;
void trainModel(const torch::Tensor& weights) override; void trainModel(const torch::Tensor& weights) override;
void checkHyperparameters(const std::vector<std::string>& validKeys, nlohmann::json& hyperparameters);
void buildDataset(torch::Tensor& y); void buildDataset(torch::Tensor& y);
public: public:
Classifier(Network model); Classifier(Network model);
@@ -37,13 +36,14 @@ namespace bayesnet {
int getNumberOfStates() const override; int getNumberOfStates() const override;
torch::Tensor predict(torch::Tensor& X) override; torch::Tensor predict(torch::Tensor& X) override;
status_t getStatus() const override { return status; } status_t getStatus() const override { return status; }
std::string getVersion() override { return "0.2.0"; };
std::vector<int> predict(std::vector<std::vector<int>>& X) override; std::vector<int> predict(std::vector<std::vector<int>>& X) override;
float score(torch::Tensor& X, torch::Tensor& y) override; float score(torch::Tensor& X, torch::Tensor& y) override;
float score(std::vector<std::vector<int>>& X, std::vector<int>& y) override; float score(std::vector<std::vector<int>>& X, std::vector<int>& y) override;
std::vector<std::string> show() const override; std::vector<std::string> show() const override;
std::vector<std::string> topological_order() override; std::vector<std::string> topological_order() override;
void dump_cpt() const override; void dump_cpt() const override;
void setHyperparameters(nlohmann::json& hyperparameters) override; void setHyperparameters(const nlohmann::json& hyperparameters) override; //For classifiers that don't have hyperparameters
}; };
} }
#endif #endif

View File

@@ -1,12 +1,13 @@
#include "KDB.h" #include "KDB.h"
namespace bayesnet { namespace bayesnet {
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) {
validHyperparameters = { "k", "theta" };
}
void KDB::setHyperparameters(const nlohmann::json& hyperparameters)
{ {
// Check if hyperparameters are valid
const std::vector<std::string> validKeys = { "k", "theta" };
checkHyperparameters(validKeys, hyperparameters);
if (hyperparameters.contains("k")) { if (hyperparameters.contains("k")) {
k = hyperparameters["k"]; k = hyperparameters["k"];
} }

View File

@@ -13,8 +13,8 @@ namespace bayesnet {
void buildModel(const torch::Tensor& weights) override; void buildModel(const torch::Tensor& weights) override;
public: public:
explicit KDB(int k, float theta = 0.03); explicit KDB(int k, float theta = 0.03);
virtual ~KDB() {}; virtual ~KDB() = default;
void setHyperparameters(nlohmann::json& hyperparameters) override; void setHyperparameters(const nlohmann::json& hyperparameters) override;
std::vector<std::string> graph(const std::string& name = "KDB") const override; std::vector<std::string> graph(const std::string& name = "KDB") const override;
}; };
} }

View File

@@ -10,7 +10,7 @@ namespace bayesnet {
void buildModel(const torch::Tensor& weights) override; void buildModel(const torch::Tensor& weights) override;
public: public:
explicit SPODE(int root); explicit SPODE(int root);
virtual ~SPODE() {}; virtual ~SPODE() = default;
std::vector<std::string> graph(const std::string& name = "SPODE") const override; std::vector<std::string> graph(const std::string& name = "SPODE") const override;
}; };
} }

View File

@@ -8,7 +8,7 @@ namespace bayesnet {
void buildModel(const torch::Tensor& weights) override; void buildModel(const torch::Tensor& weights) override;
public: public:
TAN(); TAN();
virtual ~TAN() {}; virtual ~TAN() = default;
std::vector<std::string> graph(const std::string& name = "TAN") const override; std::vector<std::string> graph(const std::string& name = "TAN") const override;
}; };
} }

View File

@@ -1,17 +1,21 @@
include_directories(${BayesNet_SOURCE_DIR}/src/BayesNet) include_directories(${BayesNet_SOURCE_DIR}/src/BayesNet)
include_directories(${BayesNet_SOURCE_DIR}/src/Platform) include_directories(${BayesNet_SOURCE_DIR}/src/Platform)
include_directories(${BayesNet_SOURCE_DIR}/src/PyClassifiers)
include_directories(${BayesNet_SOURCE_DIR}/lib/Files) include_directories(${BayesNet_SOURCE_DIR}/lib/Files)
include_directories(${BayesNet_SOURCE_DIR}/lib/mdlp) include_directories(${BayesNet_SOURCE_DIR}/lib/mdlp)
include_directories(${BayesNet_SOURCE_DIR}/lib/argparse/include) include_directories(${BayesNet_SOURCE_DIR}/lib/argparse/include)
include_directories(${BayesNet_SOURCE_DIR}/lib/json/include) include_directories(${BayesNet_SOURCE_DIR}/lib/json/include)
include_directories(${BayesNet_SOURCE_DIR}/lib/libxlsxwriter/include) include_directories(${BayesNet_SOURCE_DIR}/lib/libxlsxwriter/include)
include_directories(${Python3_INCLUDE_DIRS})
add_executable(b_main b_main.cc Folding.cc Experiment.cc Datasets.cc Dataset.cc Models.cc ReportConsole.cc ReportBase.cc)
add_executable(b_manage b_manage.cc Results.cc ManageResults.cc CommandParser.cc Result.cc ReportConsole.cc ReportExcel.cc ReportBase.cc Datasets.cc Dataset.cc ExcelFile.cc)
add_executable(b_list b_list.cc Datasets.cc Dataset.cc)
add_executable(b_best b_best.cc BestResults.cc Result.cc Statistics.cc BestResultsExcel.cc ReportExcel.cc ReportBase.cc Datasets.cc Dataset.cc ExcelFile.cc) add_executable(b_best b_best.cc BestResults.cc Result.cc Statistics.cc BestResultsExcel.cc ReportExcel.cc ReportBase.cc Datasets.cc Dataset.cc ExcelFile.cc)
add_executable(b_grid b_grid.cc GridSearch.cc GridData.cc HyperParameters.cc Folding.cc Datasets.cc Dataset.cc)
add_executable(b_list b_list.cc Datasets.cc Dataset.cc)
add_executable(b_main b_main.cc Folding.cc Experiment.cc Datasets.cc Dataset.cc Models.cc HyperParameters.cc ReportConsole.cc ReportBase.cc)
add_executable(b_manage b_manage.cc Results.cc ManageResults.cc CommandParser.cc Result.cc ReportConsole.cc ReportExcel.cc ReportBase.cc Datasets.cc Dataset.cc ExcelFile.cc)
target_link_libraries(b_main BayesNet ArffFiles mdlp "${TORCH_LIBRARIES}")
target_link_libraries(b_manage "${TORCH_LIBRARIES}" "${XLSXWRITER_LIB}" ArffFiles mdlp)
target_link_libraries(b_best Boost::boost "${XLSXWRITER_LIB}" "${TORCH_LIBRARIES}" ArffFiles mdlp) target_link_libraries(b_best Boost::boost "${XLSXWRITER_LIB}" "${TORCH_LIBRARIES}" ArffFiles mdlp)
target_link_libraries(b_grid BayesNet PyWrap)
target_link_libraries(b_list ArffFiles mdlp "${TORCH_LIBRARIES}") target_link_libraries(b_list ArffFiles mdlp "${TORCH_LIBRARIES}")
target_link_libraries(b_main BayesNet ArffFiles mdlp "${TORCH_LIBRARIES}" PyWrap)
target_link_libraries(b_manage "${TORCH_LIBRARIES}" "${XLSXWRITER_LIB}" ArffFiles mdlp)

View File

@@ -26,7 +26,6 @@ namespace platform {
oss << std::put_time(timeinfo, "%H:%M:%S"); oss << std::put_time(timeinfo, "%H:%M:%S");
return oss.str(); return oss.str();
} }
Experiment::Experiment() : hyperparameters(json::parse("{}")) {}
std::string Experiment::get_file_name() std::string Experiment::get_file_name()
{ {
std::string result = "results_" + score_name + "_" + model + "_" + platform + "_" + get_date() + "_" + get_time() + "_" + (stratified ? "1" : "0") + ".json"; std::string result = "results_" + score_name + "_" + model + "_" + platform + "_" + get_date() + "_" + get_time() + "_" + (stratified ? "1" : "0") + ".json";
@@ -134,7 +133,7 @@ namespace platform {
} }
void Experiment::cross_validation(const std::string& fileName, bool quiet) void Experiment::cross_validation(const std::string& fileName, bool quiet)
{ {
auto datasets = platform::Datasets(discretized, Paths::datasets()); auto datasets = Datasets(discretized, Paths::datasets());
// Get dataset // Get dataset
auto [X, y] = datasets.getTensors(fileName); auto [X, y] = datasets.getTensors(fileName);
auto states = datasets.getStates(fileName); auto states = datasets.getStates(fileName);
@@ -148,7 +147,7 @@ namespace platform {
auto result = Result(); auto result = Result();
auto [values, counts] = at::_unique(y); auto [values, counts] = at::_unique(y);
result.setSamples(X.size(1)).setFeatures(X.size(0)).setClasses(values.size(0)); result.setSamples(X.size(1)).setFeatures(X.size(0)).setClasses(values.size(0));
result.setHyperparameters(hyperparameters); result.setHyperparameters(hyperparameters.get(fileName));
// Initialize results std::vectors // Initialize results std::vectors
int nResults = nfolds * static_cast<int>(randomSeeds.size()); int nResults = nfolds * static_cast<int>(randomSeeds.size());
auto accuracy_test = torch::zeros({ nResults }, torch::kFloat64); auto accuracy_test = torch::zeros({ nResults }, torch::kFloat64);
@@ -171,9 +170,9 @@ namespace platform {
for (int nfold = 0; nfold < nfolds; nfold++) { for (int nfold = 0; nfold < nfolds; nfold++) {
auto clf = Models::instance()->create(model); auto clf = Models::instance()->create(model);
setModelVersion(clf->getVersion()); setModelVersion(clf->getVersion());
if (hyperparameters.size() != 0) { auto valid = clf->getValidHyperparameters();
clf->setHyperparameters(hyperparameters); hyperparameters.check(valid, fileName);
} clf->setHyperparameters(hyperparameters.get(fileName));
// Split train - test dataset // Split train - test dataset
train_timer.start(); train_timer.start();
auto [train, test] = fold->getFold(nfold); auto [train, test] = fold->getFold(nfold);
@@ -211,7 +210,6 @@ 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();
} }
if (!quiet) if (!quiet)
std::cout << "end. " << flush; std::cout << "end. " << flush;

View File

@@ -3,29 +3,16 @@
#include <torch/torch.h> #include <torch/torch.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <string> #include <string>
#include <chrono>
#include "Folding.h" #include "Folding.h"
#include "BaseClassifier.h" #include "BaseClassifier.h"
#include "HyperParameters.h"
#include "TAN.h" #include "TAN.h"
#include "KDB.h" #include "KDB.h"
#include "AODE.h" #include "AODE.h"
#include "Timer.h"
namespace platform { namespace platform {
using json = nlohmann::json; using json = nlohmann::json;
class Timer {
private:
std::chrono::high_resolution_clock::time_point begin;
public:
Timer() = default;
~Timer() = default;
void start() { begin = std::chrono::high_resolution_clock::now(); }
double getDuration()
{
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double >> (end - begin);
return time_span.count();
}
};
class Result { class Result {
private: private:
std::string dataset, model_version; std::string dataset, model_version;
@@ -80,17 +67,8 @@ namespace platform {
const std::vector<double>& getTimesTest() const { return times_test; } const std::vector<double>& getTimesTest() const { return times_test; }
}; };
class Experiment { class Experiment {
private:
std::string title, model, platform, score_name, model_version, language_version, language;
bool discretized{ false }, stratified{ false };
std::vector<Result> results;
std::vector<int> randomSeeds;
json hyperparameters = "{}";
int nfolds{ 0 };
float duration{ 0 };
json build_json();
public: public:
Experiment(); Experiment() = default;
Experiment& setTitle(const std::string& title) { this->title = title; return *this; } Experiment& setTitle(const std::string& title) { this->title = title; return *this; }
Experiment& setModel(const std::string& model) { this->model = model; return *this; } Experiment& setModel(const std::string& model) { this->model = model; return *this; }
Experiment& setPlatform(const std::string& platform) { this->platform = platform; return *this; } Experiment& setPlatform(const std::string& platform) { this->platform = platform; return *this; }
@@ -104,13 +82,22 @@ namespace platform {
Experiment& addResult(Result result) { results.push_back(result); return *this; } Experiment& addResult(Result result) { results.push_back(result); return *this; }
Experiment& addRandomSeed(int randomSeed) { randomSeeds.push_back(randomSeed); return *this; } Experiment& addRandomSeed(int randomSeed) { randomSeeds.push_back(randomSeed); return *this; }
Experiment& setDuration(float duration) { this->duration = duration; return *this; } Experiment& setDuration(float duration) { this->duration = duration; return *this; }
Experiment& setHyperparameters(const json& hyperparameters) { this->hyperparameters = hyperparameters; return *this; } Experiment& setHyperparameters(const HyperParameters& hyperparameters_) { this->hyperparameters = hyperparameters_; return *this; }
std::string get_file_name(); std::string get_file_name();
void save(const std::string& path); void save(const std::string& path);
void cross_validation(const std::string& fileName, bool quiet); void cross_validation(const std::string& fileName, bool quiet);
void go(std::vector<std::string> filesToProcess, bool quiet); void go(std::vector<std::string> filesToProcess, bool quiet);
void show(); void show();
void report(); void report();
private:
std::string title, model, platform, score_name, model_version, language_version, language;
bool discretized{ false }, stratified{ false };
std::vector<Result> results;
std::vector<int> randomSeeds;
HyperParameters hyperparameters;
int nfolds{ 0 };
float duration{ 0 };
json build_json();
}; };
} }
#endif #endif

55
src/Platform/GridData.cc Normal file
View File

@@ -0,0 +1,55 @@
#include "GridData.h"
#include <fstream>
namespace platform {
GridData::GridData(const std::string& fileName)
{
std::ifstream resultData(fileName);
if (resultData.is_open()) {
grid = json::parse(resultData);
} else {
throw std::invalid_argument("Unable to open input file. [" + fileName + "]");
}
}
int GridData::computeNumCombinations(const json& line)
{
int numCombinations = 1;
for (const auto& item : line.items()) {
numCombinations *= item.value().size();
}
return numCombinations;
}
int GridData::getNumCombinations()
{
int numCombinations = 0;
for (const auto& line : grid) {
numCombinations += computeNumCombinations(line);
}
return numCombinations;
}
json GridData::generateCombinations(json::iterator index, const json::iterator last, std::vector<json>& output, json currentCombination)
{
if (index == last) {
// If we reached the end of input, store the current combination
output.push_back(currentCombination);
return currentCombination;
}
const auto& key = index.key();
const auto& values = index.value();
for (const auto& value : values) {
auto combination = currentCombination;
combination[key] = value;
json::iterator nextIndex = index;
generateCombinations(++nextIndex, last, output, combination);
}
return currentCombination;
}
std::vector<json> GridData::getGrid()
{
auto result = std::vector<json>();
for (json line : grid) {
generateCombinations(line.begin(), line.end(), result, json({}));
}
return result;
}
} /* namespace platform */

22
src/Platform/GridData.h Normal file
View File

@@ -0,0 +1,22 @@
#ifndef GRIDDATA_H
#define GRIDDATA_H
#include <string>
#include <vector>
#include <map>
#include <nlohmann/json.hpp>
namespace platform {
using json = nlohmann::json;
class GridData {
public:
explicit GridData(const std::string& fileName);
~GridData() = default;
std::vector<json> getGrid();
int getNumCombinations();
private:
json generateCombinations(json::iterator index, const json::iterator last, std::vector<json>& output, json currentCombination);
int computeNumCombinations(const json& line);
json grid;
};
} /* namespace platform */
#endif /* GRIDDATA_H */

130
src/Platform/GridSearch.cc Normal file
View File

@@ -0,0 +1,130 @@
#include <iostream>
#include <torch/torch.h>
#include "GridSearch.h"
#include "Models.h"
#include "Paths.h"
#include "Folding.h"
#include "Colors.h"
namespace platform {
GridSearch::GridSearch(struct ConfigGrid& config) : config(config)
{
this->config.output_file = config.path + "grid_" + config.model + "_output.json";
this->config.input_file = config.path + "grid_" + config.model + "_input.json";
}
void showProgressComb(const int num, const int total, const std::string& color)
{
int spaces = int(log(total) / log(10)) + 1;
int magic = 37 + 2 * spaces;
std::string prefix = num == 1 ? "" : string(magic, '\b') + string(magic + 1, ' ') + string(magic + 1, '\b');
std::cout << prefix << color << "(" << setw(spaces) << num << "/" << setw(spaces) << total << ") " << Colors::RESET() << flush;
}
void showProgressFold(int fold, const std::string& color, const std::string& phase)
{
std::string prefix = phase == "a" ? "" : "\b\b\b\b";
std::cout << prefix << color << fold << Colors::RESET() << "(" << color << phase << Colors::RESET() << ")" << flush;
}
std::string getColor(bayesnet::status_t status)
{
switch (status) {
case bayesnet::NORMAL:
return Colors::GREEN();
case bayesnet::WARNING:
return Colors::YELLOW();
case bayesnet::ERROR:
return Colors::RED();
default:
return Colors::RESET();
}
}
double GridSearch::processFile(std::string fileName, Datasets& datasets, HyperParameters& hyperparameters)
{
// Get dataset
auto [X, y] = datasets.getTensors(fileName);
auto states = datasets.getStates(fileName);
auto features = datasets.getFeatures(fileName);
auto samples = datasets.getNSamples(fileName);
auto className = datasets.getClassName(fileName);
double totalScore = 0.0;
int numItems = 0;
for (const auto& seed : config.seeds) {
if (!config.quiet)
std::cout << "(" << seed << ") doing Fold: " << flush;
Fold* fold;
if (config.stratified)
fold = new StratifiedKFold(config.n_folds, y, seed);
else
fold = new KFold(config.n_folds, y.size(0), seed);
double bestScore = 0.0;
for (int nfold = 0; nfold < config.n_folds; nfold++) {
auto clf = Models::instance()->create(config.model);
clf->setHyperparameters(hyperparameters.get(fileName));
auto [train, test] = fold->getFold(nfold);
auto train_t = torch::tensor(train);
auto test_t = torch::tensor(test);
auto X_train = X.index({ "...", train_t });
auto y_train = y.index({ train_t });
auto X_test = X.index({ "...", test_t });
auto y_test = y.index({ test_t });
// Train model
if (!config.quiet)
showProgressFold(nfold + 1, getColor(clf->getStatus()), "a");
clf->fit(X_train, y_train, features, className, states);
// Test model
if (!config.quiet)
showProgressFold(nfold + 1, getColor(clf->getStatus()), "b");
totalScore += clf->score(X_test, y_test);
numItems++;
if (!config.quiet)
std::cout << "\b\b\b, \b" << flush;
}
delete fold;
}
return numItems == 0 ? 0.0 : totalScore / numItems;
}
void GridSearch::go()
{
// Load datasets
auto datasets = Datasets(config.discretize, Paths::datasets());
// Create model
std::cout << "***************** Starting Gridsearch *****************" << std::endl;
std::cout << "input file=" << config.input_file << std::endl;
auto grid = GridData(config.input_file);
auto totalComb = grid.getNumCombinations();
std::cout << "* Doing " << totalComb << " combinations for each dataset/seed/fold" << std::endl;
// Generate hyperparameters grid & run gridsearch
// Check each combination of hyperparameters for each dataset and each seed
for (const auto& dataset : datasets.getNames()) {
if (!config.quiet)
std::cout << "- " << setw(20) << left << dataset << " " << right << flush;
int num = 0;
double bestScore = 0.0;
json bestHyperparameters;
for (const auto& hyperparam_line : grid.getGrid()) {
if (!config.quiet)
showProgressComb(++num, totalComb, Colors::CYAN());
auto hyperparameters = platform::HyperParameters(datasets.getNames(), hyperparam_line);
double score = processFile(dataset, datasets, hyperparameters);
if (score > bestScore) {
bestScore = score;
bestHyperparameters = hyperparam_line;
}
}
if (!config.quiet) {
std::cout << "end." << " Score: " << setw(9) << setprecision(7) << fixed
<< bestScore << " [" << bestHyperparameters.dump() << "]" << std::endl;
}
results[dataset]["score"] = bestScore;
results[dataset]["hyperparameters"] = bestHyperparameters;
}
// Save results
save();
std::cout << "***************** Ending Gridsearch *******************" << std::endl;
}
void GridSearch::save() const
{
std::ofstream file(config.output_file);
file << results.dump(4);
file.close();
}
} /* namespace platform */

36
src/Platform/GridSearch.h Normal file
View File

@@ -0,0 +1,36 @@
#ifndef GRIDSEARCH_H
#define GRIDSEARCH_H
#include <string>
#include <vector>
#include <nlohmann/json.hpp>
#include "Datasets.h"
#include "HyperParameters.h"
#include "GridData.h"
namespace platform {
using json = nlohmann::json;
struct ConfigGrid {
std::string model;
std::string score;
std::string path;
std::string input_file;
std::string output_file;
bool quiet;
bool discretize;
bool stratified;
int n_folds;
std::vector<int> seeds;
};
class GridSearch {
public:
explicit GridSearch(struct ConfigGrid& config);
void go();
void save() const;
~GridSearch() = default;
private:
double processFile(std::string fileName, Datasets& datasets, HyperParameters& hyperparameters);
json results;
struct ConfigGrid config;
};
} /* namespace platform */
#endif /* GRIDSEARCH_H */

View File

@@ -0,0 +1,55 @@
#include "HyperParameters.h"
#include <fstream>
#include <sstream>
#include <iostream>
namespace platform {
HyperParameters::HyperParameters(const std::vector<std::string>& datasets, const json& hyperparameters_)
{
// Initialize all datasets with the given hyperparameters
for (const auto& item : datasets) {
hyperparameters[item] = hyperparameters_;
}
}
// https://www.techiedelight.com/implode-a-vector-of-strings-into-a-comma-separated-string-in-cpp/
std::string join(std::vector<std::string> const& strings, std::string delim)
{
std::stringstream ss;
std::copy(strings.begin(), strings.end(),
std::ostream_iterator<std::string>(ss, delim.c_str()));
return ss.str();
}
HyperParameters::HyperParameters(const std::vector<std::string>& datasets, const std::string& hyperparameters_file)
{
// Check if file exists
std::ifstream file(hyperparameters_file);
if (!file.is_open()) {
throw std::runtime_error("File " + hyperparameters_file + " not found");
}
// Check if file is a json
json input_hyperparameters = json::parse(file);
// Check if hyperparameters are valid
for (const auto& dataset : datasets) {
if (!input_hyperparameters.contains(dataset)) {
std::cerr << "*Warning: Dataset " << dataset << " not found in hyperparameters file" << " assuming default hyperparameters" << std::endl;
hyperparameters[dataset] = json({});
continue;
}
hyperparameters[dataset] = input_hyperparameters[dataset].get<json>();
}
}
void HyperParameters::check(const std::vector<std::string>& valid, const std::string& fileName)
{
json result = hyperparameters.at(fileName);
for (const auto& item : result.items()) {
if (find(valid.begin(), valid.end(), item.key()) == valid.end()) {
throw std::invalid_argument("Hyperparameter " + item.key() + " is not valid. Passed Hyperparameters are: "
+ result.dump(4) + "\n Valid hyperparameters are: {" + join(valid, ",") + "}");
}
}
}
json HyperParameters::get(const std::string& fileName)
{
return hyperparameters.at(fileName);
}
} /* namespace platform */

View File

@@ -0,0 +1,23 @@
#ifndef HYPERPARAMETERS_H
#define HYPERPARAMETERS_H
#include <string>
#include <map>
#include <vector>
#include <nlohmann/json.hpp>
namespace platform {
using json = nlohmann::json;
class HyperParameters {
public:
HyperParameters() = default;
explicit HyperParameters(const std::vector<std::string>& datasets, const json& hyperparameters_);
explicit HyperParameters(const std::vector<std::string>& datasets, const std::string& hyperparameters_file);
~HyperParameters() = default;
bool notEmpty(const std::string& key) const { return !hyperparameters.at(key).empty(); }
void check(const std::vector<std::string>& valid, const std::string& fileName);
json get(const std::string& fileName);
private:
std::map<std::string, json> hyperparameters;
};
} /* namespace platform */
#endif /* HYPERPARAMETERS_H */

View File

@@ -11,6 +11,10 @@
#include "SPODELd.h" #include "SPODELd.h"
#include "AODELd.h" #include "AODELd.h"
#include "BoostAODE.h" #include "BoostAODE.h"
#include "STree.h"
#include "ODTE.h"
#include "SVC.h"
#include "RandomForest.h"
namespace platform { namespace platform {
class Models { class Models {
private: private:

View File

@@ -1,6 +1,7 @@
#ifndef PATHS_H #ifndef PATHS_H
#define PATHS_H #define PATHS_H
#include <string> #include <string>
#include <filesystem>
#include "DotEnv.h" #include "DotEnv.h"
namespace platform { namespace platform {
class Paths { class Paths {
@@ -8,12 +9,22 @@ namespace platform {
static std::string results() { return "results/"; } static std::string results() { return "results/"; }
static std::string hiddenResults() { return "hidden_results/"; } static std::string hiddenResults() { return "hidden_results/"; }
static std::string excel() { return "excel/"; } static std::string excel() { return "excel/"; }
static std::string cfs() { return "cfs/"; } static std::string grid() { return "grid/"; }
static std::string datasets() static std::string datasets()
{ {
auto env = platform::DotEnv(); auto env = platform::DotEnv();
return env.get("source_data"); return env.get("source_data");
} }
static void createPath(const std::string& path)
{
// Create directory if it does not exist
try {
std::filesystem::create_directory(path);
}
catch (std::exception& e) {
throw std::runtime_error("Could not create directory " + path);
}
}
static std::string excelResults() { return "some_results.xlsx"; } static std::string excelResults() { return "some_results.xlsx"; }
}; };
} }

34
src/Platform/Timer.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef TIMER_H
#define TIMER_H
#include <chrono>
#include <string>
#include <sstream>
namespace platform {
class Timer {
private:
std::chrono::high_resolution_clock::time_point begin;
std::chrono::high_resolution_clock::time_point end;
public:
Timer() = default;
~Timer() = default;
void start() { begin = std::chrono::high_resolution_clock::now(); }
void stop() { end = std::chrono::high_resolution_clock::now(); }
double getDuration()
{
stop();
std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double >> (end - begin);
return time_span.count();
}
std::string getDurationString()
{
double duration = getDuration();
double durationShow = duration > 3600 ? duration / 3600 : duration > 60 ? duration / 60 : duration;
std::string durationUnit = duration > 3600 ? "h" : duration > 60 ? "m" : "s";
std::stringstream ss;
ss << std::setw(7) << std::setprecision(2) << std::fixed << durationShow << " " << durationUnit << " ";
return ss.str();
}
};
} /* namespace platform */
#endif /* TIMER_H */

View File

@@ -7,7 +7,7 @@
argparse::ArgumentParser manageArguments(int argc, char** argv) argparse::ArgumentParser manageArguments(int argc, char** argv)
{ {
argparse::ArgumentParser program("best"); argparse::ArgumentParser program("b_sbest");
program.add_argument("-m", "--model").default_value("").help("Filter results of the selected model) (any for all models)"); program.add_argument("-m", "--model").default_value("").help("Filter results of the selected model) (any for all models)");
program.add_argument("-s", "--score").default_value("").help("Filter results of the score name supplied"); program.add_argument("-s", "--score").default_value("").help("Filter results of the score name supplied");
program.add_argument("--build").help("build best score results file").default_value(false).implicit_value(true); program.add_argument("--build").help("build best score results file").default_value(false).implicit_value(true);

81
src/Platform/b_grid.cc Normal file
View File

@@ -0,0 +1,81 @@
#include <iostream>
#include <argparse/argparse.hpp>
#include "DotEnv.h"
#include "Models.h"
#include "modelRegister.h"
#include "GridSearch.h"
#include "Paths.h"
#include "Timer.h"
argparse::ArgumentParser manageArguments(std::string program_name)
{
auto env = platform::DotEnv();
argparse::ArgumentParser program(program_name);
program.add_argument("-m", "--model")
.help("Model to use " + platform::Models::instance()->tostring())
.action([](const std::string& value) {
static const std::vector<std::string> choices = platform::Models::instance()->getNames();
if (find(choices.begin(), choices.end(), value) != choices.end()) {
return value;
}
throw std::runtime_error("Model must be one of " + platform::Models::instance()->tostring());
}
);
program.add_argument("--discretize").help("Discretize input datasets").default_value((bool)stoi(env.get("discretize"))).implicit_value(true);
program.add_argument("--quiet").help("Don't display detailed progress").default_value(false).implicit_value(true);
program.add_argument("--stratified").help("If Stratified KFold is to be done").default_value((bool)stoi(env.get("stratified"))).implicit_value(true);
program.add_argument("--score").help("Score used in gridsearch").default_value("accuracy");
program.add_argument("-f", "--folds").help("Number of folds").default_value(stoi(env.get("n_folds"))).scan<'i', int>().action([](const std::string& value) {
try {
auto k = stoi(value);
if (k < 2) {
throw std::runtime_error("Number of folds must be greater than 1");
}
return k;
}
catch (const runtime_error& err) {
throw std::runtime_error(err.what());
}
catch (...) {
throw std::runtime_error("Number of folds must be an integer");
}});
auto seed_values = env.getSeeds();
program.add_argument("-s", "--seeds").nargs(1, 10).help("Random seeds. Set to -1 to have pseudo random").scan<'i', int>().default_value(seed_values);
return program;
}
int main(int argc, char** argv)
{
auto program = manageArguments("b_grid");
struct platform::ConfigGrid config;
try {
program.parse_args(argc, argv);
config.model = program.get<std::string>("model");
config.score = program.get<std::string>("score");
config.discretize = program.get<bool>("discretize");
config.stratified = program.get<bool>("stratified");
config.n_folds = program.get<int>("folds");
config.quiet = program.get<bool>("quiet");
config.seeds = program.get<std::vector<int>>("seeds");
}
catch (const exception& err) {
cerr << err.what() << std::endl;
cerr << program;
exit(1);
}
/*
* Begin Processing
*/
auto env = platform::DotEnv();
platform::Paths::createPath(platform::Paths::grid());
config.path = platform::Paths::grid();
auto grid_search = platform::GridSearch(config);
platform::Timer timer;
timer.start();
grid_search.go();
std::cout << "Process took " << timer.getDurationString() << std::endl;
grid_search.save();
std::cout << "Done!" << std::endl;
return 0;
}

View File

@@ -11,12 +11,14 @@
using json = nlohmann::json; using json = nlohmann::json;
argparse::ArgumentParser manageArguments() argparse::ArgumentParser manageArguments(std::string program_name)
{ {
auto env = platform::DotEnv(); auto env = platform::DotEnv();
argparse::ArgumentParser program("main"); argparse::ArgumentParser program(program_name);
program.add_argument("-d", "--dataset").default_value("").help("Dataset file name"); program.add_argument("-d", "--dataset").default_value("").help("Dataset file name");
program.add_argument("--hyperparameters").default_value("{}").help("Hyperparamters passed to the model in Experiment"); program.add_argument("--hyperparameters").default_value("{}").help("Hyperparameters passed to the model in Experiment");
program.add_argument("--hyper-file").default_value("").help("Hyperparameters file name." \
"Mutually exclusive with hyperparameters. This file should contain hyperparameters for each dataset in json format.");
program.add_argument("-m", "--model") program.add_argument("-m", "--model")
.help("Model to use " + platform::Models::instance()->tostring()) .help("Model to use " + platform::Models::instance()->tostring())
.action([](const std::string& value) { .action([](const std::string& value) {
@@ -53,13 +55,13 @@ argparse::ArgumentParser manageArguments()
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
std::string file_name, model_name, title; std::string file_name, model_name, title, hyperparameters_file;
json hyperparameters_json; json hyperparameters_json;
bool discretize_dataset, stratified, saveResults, quiet; bool discretize_dataset, stratified, saveResults, quiet;
std::vector<int> seeds; std::vector<int> seeds;
std::vector<std::string> filesToTest; std::vector<std::string> filesToTest;
int n_folds; int n_folds;
auto program = manageArguments(); auto program = manageArguments("b_main");
try { try {
program.parse_args(argc, argv); program.parse_args(argc, argv);
file_name = program.get<std::string>("dataset"); file_name = program.get<std::string>("dataset");
@@ -71,6 +73,10 @@ int main(int argc, char** argv)
seeds = program.get<std::vector<int>>("seeds"); seeds = program.get<std::vector<int>>("seeds");
auto hyperparameters = program.get<std::string>("hyperparameters"); auto hyperparameters = program.get<std::string>("hyperparameters");
hyperparameters_json = json::parse(hyperparameters); hyperparameters_json = json::parse(hyperparameters);
hyperparameters_file = program.get<std::string>("hyper-file");
if (hyperparameters_file != "" && hyperparameters != "{}") {
throw runtime_error("hyperparameters and hyper_file are mutually exclusive");
}
title = program.get<std::string>("title"); title = program.get<std::string>("title");
if (title == "" && file_name == "") { if (title == "" && file_name == "") {
throw runtime_error("title is mandatory if dataset is not provided"); throw runtime_error("title is mandatory if dataset is not provided");
@@ -96,6 +102,13 @@ int main(int argc, char** argv)
filesToTest = datasets.getNames(); filesToTest = datasets.getNames();
saveResults = true; saveResults = true;
} }
platform::HyperParameters test_hyperparams;
if (hyperparameters_file != "") {
test_hyperparams = platform::HyperParameters(datasets.getNames(), hyperparameters_file);
} else {
test_hyperparams = platform::HyperParameters(datasets.getNames(), hyperparameters_json);
}
/* /*
* Begin Processing * Begin Processing
*/ */
@@ -104,7 +117,7 @@ int main(int argc, char** argv)
experiment.setTitle(title).setLanguage("cpp").setLanguageVersion("14.0.3"); experiment.setTitle(title).setLanguage("cpp").setLanguageVersion("14.0.3");
experiment.setDiscretized(discretize_dataset).setModel(model_name).setPlatform(env.get("platform")); experiment.setDiscretized(discretize_dataset).setModel(model_name).setPlatform(env.get("platform"));
experiment.setStratified(stratified).setNFolds(n_folds).setScoreName("accuracy"); experiment.setStratified(stratified).setNFolds(n_folds).setScoreName("accuracy");
experiment.setHyperparameters(hyperparameters_json); experiment.setHyperparameters(test_hyperparams);
for (auto seed : seeds) { for (auto seed : seeds) {
experiment.addRandomSeed(seed); experiment.addRandomSeed(seed);
} }

View File

@@ -5,7 +5,7 @@
argparse::ArgumentParser manageArguments(int argc, char** argv) argparse::ArgumentParser manageArguments(int argc, char** argv)
{ {
argparse::ArgumentParser program("manage"); argparse::ArgumentParser program("b_manage");
program.add_argument("-n", "--number").default_value(0).help("Number of results to show (0 = all)").scan<'i', int>(); program.add_argument("-n", "--number").default_value(0).help("Number of results to show (0 = all)").scan<'i', int>();
program.add_argument("-m", "--model").default_value("any").help("Filter results of the selected model)"); program.add_argument("-m", "--model").default_value("any").help("Filter results of the selected model)");
program.add_argument("-s", "--score").default_value("any").help("Filter results of the score name supplied"); program.add_argument("-s", "--score").default_value("any").help("Filter results of the score name supplied");

View File

@@ -18,4 +18,12 @@ static platform::Registrar registrarALD("AODELd",
[](void) -> bayesnet::BaseClassifier* { return new bayesnet::AODELd();}); [](void) -> bayesnet::BaseClassifier* { return new bayesnet::AODELd();});
static platform::Registrar registrarBA("BoostAODE", static platform::Registrar registrarBA("BoostAODE",
[](void) -> bayesnet::BaseClassifier* { return new bayesnet::BoostAODE();}); [](void) -> bayesnet::BaseClassifier* { return new bayesnet::BoostAODE();});
static platform::Registrar registrarSt("STree",
[](void) -> bayesnet::BaseClassifier* { return new pywrap::STree();});
static platform::Registrar registrarOdte("Odte",
[](void) -> bayesnet::BaseClassifier* { return new pywrap::ODTE();});
static platform::Registrar registrarSvc("SVC",
[](void) -> bayesnet::BaseClassifier* { return new pywrap::SVC();});
static platform::Registrar registrarRaF("RandomForest",
[](void) -> bayesnet::BaseClassifier* { return new pywrap::RandomForest();});
#endif #endif

View File

@@ -1,5 +1,6 @@
include_directories(${PyWrap_SOURCE_DIR}/lib/Files) include_directories(${BayesNet_SOURCE_DIR}/lib/Files)
include_directories(${PyWrap_SOURCE_DIR}/lib/json/include) include_directories(${BayesNet_SOURCE_DIR}/lib/json/include)
include_directories(${BayesNet_SOURCE_DIR}/src/BayesNet)
include_directories(${Python3_INCLUDE_DIRS}) include_directories(${Python3_INCLUDE_DIRS})
include_directories(${TORCH_INCLUDE_DIRS}) include_directories(${TORCH_INCLUDE_DIRS})

View File

@@ -1,25 +0,0 @@
#ifndef CLASSIFIER_H
#define CLASSIFIER_H
#include <torch/torch.h>
#include <nlohmann/json.hpp>
#include <string>
#include <map>
#include <vector>
namespace pywrap {
class Classifier {
public:
Classifier() = default;
virtual ~Classifier() = default;
virtual 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) = 0;
virtual Classifier& fit(torch::Tensor& X, torch::Tensor& y) = 0;
virtual torch::Tensor predict(torch::Tensor& X) = 0;
virtual double score(torch::Tensor& X, torch::Tensor& y) = 0;
virtual std::string version() = 0;
virtual std::string sklearnVersion() = 0;
virtual void setHyperparameters(const nlohmann::json& hyperparameters) = 0;
protected:
virtual void checkHyperparameters(const std::vector<std::string>& validKeys, const nlohmann::json& hyperparameters) = 0;
};
} /* namespace pywrap */
#endif /* CLASSIFIER_H */

View File

@@ -1,15 +1,12 @@
#include "ODTE.h" #include "ODTE.h"
namespace pywrap { namespace pywrap {
ODTE::ODTE() : PyClassifier("odte", "Odte")
{
validHyperparameters = { "n_jobs", "n_estimators", "random_state" };
}
std::string ODTE::graph() std::string ODTE::graph()
{ {
return callMethodString("graph"); return callMethodString("graph");
} }
void ODTE::setHyperparameters(const nlohmann::json& hyperparameters)
{
// Check if hyperparameters are valid
const std::vector<std::string> validKeys = { "n_jobs", "n_estimators", "random_state" };
checkHyperparameters(validKeys, hyperparameters);
this->hyperparameters = hyperparameters;
}
} /* namespace pywrap */ } /* namespace pywrap */

View File

@@ -6,10 +6,9 @@
namespace pywrap { namespace pywrap {
class ODTE : public PyClassifier { class ODTE : public PyClassifier {
public: public:
ODTE() : PyClassifier("odte", "Odte") {}; ODTE();
~ODTE() = default; ~ODTE() = default;
std::string graph(); std::string graph();
void setHyperparameters(const nlohmann::json& hyperparameters) override;
}; };
} /* namespace pywrap */ } /* namespace pywrap */
#endif /* ODTE_H */ #endif /* ODTE_H */

View File

@@ -2,7 +2,7 @@
namespace pywrap { namespace pywrap {
namespace bp = boost::python; namespace bp = boost::python;
namespace np = boost::python::numpy; namespace np = boost::python::numpy;
PyClassifier::PyClassifier(const std::string& module, const std::string& className) : module(module), className(className), fitted(false) PyClassifier::PyClassifier(const std::string& module, const std::string& className, bool sklearn) : module(module), className(className), sklearn(sklearn), fitted(false)
{ {
// This id allows to have more than one instance of the same module/class // This id allows to have more than one instance of the same module/class
id = reinterpret_cast<clfId_t>(this); id = reinterpret_cast<clfId_t>(this);
@@ -29,12 +29,11 @@ namespace pywrap {
} }
std::string PyClassifier::version() std::string PyClassifier::version()
{ {
return pyWrap->version(id); if (sklearn) {
}
std::string PyClassifier::sklearnVersion()
{
return pyWrap->sklearnVersion(); return pyWrap->sklearnVersion();
} }
return pyWrap->version(id);
}
std::string PyClassifier::callMethodString(const std::string& method) std::string PyClassifier::callMethodString(const std::string& method)
{ {
return pyWrap->callMethodString(id, method); return pyWrap->callMethodString(id, method);
@@ -74,27 +73,16 @@ namespace pywrap {
Py_XDECREF(incoming); Py_XDECREF(incoming);
return resultTensor; return resultTensor;
} }
double PyClassifier::score(torch::Tensor& X, torch::Tensor& y) float PyClassifier::score(torch::Tensor& X, torch::Tensor& y)
{ {
auto [Xn, yn] = tensors2numpy(X, y); auto [Xn, yn] = tensors2numpy(X, y);
CPyObject Xp = bp::incref(bp::object(Xn).ptr()); CPyObject Xp = bp::incref(bp::object(Xn).ptr());
CPyObject yp = bp::incref(bp::object(yn).ptr()); CPyObject yp = bp::incref(bp::object(yn).ptr());
auto result = pyWrap->score(id, Xp, yp); float result = pyWrap->score(id, Xp, yp);
return result; return result;
} }
void PyClassifier::setHyperparameters(const nlohmann::json& hyperparameters) void PyClassifier::setHyperparameters(const nlohmann::json& hyperparameters)
{ {
// Check if hyperparameters are valid, default is no hyperparameters
const std::vector<std::string> validKeys = { };
checkHyperparameters(validKeys, hyperparameters);
this->hyperparameters = hyperparameters; this->hyperparameters = hyperparameters;
} }
void PyClassifier::checkHyperparameters(const std::vector<std::string>& validKeys, const nlohmann::json& hyperparameters)
{
for (const auto& item : hyperparameters.items()) {
if (find(validKeys.begin(), validKeys.end(), item.key()) == validKeys.end()) {
throw std::invalid_argument("Hyperparameter " + item.key() + " is not valid");
}
}
}
} /* namespace pywrap */ } /* namespace pywrap */

View File

@@ -13,25 +13,41 @@
#include "TypeId.h" #include "TypeId.h"
namespace pywrap { namespace pywrap {
class PyClassifier : public Classifier { class PyClassifier : public bayesnet::BaseClassifier {
public: public:
PyClassifier(const std::string& module, const std::string& className); PyClassifier(const std::string& module, const std::string& className, const bool sklearn = false);
virtual ~PyClassifier(); virtual ~PyClassifier();
PyClassifier& 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) override { return *this; };
// X is nxm tensor, y is nx1 tensor
PyClassifier& 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) override; PyClassifier& 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) override;
PyClassifier& fit(torch::Tensor& X, torch::Tensor& y) override; PyClassifier& fit(torch::Tensor& X, torch::Tensor& y);
PyClassifier& fit(torch::Tensor& dataset, const std::vector<std::string>& features, const std::string& className, std::map<std::string, std::vector<int>>& states) override { return *this; };
PyClassifier& 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) override { return *this; };
torch::Tensor predict(torch::Tensor& X) override; torch::Tensor predict(torch::Tensor& X) override;
double score(torch::Tensor& X, torch::Tensor& y) override; std::vector<int> predict(std::vector<std::vector<int >>& X) override { return std::vector<int>(); };
std::string version() override; float score(std::vector<std::vector<int>>& X, std::vector<int>& y) override { return 0.0; };
std::string sklearnVersion() override; float score(torch::Tensor& X, torch::Tensor& y) override;
std::string version();
std::string callMethodString(const std::string& method); std::string callMethodString(const std::string& method);
std::string getVersion() override { return this->version(); };
// TODO: Implement these 3 methods
int getNumberOfNodes()const override { return 0; };
int getNumberOfEdges()const override { return 0; };
int getNumberOfStates() const override { return 0; };
std::vector<std::string> show() const override { return std::vector<std::string>(); }
std::vector<std::string> graph(const std::string& title = "") const override { return std::vector<std::string>(); }
bayesnet::status_t getStatus() const override { return bayesnet::NORMAL; };
std::vector<std::string> topological_order() override { return std::vector<std::string>(); }
void dump_cpt() const override {};
void setHyperparameters(const nlohmann::json& hyperparameters) override; void setHyperparameters(const nlohmann::json& hyperparameters) override;
protected: protected:
void checkHyperparameters(const std::vector<std::string>& validKeys, const nlohmann::json& hyperparameters) override;
nlohmann::json hyperparameters; nlohmann::json hyperparameters;
void trainModel(const torch::Tensor& weights) override {};
private: private:
PyWrap* pyWrap; PyWrap* pyWrap;
std::string module; std::string module;
std::string className; std::string className;
bool sklearn;
clfId_t id; clfId_t id;
bool fitted; bool fitted;
}; };

View File

@@ -5,6 +5,7 @@
#include <map> #include <map>
#include <sstream> #include <sstream>
#include <boost/python/numpy.hpp> #include <boost/python/numpy.hpp>
#include <iostream>
namespace pywrap { namespace pywrap {
namespace np = boost::python::numpy; namespace np = boost::python::numpy;
@@ -19,6 +20,7 @@ namespace pywrap {
if (wrapper == nullptr) { if (wrapper == nullptr) {
wrapper = new PyWrap(); wrapper = new PyWrap();
pyInstance = new CPyInstance(); pyInstance = new CPyInstance();
PyRun_SimpleString("import warnings;warnings.filterwarnings('ignore')");
} }
return wrapper; return wrapper;
} }
@@ -72,9 +74,11 @@ namespace pywrap {
PyErr_Print(); PyErr_Print();
errorAbort("Error cleaning module "); errorAbort("Error cleaning module ");
} }
if (moduleClassMap.empty()) { // With boost you can't remove the interpreter
RemoveInstance(); // https://www.boost.org/doc/libs/1_83_0/libs/python/doc/html/tutorial/tutorial/embedding.html#tutorial.embedding.getting_started
} // if (moduleClassMap.empty()) {
// RemoveInstance();
// }
} }
void PyWrap::errorAbort(const std::string& message) void PyWrap::errorAbort(const std::string& message)
{ {

View File

@@ -1,8 +1,8 @@
#include "RandomForest.h" #include "RandomForest.h"
namespace pywrap { namespace pywrap {
std::string RandomForest::version() RandomForest::RandomForest() : PyClassifier("sklearn.ensemble", "RandomForestClassifier", true)
{ {
return sklearnVersion(); validHyperparameters = { "n_estimators", "n_jobs", "random_state" };
} }
} /* namespace pywrap */ } /* namespace pywrap */

View File

@@ -5,9 +5,8 @@
namespace pywrap { namespace pywrap {
class RandomForest : public PyClassifier { class RandomForest : public PyClassifier {
public: public:
RandomForest() : PyClassifier("sklearn.ensemble", "RandomForestClassifier") {}; RandomForest();
~RandomForest() = default; ~RandomForest() = default;
std::string version();
}; };
} /* namespace pywrap */ } /* namespace pywrap */
#endif /* RANDOMFOREST_H */ #endif /* RANDOMFOREST_H */

View File

@@ -1,15 +1,12 @@
#include "STree.h" #include "STree.h"
namespace pywrap { namespace pywrap {
STree::STree() : PyClassifier("stree", "Stree")
{
validHyperparameters = { "C", "kernel", "max_iter", "max_depth", "random_state", "multiclass_strategy", "gamma", "max_features", "degree" };
};
std::string STree::graph() std::string STree::graph()
{ {
return callMethodString("graph"); return callMethodString("graph");
} }
void STree::setHyperparameters(const nlohmann::json& hyperparameters)
{
// Check if hyperparameters are valid
const std::vector<std::string> validKeys = { "C", "n_jobs", "kernel", "max_iter", "max_depth", "random_state", "multiclass_strategy" };
checkHyperparameters(validKeys, hyperparameters);
this->hyperparameters = hyperparameters;
}
} /* namespace pywrap */ } /* namespace pywrap */

View File

@@ -6,10 +6,9 @@
namespace pywrap { namespace pywrap {
class STree : public PyClassifier { class STree : public PyClassifier {
public: public:
STree() : PyClassifier("stree", "Stree") {}; STree();
~STree() = default; ~STree() = default;
std::string graph(); std::string graph();
void setHyperparameters(const nlohmann::json& hyperparameters) override;
}; };
} /* namespace pywrap */ } /* namespace pywrap */
#endif /* STREE_H */ #endif /* STREE_H */

View File

@@ -1,15 +1,8 @@
#include "SVC.h" #include "SVC.h"
namespace pywrap { namespace pywrap {
std::string SVC::version() SVC::SVC() : PyClassifier("sklearn.svm", "SVC", true)
{ {
return sklearnVersion(); validHyperparameters = { "C", "gamma", "kernel", "random_state" };
}
void SVC::setHyperparameters(const nlohmann::json& hyperparameters)
{
// Check if hyperparameters are valid
const std::vector<std::string> validKeys = { "C", "gamma", "kernel", "random_state" };
checkHyperparameters(validKeys, hyperparameters);
this->hyperparameters = hyperparameters;
} }
} /* namespace pywrap */ } /* namespace pywrap */

View File

@@ -5,11 +5,9 @@
namespace pywrap { namespace pywrap {
class SVC : public PyClassifier { class SVC : public PyClassifier {
public: public:
SVC() : PyClassifier("sklearn.svm", "SVC") {}; SVC();
~SVC() = default; ~SVC() = default;
std::string version();
void setHyperparameters(const nlohmann::json& hyperparameters) override;
}; };
} /* namespace pywrap */ } /* namespace pywrap */
#endif /* STREE_H */ #endif /* SVC_H */

835
stree_results.json Normal file
View File

@@ -0,0 +1,835 @@
[
{
"date": "2021-04-11",
"time": "18:46:29",
"type": "crossval",
"classifier": "stree",
"dataset": "balance-scale",
"accuracy": "0.97056",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 10000.0, \"gamma\": 0.1, \"kernel\": \"rbf\", \"max_iter\": 10000.0}",
"time_spent": "0.0135214",
"time_spent_std": "0.00111213",
"accuracy_std": "0.0150468",
"nodes": "7.0",
"leaves": "4.0",
"depth": "3.0"
},
{
"date": "2021-04-11",
"time": "18:46:29",
"type": "crossval",
"classifier": "stree",
"dataset": "balloons",
"accuracy": "0.86",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 7, \"gamma\": 0.1, \"kernel\": \"rbf\", \"max_iter\": 10000.0}",
"time_spent": "0.000804768",
"time_spent_std": "7.74797e-05",
"accuracy_std": "0.285015",
"nodes": "3.0",
"leaves": "2.0",
"depth": "2.0"
},
{
"date": "2021-04-11",
"time": "18:46:29",
"type": "crossval",
"classifier": "stree",
"dataset": "breast-cancer-wisc-diag",
"accuracy": "0.972764",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.2, \"max_iter\": 10000.0}",
"time_spent": "0.00380772",
"time_spent_std": "0.000638676",
"accuracy_std": "0.0173132",
"nodes": "3.24",
"leaves": "2.12",
"depth": "2.12"
},
{
"date": "2021-04-11",
"time": "18:46:30",
"type": "crossval",
"classifier": "stree",
"dataset": "breast-cancer-wisc-prog",
"accuracy": "0.811128",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.2, \"max_iter\": 10000.0}",
"time_spent": "0.00767535",
"time_spent_std": "0.00148114",
"accuracy_std": "0.0584601",
"nodes": "5.84",
"leaves": "3.42",
"depth": "3.24"
},
{
"date": "2021-04-11",
"time": "18:46:31",
"type": "crossval",
"classifier": "stree",
"dataset": "breast-cancer-wisc",
"accuracy": "0.966661",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.00652217",
"time_spent_std": "0.000726579",
"accuracy_std": "0.0139421",
"nodes": "8.88",
"leaves": "4.94",
"depth": "4.08"
},
{
"date": "2021-04-11",
"time": "18:46:32",
"type": "crossval",
"classifier": "stree",
"dataset": "breast-cancer",
"accuracy": "0.734211",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.023475",
"time_spent_std": "0.00584447",
"accuracy_std": "0.0479774",
"nodes": "21.72",
"leaves": "11.36",
"depth": "5.86"
},
{
"date": "2021-04-11",
"time": "18:49:08",
"type": "crossval",
"classifier": "stree",
"dataset": "cardiotocography-10clases",
"accuracy": "0.791487",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "3.10582",
"time_spent_std": "0.339218",
"accuracy_std": "0.0192082",
"nodes": "160.76",
"leaves": "80.88",
"depth": "22.86"
},
{
"date": "2021-04-11",
"time": "18:50:01",
"type": "crossval",
"classifier": "stree",
"dataset": "cardiotocography-3clases",
"accuracy": "0.900613",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "1.05228",
"time_spent_std": "0.138768",
"accuracy_std": "0.0154004",
"nodes": "47.68",
"leaves": "24.34",
"depth": "8.84"
},
{
"date": "2021-04-11",
"time": "18:50:01",
"type": "crossval",
"classifier": "stree",
"dataset": "conn-bench-sonar-mines-rocks",
"accuracy": "0.755528",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.011577",
"time_spent_std": "0.00341148",
"accuracy_std": "0.0678424",
"nodes": "6.08",
"leaves": "3.54",
"depth": "2.86"
},
{
"date": "2021-04-11",
"time": "18:50:17",
"type": "crossval",
"classifier": "stree",
"dataset": "cylinder-bands",
"accuracy": "0.715049",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.301143",
"time_spent_std": "0.109773",
"accuracy_std": "0.0367646",
"nodes": "26.2",
"leaves": "13.6",
"depth": "6.82"
},
{
"date": "2021-04-11",
"time": "18:50:19",
"type": "crossval",
"classifier": "stree",
"dataset": "dermatology",
"accuracy": "0.971833",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 55, \"max_iter\": 10000.0}",
"time_spent": "0.0377538",
"time_spent_std": "0.010726",
"accuracy_std": "0.0206883",
"nodes": "11.0",
"leaves": "6.0",
"depth": "6.0"
},
{
"date": "2021-04-11",
"time": "18:50:19",
"type": "crossval",
"classifier": "stree",
"dataset": "echocardiogram",
"accuracy": "0.814758",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 7, \"gamma\": 0.1, \"kernel\": \"poly\", \"max_features\": \"auto\", \"max_iter\": 10000.0}",
"time_spent": "0.00333449",
"time_spent_std": "0.000964686",
"accuracy_std": "0.0998078",
"nodes": "7.0",
"leaves": "4.0",
"depth": "3.54"
},
{
"date": "2021-04-11",
"time": "18:50:20",
"type": "crossval",
"classifier": "stree",
"dataset": "fertility",
"accuracy": "0.88",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.05, \"max_features\": \"auto\", \"max_iter\": 10000.0}",
"time_spent": "0.00090271",
"time_spent_std": "8.96446e-05",
"accuracy_std": "0.0547723",
"nodes": "1.0",
"leaves": "1.0",
"depth": "1.0"
},
{
"date": "2021-04-11",
"time": "18:50:21",
"type": "crossval",
"classifier": "stree",
"dataset": "haberman-survival",
"accuracy": "0.735637",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.0171611",
"time_spent_std": "0.00334945",
"accuracy_std": "0.0434614",
"nodes": "23.4",
"leaves": "12.2",
"depth": "5.98"
},
{
"date": "2021-04-11",
"time": "18:50:21",
"type": "crossval",
"classifier": "stree",
"dataset": "heart-hungarian",
"accuracy": "0.827522",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.05, \"max_iter\": 10000.0}",
"time_spent": "0.00493946",
"time_spent_std": "0.000738198",
"accuracy_std": "0.0505283",
"nodes": "10.16",
"leaves": "5.58",
"depth": "4.0"
},
{
"date": "2021-04-11",
"time": "18:50:21",
"type": "crossval",
"classifier": "stree",
"dataset": "hepatitis",
"accuracy": "0.824516",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 7, \"gamma\": 0.1, \"kernel\": \"rbf\", \"max_iter\": 10000.0}",
"time_spent": "0.0021534",
"time_spent_std": "0.000133715",
"accuracy_std": "0.0738872",
"nodes": "3.0",
"leaves": "2.0",
"depth": "2.0"
},
{
"date": "2021-04-11",
"time": "18:50:23",
"type": "crossval",
"classifier": "stree",
"dataset": "ilpd-indian-liver",
"accuracy": "0.723498",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.0345243",
"time_spent_std": "0.015789",
"accuracy_std": "0.0384886",
"nodes": "16.04",
"leaves": "8.52",
"depth": "5.28"
},
{
"date": "2021-04-11",
"time": "18:50:24",
"type": "crossval",
"classifier": "stree",
"dataset": "ionosphere",
"accuracy": "0.953276",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 7, \"gamma\": 0.1, \"kernel\": \"rbf\", \"max_iter\": 10000.0}",
"time_spent": "0.00881722",
"time_spent_std": "0.000843108",
"accuracy_std": "0.0238537",
"nodes": "3.16",
"leaves": "2.08",
"depth": "2.08"
},
{
"date": "2021-04-11",
"time": "18:50:24",
"type": "crossval",
"classifier": "stree",
"dataset": "iris",
"accuracy": "0.965333",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.00357342",
"time_spent_std": "0.000400509",
"accuracy_std": "0.0319444",
"nodes": "5.0",
"leaves": "3.0",
"depth": "3.0"
},
{
"date": "2021-04-11",
"time": "18:50:36",
"type": "crossval",
"classifier": "stree",
"dataset": "led-display",
"accuracy": "0.703",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.222106",
"time_spent_std": "0.0116922",
"accuracy_std": "0.0291204",
"nodes": "47.16",
"leaves": "24.08",
"depth": "17.76"
},
{
"date": "2021-04-11",
"time": "18:51:18",
"type": "crossval",
"classifier": "stree",
"dataset": "libras",
"accuracy": "0.788611",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.08, \"max_iter\": 10000.0}",
"time_spent": "0.841714",
"time_spent_std": "0.0830966",
"accuracy_std": "0.0516913",
"nodes": "82.28",
"leaves": "41.64",
"depth": "28.84"
},
{
"date": "2021-04-11",
"time": "18:51:41",
"type": "crossval",
"classifier": "stree",
"dataset": "low-res-spect",
"accuracy": "0.883782",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.05, \"max_iter\": 10000.0}",
"time_spent": "0.446301",
"time_spent_std": "0.0411822",
"accuracy_std": "0.0324593",
"nodes": "27.4",
"leaves": "14.2",
"depth": "10.74"
},
{
"date": "2021-04-11",
"time": "18:51:41",
"type": "crossval",
"classifier": "stree",
"dataset": "lymphography",
"accuracy": "0.835034",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.05, \"max_iter\": 10000.0}",
"time_spent": "0.00539465",
"time_spent_std": "0.000754365",
"accuracy_std": "0.0590649",
"nodes": "9.04",
"leaves": "5.02",
"depth": "4.48"
},
{
"date": "2021-04-11",
"time": "18:51:43",
"type": "crossval",
"classifier": "stree",
"dataset": "mammographic",
"accuracy": "0.81915",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.0227931",
"time_spent_std": "0.00328533",
"accuracy_std": "0.0222517",
"nodes": "7.4",
"leaves": "4.2",
"depth": "4.0"
},
{
"date": "2021-04-11",
"time": "18:51:43",
"type": "crossval",
"classifier": "stree",
"dataset": "molec-biol-promoter",
"accuracy": "0.767056",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.05, \"gamma\": 0.1, \"kernel\": \"poly\", \"max_iter\": 10000.0}",
"time_spent": "0.00130273",
"time_spent_std": "0.000105772",
"accuracy_std": "0.0910923",
"nodes": "3.0",
"leaves": "2.0",
"depth": "2.0"
},
{
"date": "2021-04-11",
"time": "18:51:44",
"type": "crossval",
"classifier": "stree",
"dataset": "musk-1",
"accuracy": "0.916388",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.05, \"gamma\": 0.1, \"kernel\": \"poly\", \"max_iter\": 10000.0}",
"time_spent": "0.0116367",
"time_spent_std": "0.000331845",
"accuracy_std": "0.0275208",
"nodes": "3.0",
"leaves": "2.0",
"depth": "2.0"
},
{
"date": "2021-04-11",
"time": "18:51:55",
"type": "crossval",
"classifier": "stree",
"dataset": "oocytes_merluccius_nucleus_4d",
"accuracy": "0.835125",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 8.25, \"gamma\": 0.1, \"kernel\": \"poly\"}",
"time_spent": "0.208895",
"time_spent_std": "0.0270573",
"accuracy_std": "0.0220961",
"nodes": "10.52",
"leaves": "5.76",
"depth": "4.42"
},
{
"date": "2021-04-11",
"time": "18:52:04",
"type": "crossval",
"classifier": "stree",
"dataset": "oocytes_merluccius_states_2f",
"accuracy": "0.915365",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.182198",
"time_spent_std": "0.0294267",
"accuracy_std": "0.020396",
"nodes": "18.04",
"leaves": "9.52",
"depth": "5.3"
},
{
"date": "2021-04-11",
"time": "18:52:41",
"type": "crossval",
"classifier": "stree",
"dataset": "oocytes_trisopterus_nucleus_2f",
"accuracy": "0.800986",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.717113",
"time_spent_std": "0.209608",
"accuracy_std": "0.0218449",
"nodes": "29.88",
"leaves": "15.44",
"depth": "7.38"
},
{
"date": "2021-04-11",
"time": "18:52:44",
"type": "crossval",
"classifier": "stree",
"dataset": "oocytes_trisopterus_states_5b",
"accuracy": "0.922249",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.11, \"max_iter\": 10000.0}",
"time_spent": "0.0545047",
"time_spent_std": "0.00853014",
"accuracy_std": "0.0179203",
"nodes": "7.44",
"leaves": "4.22",
"depth": "3.6"
},
{
"date": "2021-04-11",
"time": "18:52:44",
"type": "crossval",
"classifier": "stree",
"dataset": "parkinsons",
"accuracy": "0.882051",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.00795048",
"time_spent_std": "0.00176761",
"accuracy_std": "0.0478327",
"nodes": "8.48",
"leaves": "4.74",
"depth": "3.76"
},
{
"date": "2021-04-11",
"time": "18:52:48",
"type": "crossval",
"classifier": "stree",
"dataset": "pima",
"accuracy": "0.766651",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.0750048",
"time_spent_std": "0.0213995",
"accuracy_std": "0.0297203",
"nodes": "17.4",
"leaves": "9.2",
"depth": "5.66"
},
{
"date": "2021-04-11",
"time": "18:52:48",
"type": "crossval",
"classifier": "stree",
"dataset": "pittsburg-bridges-MATERIAL",
"accuracy": "0.867749",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 7, \"gamma\": 0.1, \"kernel\": \"rbf\", \"max_iter\": 10000.0}",
"time_spent": "0.00293318",
"time_spent_std": "0.000331469",
"accuracy_std": "0.0712226",
"nodes": "5.16",
"leaves": "3.08",
"depth": "3.02"
},
{
"date": "2021-04-11",
"time": "18:52:49",
"type": "crossval",
"classifier": "stree",
"dataset": "pittsburg-bridges-REL-L",
"accuracy": "0.632238",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.0136311",
"time_spent_std": "0.00322964",
"accuracy_std": "0.101211",
"nodes": "16.32",
"leaves": "8.66",
"depth": "5.96"
},
{
"date": "2021-04-11",
"time": "18:52:50",
"type": "crossval",
"classifier": "stree",
"dataset": "pittsburg-bridges-SPAN",
"accuracy": "0.659766",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.05, \"max_iter\": 10000.0}",
"time_spent": "0.00524256",
"time_spent_std": "0.00158822",
"accuracy_std": "0.1165",
"nodes": "9.84",
"leaves": "5.42",
"depth": "4.58"
},
{
"date": "2021-04-11",
"time": "18:52:50",
"type": "crossval",
"classifier": "stree",
"dataset": "pittsburg-bridges-T-OR-D",
"accuracy": "0.861619",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.00295627",
"time_spent_std": "0.000578594",
"accuracy_std": "0.0693747",
"nodes": "4.56",
"leaves": "2.78",
"depth": "2.68"
},
{
"date": "2021-04-11",
"time": "18:52:50",
"type": "crossval",
"classifier": "stree",
"dataset": "planning",
"accuracy": "0.73527",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 7, \"gamma\": 10.0, \"kernel\": \"rbf\", \"max_iter\": 10000.0}",
"time_spent": "0.0030475",
"time_spent_std": "0.000172266",
"accuracy_std": "0.0669776",
"nodes": "3.0",
"leaves": "2.0",
"depth": "2.0"
},
{
"date": "2021-04-11",
"time": "18:52:51",
"type": "crossval",
"classifier": "stree",
"dataset": "post-operative",
"accuracy": "0.711111",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 55, \"degree\": 5, \"gamma\": 0.1, \"kernel\": \"poly\", \"max_iter\": 10000.0}",
"time_spent": "0.0018727",
"time_spent_std": "0.000481977",
"accuracy_std": "0.0753592",
"nodes": "2.64",
"leaves": "1.82",
"depth": "1.82"
},
{
"date": "2021-04-11",
"time": "18:52:52",
"type": "crossval",
"classifier": "stree",
"dataset": "seeds",
"accuracy": "0.952857",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 10000.0, \"max_iter\": 10000.0}",
"time_spent": "0.0203492",
"time_spent_std": "0.00518065",
"accuracy_std": "0.0279658",
"nodes": "9.88",
"leaves": "5.44",
"depth": "4.44"
},
{
"date": "2021-04-11",
"time": "18:52:52",
"type": "crossval",
"classifier": "stree",
"dataset": "statlog-australian-credit",
"accuracy": "0.678261",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.05, \"max_features\": \"auto\", \"max_iter\": 10000.0}",
"time_spent": "0.00205337",
"time_spent_std": "0.00083162",
"accuracy_std": "0.0390498",
"nodes": "1.32",
"leaves": "1.16",
"depth": "1.16"
},
{
"date": "2021-04-11",
"time": "18:53:07",
"type": "crossval",
"classifier": "stree",
"dataset": "statlog-german-credit",
"accuracy": "0.7625",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.290754",
"time_spent_std": "0.0653152",
"accuracy_std": "0.0271892",
"nodes": "21.24",
"leaves": "11.12",
"depth": "6.18"
},
{
"date": "2021-04-11",
"time": "18:53:09",
"type": "crossval",
"classifier": "stree",
"dataset": "statlog-heart",
"accuracy": "0.822963",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.0138923",
"time_spent_std": "0.00323664",
"accuracy_std": "0.044004",
"nodes": "14.56",
"leaves": "7.78",
"depth": "5.0"
},
{
"date": "2021-04-11",
"time": "18:56:43",
"type": "crossval",
"classifier": "stree",
"dataset": "statlog-image",
"accuracy": "0.955931",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 7, \"max_iter\": 10000.0}",
"time_spent": "4.27584",
"time_spent_std": "0.200362",
"accuracy_std": "0.00956073",
"nodes": "36.92",
"leaves": "18.96",
"depth": "10.8"
},
{
"date": "2021-04-11",
"time": "18:56:57",
"type": "crossval",
"classifier": "stree",
"dataset": "statlog-vehicle",
"accuracy": "0.793028",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.278833",
"time_spent_std": "0.0392173",
"accuracy_std": "0.030104",
"nodes": "23.88",
"leaves": "12.44",
"depth": "7.06"
},
{
"date": "2021-04-11",
"time": "18:57:07",
"type": "crossval",
"classifier": "stree",
"dataset": "synthetic-control",
"accuracy": "0.95",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.55, \"max_iter\": 10000.0}",
"time_spent": "0.205184",
"time_spent_std": "0.040793",
"accuracy_std": "0.0253859",
"nodes": "12.48",
"leaves": "6.74",
"depth": "6.5"
},
{
"date": "2021-04-11",
"time": "18:57:08",
"type": "crossval",
"classifier": "stree",
"dataset": "tic-tac-toe",
"accuracy": "0.984444",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.2, \"gamma\": 0.1, \"kernel\": \"poly\", \"max_iter\": 10000.0}",
"time_spent": "0.0123015",
"time_spent_std": "0.000423728",
"accuracy_std": "0.00838747",
"nodes": "3.0",
"leaves": "2.0",
"depth": "2.0"
},
{
"date": "2021-04-11",
"time": "18:57:09",
"type": "crossval",
"classifier": "stree",
"dataset": "vertebral-column-2clases",
"accuracy": "0.852903",
"norm": 1,
"stand": 0,
"parameters": "{}",
"time_spent": "0.00576833",
"time_spent_std": "0.000910332",
"accuracy_std": "0.0408851",
"nodes": "6.04",
"leaves": "3.52",
"depth": "3.34"
},
{
"date": "2021-04-11",
"time": "18:57:09",
"type": "crossval",
"classifier": "stree",
"dataset": "wine",
"accuracy": "0.979159",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.55, \"max_iter\": 10000.0}",
"time_spent": "0.0019741",
"time_spent_std": "0.000137745",
"accuracy_std": "0.022427",
"nodes": "5.0",
"leaves": "3.0",
"depth": "3.0"
},
{
"date": "2021-04-11",
"time": "18:57:10",
"type": "crossval",
"classifier": "stree",
"dataset": "zoo",
"accuracy": "0.957524",
"norm": 1,
"stand": 0,
"parameters": "{\"C\": 0.1, \"max_iter\": 10000.0}",
"time_spent": "0.00556221",
"time_spent_std": "0.000230106",
"accuracy_std": "0.0454615",
"nodes": "13.04",
"leaves": "7.02",
"depth": "7.02"
}
]