Compare commits
47 Commits
643633e6dd
...
alphablock
Author | SHA1 | Date | |
---|---|---|---|
ba455bb934
|
|||
a65955248a
|
|||
84930b0537
|
|||
10c65f44a0
|
|||
6d112f01e7
|
|||
401296293b
|
|||
9566ae4cf6
|
|||
55187ee521
|
|||
68ea06d129
|
|||
6c1d1d0d32
|
|||
b0853d169b
|
|||
26f8e07774
|
|||
315dfb104f
|
|||
381f226d53
|
|||
ea13835701
|
|||
d75468cf78
|
|||
c58bd9d60d
|
|||
148a3b831a
|
|||
69063badbb
|
|||
6ae2b2182a
|
|||
4dbd76df55
|
|||
4545f76667
|
|||
8372987dae
|
|||
d72943c749
|
|||
800246acd2
|
|||
0ea967dd9d
|
|||
97abec8b69
|
|||
17c9522e77
|
|||
45af550cf9
|
|||
5d5f49777e
|
|||
540a8ea06d
|
|||
1924c4392b
|
|||
f2556a30af
|
|||
2f2ed00ca1
|
|||
28f6a0d7a7
|
|||
028522f180
|
|||
84adf13a79
|
|||
26dfe6d056
|
|||
3acc34e4c6
|
|||
8f92b74260
|
|||
3d900f8c81
|
|||
e628d80f4c
|
|||
0f06f8971e
|
|||
f800772149
|
|||
b8a8ddaf8c
|
|||
90555489ff
|
|||
080f3cee34
|
7
.gitmodules
vendored
7
.gitmodules
vendored
@@ -10,13 +10,12 @@
|
|||||||
[submodule "lib/libxlsxwriter"]
|
[submodule "lib/libxlsxwriter"]
|
||||||
path = lib/libxlsxwriter
|
path = lib/libxlsxwriter
|
||||||
url = https://github.com/jmcnamara/libxlsxwriter.git
|
url = https://github.com/jmcnamara/libxlsxwriter.git
|
||||||
[submodule "lib/mdlp"]
|
|
||||||
path = lib/mdlp
|
|
||||||
url = https://github.com/rmontanana/mdlp
|
|
||||||
update = merge
|
|
||||||
[submodule "lib/folding"]
|
[submodule "lib/folding"]
|
||||||
path = lib/folding
|
path = lib/folding
|
||||||
url = https://github.com/rmontanana/folding
|
url = https://github.com/rmontanana/folding
|
||||||
[submodule "lib/Files"]
|
[submodule "lib/Files"]
|
||||||
path = lib/Files
|
path = lib/Files
|
||||||
url = https://github.com/rmontanana/ArffFiles
|
url = https://github.com/rmontanana/ArffFiles
|
||||||
|
[submodule "lib/mdlp"]
|
||||||
|
path = lib/mdlp
|
||||||
|
url = https://github.com/rmontanana/mdlp
|
||||||
|
@@ -21,7 +21,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
|
|||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -O0 -g")
|
set(CMAKE_CXX_FLAGS_DEBUG " ${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage -O0 -g")
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
@@ -46,7 +46,7 @@ if(Boost_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
find_package(Python3 3.11...3.11.9 COMPONENTS Interpreter Development REQUIRED)
|
find_package(Python3 3.11 COMPONENTS Interpreter Development REQUIRED)
|
||||||
message("Python3_LIBRARIES=${Python3_LIBRARIES}")
|
message("Python3_LIBRARIES=${Python3_LIBRARIES}")
|
||||||
|
|
||||||
# CMakes modules
|
# CMakes modules
|
||||||
@@ -90,7 +90,7 @@ cmake_path(SET TEST_DATA_PATH "${CMAKE_CURRENT_SOURCE_DIR}/tests/data")
|
|||||||
configure_file(src/common/SourceData.h.in "${CMAKE_BINARY_DIR}/configured_files/include/SourceData.h")
|
configure_file(src/common/SourceData.h.in "${CMAKE_BINARY_DIR}/configured_files/include/SourceData.h")
|
||||||
add_subdirectory(config)
|
add_subdirectory(config)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(sample)
|
# add_subdirectory(sample)
|
||||||
file(GLOB Platform_SOURCES CONFIGURE_DEPENDS ${Platform_SOURCE_DIR}/src/*.cpp)
|
file(GLOB Platform_SOURCES CONFIGURE_DEPENDS ${Platform_SOURCE_DIR}/src/*.cpp)
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
|
7
Makefile
7
Makefile
@@ -6,7 +6,6 @@ f_release = build_release
|
|||||||
f_debug = build_debug
|
f_debug = build_debug
|
||||||
app_targets = b_best b_list b_main b_manage b_grid
|
app_targets = b_best b_list b_main b_manage b_grid
|
||||||
test_targets = unit_tests_platform
|
test_targets = unit_tests_platform
|
||||||
n_procs = -j 16
|
|
||||||
|
|
||||||
define ClearTests
|
define ClearTests
|
||||||
@for t in $(test_targets); do \
|
@for t in $(test_targets); do \
|
||||||
@@ -56,10 +55,10 @@ dependency: ## Create a dependency graph diagram of the project (build/dependenc
|
|||||||
cd $(f_debug) && cmake .. --graphviz=dependency.dot && dot -Tpng dependency.dot -o dependency.png
|
cd $(f_debug) && cmake .. --graphviz=dependency.dot && dot -Tpng dependency.dot -o dependency.png
|
||||||
|
|
||||||
buildd: ## Build the debug targets
|
buildd: ## Build the debug targets
|
||||||
cmake --build $(f_debug) -t $(app_targets) PlatformSample $(n_procs)
|
cmake --build $(f_debug) -t $(app_targets) PlatformSample --parallel
|
||||||
|
|
||||||
buildr: ## Build the release targets
|
buildr: ## Build the release targets
|
||||||
cmake --build $(f_release) -t $(app_targets) $(n_procs)
|
cmake --build $(f_release) -t $(app_targets) --parallel
|
||||||
|
|
||||||
clean: ## Clean the tests info
|
clean: ## Clean the tests info
|
||||||
@echo ">>> Cleaning Debug Platform tests...";
|
@echo ">>> Cleaning Debug Platform tests...";
|
||||||
@@ -87,7 +86,7 @@ opt = ""
|
|||||||
test: ## Run tests (opt="-s") to verbose output the tests, (opt="-c='Test Maximum Spanning Tree'") to run only that section
|
test: ## Run tests (opt="-s") to verbose output the tests, (opt="-c='Test Maximum Spanning Tree'") to run only that section
|
||||||
@echo ">>> Running Platform tests...";
|
@echo ">>> Running Platform tests...";
|
||||||
@$(MAKE) clean
|
@$(MAKE) clean
|
||||||
@cmake --build $(f_debug) -t $(test_targets) $(n_procs)
|
@cmake --build $(f_debug) -t $(test_targets) --parallel
|
||||||
@for t in $(test_targets); do \
|
@for t in $(test_targets); do \
|
||||||
if [ -f $(f_debug)/tests/$$t ]; then \
|
if [ -f $(f_debug)/tests/$$t ]; then \
|
||||||
cd $(f_debug)/tests ; \
|
cd $(f_debug)/tests ; \
|
||||||
|
11
README.md
11
README.md
@@ -20,11 +20,18 @@ In Linux sometimes the library libstdc++ is mistaken from the miniconda installa
|
|||||||
libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by b_xxxx)
|
libstdc++.so.6: version `GLIBCXX_3.4.32' not found (required by b_xxxx)
|
||||||
```
|
```
|
||||||
|
|
||||||
The solution is to erase the libstdc++ library from the miniconda installation:
|
The solution is to erase the libstdc++ library from the miniconda installation and no further compilation is needed.
|
||||||
|
|
||||||
### MPI
|
### MPI
|
||||||
|
|
||||||
In Linux just install openmpi & openmpi-devel packages. Only if cmake can't find openmpi installation (like in Oracle Linux) set the following variable:
|
In Linux just install openmpi & openmpi-devel packages.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source /etc/profile.d/modules.sh
|
||||||
|
module load mpi/openmpi-x86_64
|
||||||
|
```
|
||||||
|
|
||||||
|
If cmake can't find openmpi installation (like in Oracle Linux) set the following variable:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export MPI_HOME="/usr/lib64/openmpi"
|
export MPI_HOME="/usr/lib64/openmpi"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
configure_file(
|
configure_file(
|
||||||
"config.h.in"
|
"config.h.in"
|
||||||
"${CMAKE_BINARY_DIR}/configured_files/include/config.h" ESCAPE_QUOTES
|
"${CMAKE_BINARY_DIR}/configured_files/include/config_platform.h" ESCAPE_QUOTES
|
||||||
)
|
)
|
||||||
|
@@ -1,8 +1,3 @@
|
|||||||
[submodule "lib/mdlp"]
|
|
||||||
path = lib/mdlp
|
|
||||||
url = https://github.com/rmontanana/mdlp
|
|
||||||
main = main
|
|
||||||
update = merge
|
|
||||||
[submodule "lib/catch2"]
|
[submodule "lib/catch2"]
|
||||||
path = lib/catch2
|
path = lib/catch2
|
||||||
main = v2.x
|
main = v2.x
|
||||||
|
Submodule lib/Files updated: dbefa02d9c...a4329f5f9d
Submodule lib/argparse updated: e462ab980c...cbd9fd8ed6
Submodule lib/catch2 updated: 4e8d92bf02...0321d2fce3
2
lib/json
2
lib/json
Submodule lib/json updated: 8c391e04fe...620034ecec
Submodule lib/libxlsxwriter updated: f483e65f2e...8206bda64a
2
lib/mdlp
2
lib/mdlp
Submodule lib/mdlp updated: c4e6c041fe...cfb993f5ec
@@ -3,7 +3,7 @@ include_directories(
|
|||||||
${Platform_SOURCE_DIR}/src/main
|
${Platform_SOURCE_DIR}/src/main
|
||||||
${Python3_INCLUDE_DIRS}
|
${Python3_INCLUDE_DIRS}
|
||||||
${Platform_SOURCE_DIR}/lib/Files
|
${Platform_SOURCE_DIR}/lib/Files
|
||||||
${Platform_SOURCE_DIR}/lib/mdlp
|
${Platform_SOURCE_DIR}/lib/mdlp/src
|
||||||
${Platform_SOURCE_DIR}/lib/argparse/include
|
${Platform_SOURCE_DIR}/lib/argparse/include
|
||||||
${Platform_SOURCE_DIR}/lib/folding
|
${Platform_SOURCE_DIR}/lib/folding
|
||||||
${Platform_SOURCE_DIR}/lib/json/include
|
${Platform_SOURCE_DIR}/lib/json/include
|
||||||
@@ -12,4 +12,4 @@ include_directories(
|
|||||||
${Bayesnet_INCLUDE_DIRS}
|
${Bayesnet_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
add_executable(PlatformSample sample.cpp ${Platform_SOURCE_DIR}/src/main/Models.cpp)
|
add_executable(PlatformSample sample.cpp ${Platform_SOURCE_DIR}/src/main/Models.cpp)
|
||||||
target_link_libraries(PlatformSample "${PyClassifiers}" "${BayesNet}" mdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy)
|
target_link_libraries(PlatformSample "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy)
|
@@ -6,12 +6,12 @@
|
|||||||
#include <argparse/argparse.hpp>
|
#include <argparse/argparse.hpp>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <ArffFiles.hpp>
|
#include <ArffFiles.hpp>
|
||||||
#include <CPPFImdlp.h>
|
#include <fimdlp/CPPFImdlp.h>
|
||||||
#include <folding.hpp>
|
#include <folding.hpp>
|
||||||
#include <bayesnet/utils/BayesMetrics.h>
|
#include <bayesnet/utils/BayesMetrics.h>
|
||||||
#include "Models.h"
|
#include "Models.h"
|
||||||
#include "modelRegister.h"
|
#include "modelRegister.h"
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
const std::string PATH = { platform_data_path.begin(), platform_data_path.end() };
|
const std::string PATH = { platform_data_path.begin(), platform_data_path.end() };
|
||||||
|
|
||||||
@@ -161,7 +161,8 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
states[className] = std::vector<int>(maxes[className]);
|
states[className] = std::vector<int>(maxes[className]);
|
||||||
auto clf = platform::Models::instance()->create(model_name);
|
auto clf = platform::Models::instance()->create(model_name);
|
||||||
clf->fit(Xd, y, features, className, states);
|
bayesnet::Smoothing_t smoothing = bayesnet::Smoothing_t::ORIGINAL;
|
||||||
|
clf->fit(Xd, y, features, className, states, smoothing);
|
||||||
if (dump_cpt) {
|
if (dump_cpt) {
|
||||||
std::cout << "--- CPT Tables ---" << std::endl;
|
std::cout << "--- CPT Tables ---" << std::endl;
|
||||||
clf->dump_cpt();
|
clf->dump_cpt();
|
||||||
@@ -210,14 +211,14 @@ int main(int argc, char** argv)
|
|||||||
torch::Tensor ytraint = yt.index({ ttrain });
|
torch::Tensor ytraint = yt.index({ ttrain });
|
||||||
torch::Tensor Xtestt = torch::index_select(Xt, 1, ttest);
|
torch::Tensor Xtestt = torch::index_select(Xt, 1, ttest);
|
||||||
torch::Tensor ytestt = yt.index({ ttest });
|
torch::Tensor ytestt = yt.index({ ttest });
|
||||||
clf->fit(Xtraint, ytraint, features, className, states);
|
clf->fit(Xtraint, ytraint, features, className, states, smoothing);
|
||||||
auto temp = clf->predict(Xtraint);
|
auto temp = clf->predict(Xtraint);
|
||||||
score_train = clf->score(Xtraint, ytraint);
|
score_train = clf->score(Xtraint, ytraint);
|
||||||
score_test = clf->score(Xtestt, ytestt);
|
score_test = clf->score(Xtestt, ytestt);
|
||||||
} else {
|
} else {
|
||||||
auto [Xtrain, ytrain] = extract_indices(train, Xd, y);
|
auto [Xtrain, ytrain] = extract_indices(train, Xd, y);
|
||||||
auto [Xtest, ytest] = extract_indices(test, Xd, y);
|
auto [Xtest, ytest] = extract_indices(test, Xd, y);
|
||||||
clf->fit(Xtrain, ytrain, features, className, states);
|
clf->fit(Xtrain, ytrain, features, className, states, smoothing);
|
||||||
std::cout << "Nodes: " << clf->getNumberOfNodes() << std::endl;
|
std::cout << "Nodes: " << clf->getNumberOfNodes() << std::endl;
|
||||||
nodes += clf->getNumberOfNodes();
|
nodes += clf->getNumberOfNodes();
|
||||||
score_train = clf->score(Xtrain, ytrain);
|
score_train = clf->score(Xtrain, ytrain);
|
||||||
|
@@ -2,7 +2,7 @@ include_directories(
|
|||||||
## Libs
|
## Libs
|
||||||
${Platform_SOURCE_DIR}/lib/Files
|
${Platform_SOURCE_DIR}/lib/Files
|
||||||
${Platform_SOURCE_DIR}/lib/folding
|
${Platform_SOURCE_DIR}/lib/folding
|
||||||
${Platform_SOURCE_DIR}/lib/mdlp
|
${Platform_SOURCE_DIR}/lib/mdlp/src
|
||||||
${Platform_SOURCE_DIR}/lib/argparse/include
|
${Platform_SOURCE_DIR}/lib/argparse/include
|
||||||
${Platform_SOURCE_DIR}/lib/json/include
|
${Platform_SOURCE_DIR}/lib/json/include
|
||||||
${Platform_SOURCE_DIR}/lib/libxlsxwriter/include
|
${Platform_SOURCE_DIR}/lib/libxlsxwriter/include
|
||||||
@@ -20,13 +20,13 @@ include_directories(
|
|||||||
# b_best
|
# b_best
|
||||||
add_executable(
|
add_executable(
|
||||||
b_best commands/b_best.cpp best/Statistics.cpp
|
b_best commands/b_best.cpp best/Statistics.cpp
|
||||||
best/BestResultsExcel.cpp best/BestResults.cpp
|
best/BestResultsExcel.cpp best/BestResultsTex.cpp best/BestResultsMd.cpp best/BestResults.cpp
|
||||||
common/Datasets.cpp common/Dataset.cpp common/Discretization.cpp
|
common/Datasets.cpp common/Dataset.cpp common/Discretization.cpp
|
||||||
main/Models.cpp main/Scores.cpp
|
main/Models.cpp main/Scores.cpp
|
||||||
reports/ReportExcel.cpp reports/ReportBase.cpp reports/ExcelFile.cpp
|
reports/ReportExcel.cpp reports/ReportBase.cpp reports/ExcelFile.cpp
|
||||||
results/Result.cpp
|
results/Result.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(b_best Boost::boost "${PyClassifiers}" "${BayesNet}" mdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}")
|
target_link_libraries(b_best Boost::boost "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}")
|
||||||
|
|
||||||
# b_grid
|
# b_grid
|
||||||
set(grid_sources GridSearch.cpp GridData.cpp)
|
set(grid_sources GridSearch.cpp GridData.cpp)
|
||||||
@@ -35,7 +35,7 @@ add_executable(b_grid commands/b_grid.cpp ${grid_sources}
|
|||||||
common/Datasets.cpp common/Dataset.cpp common/Discretization.cpp
|
common/Datasets.cpp common/Dataset.cpp common/Discretization.cpp
|
||||||
main/HyperParameters.cpp main/Models.cpp
|
main/HyperParameters.cpp main/Models.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(b_grid ${MPI_CXX_LIBRARIES} "${PyClassifiers}" "${BayesNet}" mdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy)
|
target_link_libraries(b_grid ${MPI_CXX_LIBRARIES} "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy)
|
||||||
|
|
||||||
# b_list
|
# b_list
|
||||||
add_executable(b_list commands/b_list.cpp
|
add_executable(b_list commands/b_list.cpp
|
||||||
@@ -44,7 +44,7 @@ add_executable(b_list commands/b_list.cpp
|
|||||||
reports/ReportExcel.cpp reports/ExcelFile.cpp reports/ReportBase.cpp reports/DatasetsExcel.cpp reports/DatasetsConsole.cpp reports/ReportsPaged.cpp
|
reports/ReportExcel.cpp reports/ExcelFile.cpp reports/ReportBase.cpp reports/DatasetsExcel.cpp reports/DatasetsConsole.cpp reports/ReportsPaged.cpp
|
||||||
results/Result.cpp results/ResultsDatasetExcel.cpp results/ResultsDataset.cpp results/ResultsDatasetConsole.cpp
|
results/Result.cpp results/ResultsDatasetExcel.cpp results/ResultsDataset.cpp results/ResultsDatasetConsole.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(b_list "${PyClassifiers}" "${BayesNet}" mdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}")
|
target_link_libraries(b_list "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy "${XLSXWRITER_LIB}")
|
||||||
|
|
||||||
# b_main
|
# b_main
|
||||||
set(main_sources Experiment.cpp Models.cpp HyperParameters.cpp Scores.cpp)
|
set(main_sources Experiment.cpp Models.cpp HyperParameters.cpp Scores.cpp)
|
||||||
@@ -54,10 +54,10 @@ add_executable(b_main commands/b_main.cpp ${main_sources}
|
|||||||
reports/ReportConsole.cpp reports/ReportBase.cpp
|
reports/ReportConsole.cpp reports/ReportBase.cpp
|
||||||
results/Result.cpp
|
results/Result.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(b_main "${PyClassifiers}" "${BayesNet}" mdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy)
|
target_link_libraries(b_main "${PyClassifiers}" "${BayesNet}" fimdlp ${Python3_LIBRARIES} "${TORCH_LIBRARIES}" ${LIBTORCH_PYTHON} Boost::python Boost::numpy)
|
||||||
|
|
||||||
# b_manage
|
# b_manage
|
||||||
set(manage_sources ManageScreen.cpp CommandParser.cpp ResultsManager.cpp)
|
set(manage_sources ManageScreen.cpp OptionsMenu.cpp ResultsManager.cpp)
|
||||||
list(TRANSFORM manage_sources PREPEND manage/)
|
list(TRANSFORM manage_sources PREPEND manage/)
|
||||||
add_executable(
|
add_executable(
|
||||||
b_manage commands/b_manage.cpp ${manage_sources}
|
b_manage commands/b_manage.cpp ${manage_sources}
|
||||||
@@ -66,4 +66,4 @@ add_executable(
|
|||||||
results/Result.cpp results/ResultsDataset.cpp results/ResultsDatasetConsole.cpp
|
results/Result.cpp results/ResultsDataset.cpp results/ResultsDatasetConsole.cpp
|
||||||
main/Scores.cpp
|
main/Scores.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(b_manage "${TORCH_LIBRARIES}" "${XLSXWRITER_LIB}" mdlp "${BayesNet}")
|
target_link_libraries(b_manage "${TORCH_LIBRARIES}" "${XLSXWRITER_LIB}" fimdlp "${BayesNet}")
|
||||||
|
@@ -6,8 +6,12 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "common/Colors.h"
|
#include "common/Colors.h"
|
||||||
#include "common/CLocale.h"
|
#include "common/CLocale.h"
|
||||||
|
#include "common/Paths.h"
|
||||||
|
#include "common/Utils.h" // compute_std
|
||||||
#include "results/Result.h"
|
#include "results/Result.h"
|
||||||
#include "BestResultsExcel.h"
|
#include "BestResultsExcel.h"
|
||||||
|
#include "BestResultsTex.h"
|
||||||
|
#include "BestResultsMd.h"
|
||||||
#include "best/Statistics.h"
|
#include "best/Statistics.h"
|
||||||
#include "BestResults.h"
|
#include "BestResults.h"
|
||||||
|
|
||||||
@@ -51,7 +55,7 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (update) {
|
if (update) {
|
||||||
bests[datasetName] = { item.at("score").get<double>(), item.at("hyperparameters"), file };
|
bests[datasetName] = { item.at("score").get<double>(), item.at("hyperparameters"), file, item.at("score_std").get<double>() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,16 +63,12 @@ namespace platform {
|
|||||||
std::cerr << Colors::MAGENTA() << "No results found for model " << model << " and score " << score << Colors::RESET() << std::endl;
|
std::cerr << Colors::MAGENTA() << "No results found for model " << model << " and score " << score << Colors::RESET() << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
std::string bestFileName = path + bestResultFile();
|
std::string bestFileName = path + Paths::bestResultsFile(score, model);
|
||||||
std::ofstream file(bestFileName);
|
std::ofstream file(bestFileName);
|
||||||
file << bests;
|
file << bests;
|
||||||
file.close();
|
file.close();
|
||||||
return bestFileName;
|
return bestFileName;
|
||||||
}
|
}
|
||||||
std::string BestResults::bestResultFile()
|
|
||||||
{
|
|
||||||
return "best_results_" + score + "_" + model + ".json";
|
|
||||||
}
|
|
||||||
std::pair<std::string, std::string> getModelScore(std::string name)
|
std::pair<std::string, std::string> getModelScore(std::string name)
|
||||||
{
|
{
|
||||||
// results_accuracy_BoostAODE_MacBookpro16_2023-09-06_12:27:00_1.json
|
// results_accuracy_BoostAODE_MacBookpro16_2023-09-06_12:27:00_1.json
|
||||||
@@ -150,7 +150,7 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
void BestResults::listFile()
|
void BestResults::listFile()
|
||||||
{
|
{
|
||||||
std::string bestFileName = path + bestResultFile();
|
std::string bestFileName = path + Paths::bestResultsFile(score, model);
|
||||||
if (FILE* fileTest = fopen(bestFileName.c_str(), "r")) {
|
if (FILE* fileTest = fopen(bestFileName.c_str(), "r")) {
|
||||||
fclose(fileTest);
|
fclose(fileTest);
|
||||||
} else {
|
} else {
|
||||||
@@ -196,7 +196,7 @@ namespace platform {
|
|||||||
auto maxDate = std::filesystem::file_time_type::max();
|
auto maxDate = std::filesystem::file_time_type::max();
|
||||||
for (const auto& model : models) {
|
for (const auto& model : models) {
|
||||||
this->model = model;
|
this->model = model;
|
||||||
std::string bestFileName = path + bestResultFile();
|
std::string bestFileName = path + Paths::bestResultsFile(score, model);
|
||||||
if (FILE* fileTest = fopen(bestFileName.c_str(), "r")) {
|
if (FILE* fileTest = fopen(bestFileName.c_str(), "r")) {
|
||||||
fclose(fileTest);
|
fclose(fileTest);
|
||||||
} else {
|
} else {
|
||||||
@@ -213,13 +213,20 @@ namespace platform {
|
|||||||
table["dateTable"] = ftime_to_string(maxDate);
|
table["dateTable"] = ftime_to_string(maxDate);
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
void BestResults::printTableResults(std::vector<std::string> models, json table)
|
|
||||||
|
void BestResults::printTableResults(std::vector<std::string> models, json table, bool tex)
|
||||||
{
|
{
|
||||||
std::stringstream oss;
|
std::stringstream oss;
|
||||||
oss << Colors::GREEN() << "Best results for " << score << " as of " << table.at("dateTable").get<std::string>() << std::endl;
|
oss << Colors::GREEN() << "Best results for " << score << " as of " << table.at("dateTable").get<std::string>() << std::endl;
|
||||||
std::cout << oss.str();
|
std::cout << oss.str();
|
||||||
std::cout << std::string(oss.str().size() - 8, '-') << std::endl;
|
std::cout << std::string(oss.str().size() - 8, '-') << std::endl;
|
||||||
std::cout << Colors::GREEN() << " # " << std::setw(maxDatasetName + 1) << std::left << std::string("Dataset");
|
std::cout << Colors::GREEN() << " # " << std::setw(maxDatasetName + 1) << std::left << std::string("Dataset");
|
||||||
|
auto bestResultsTex = BestResultsTex();
|
||||||
|
auto bestResultsMd = BestResultsMd();
|
||||||
|
if (tex) {
|
||||||
|
bestResultsTex.results_header(models, table.at("dateTable").get<std::string>());
|
||||||
|
bestResultsMd.results_header(models, table.at("dateTable").get<std::string>());
|
||||||
|
}
|
||||||
for (const auto& model : models) {
|
for (const auto& model : models) {
|
||||||
std::cout << std::setw(maxModelName) << std::left << model << " ";
|
std::cout << std::setw(maxModelName) << std::left << model << " ";
|
||||||
}
|
}
|
||||||
@@ -230,12 +237,13 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
std::map<std::string, double> totals;
|
std::map<std::string, std::vector<double>> totals;
|
||||||
int nDatasets = table.begin().value().size();
|
int nDatasets = table.begin().value().size();
|
||||||
for (const auto& model : models) {
|
|
||||||
totals[model] = 0.0;
|
|
||||||
}
|
|
||||||
auto datasets = getDatasets(table.begin().value());
|
auto datasets = getDatasets(table.begin().value());
|
||||||
|
if (tex) {
|
||||||
|
bestResultsTex.results_body(datasets, table);
|
||||||
|
bestResultsMd.results_body(datasets, table);
|
||||||
|
}
|
||||||
for (auto const& dataset_ : datasets) {
|
for (auto const& dataset_ : datasets) {
|
||||||
auto color = (i % 2) ? Colors::BLUE() : Colors::CYAN();
|
auto color = (i % 2) ? Colors::BLUE() : Colors::CYAN();
|
||||||
std::cout << color << std::setw(3) << std::fixed << std::right << i++ << " ";
|
std::cout << color << std::setw(3) << std::fixed << std::right << i++ << " ";
|
||||||
@@ -270,7 +278,7 @@ namespace platform {
|
|||||||
if (value == -1) {
|
if (value == -1) {
|
||||||
std::cout << Colors::YELLOW() << std::setw(maxModelName) << std::right << "N/A" << " ";
|
std::cout << Colors::YELLOW() << std::setw(maxModelName) << std::right << "N/A" << " ";
|
||||||
} else {
|
} else {
|
||||||
totals[model] += value;
|
totals[model].push_back(value);
|
||||||
std::cout << efectiveColor << std::setw(maxModelName) << std::setprecision(maxModelName - 2) << std::fixed << value << " ";
|
std::cout << efectiveColor << std::setw(maxModelName) << std::setprecision(maxModelName - 2) << std::fixed << value << " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,19 +289,26 @@ namespace platform {
|
|||||||
std::cout << std::string(maxModelName, '=') << " ";
|
std::cout << std::string(maxModelName, '=') << " ";
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << Colors::GREEN() << " Totals" << std::string(maxDatasetName - 6, '.') << " ";
|
std::cout << Colors::GREEN() << " Average" << std::string(maxDatasetName - 7, '.') << " ";
|
||||||
double max_value = 0.0;
|
double max_value = 0.0;
|
||||||
|
std::string best_model = "";
|
||||||
for (const auto& total : totals) {
|
for (const auto& total : totals) {
|
||||||
if (total.second > max_value) {
|
auto actual = std::reduce(total.second.begin(), total.second.end());
|
||||||
max_value = total.second;
|
if (actual > max_value) {
|
||||||
|
max_value = actual;
|
||||||
|
best_model = total.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tex) {
|
||||||
|
bestResultsTex.results_footer(totals, best_model);
|
||||||
|
bestResultsMd.results_footer(totals, best_model);
|
||||||
|
}
|
||||||
for (const auto& model : models) {
|
for (const auto& model : models) {
|
||||||
std::string efectiveColor = Colors::GREEN();
|
std::string efectiveColor = model == best_model ? Colors::RED() : Colors::GREEN();
|
||||||
if (totals[model] == max_value) {
|
double value = std::reduce(totals[model].begin(), totals[model].end()) / nDatasets;
|
||||||
efectiveColor = Colors::RED();
|
double std_value = compute_std(totals[model], value);
|
||||||
}
|
std::cout << efectiveColor << std::right << std::setw(maxModelName) << std::setprecision(maxModelName - 4) << std::fixed << value << " ";
|
||||||
std::cout << efectiveColor << std::right << std::setw(maxModelName) << std::setprecision(maxModelName - 4) << std::fixed << totals[model] << " ";
|
|
||||||
}
|
}
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
@@ -306,26 +321,34 @@ namespace platform {
|
|||||||
json table = buildTableResults(models);
|
json table = buildTableResults(models);
|
||||||
std::vector<std::string> datasets = getDatasets(table.begin().value());
|
std::vector<std::string> datasets = getDatasets(table.begin().value());
|
||||||
BestResultsExcel excel_report(score, datasets);
|
BestResultsExcel excel_report(score, datasets);
|
||||||
excel_report.reportSingle(model, path + bestResultFile());
|
excel_report.reportSingle(model, path + Paths::bestResultsFile(score, model));
|
||||||
messageExcelFile(excel_report.getFileName());
|
messageOutputFile("Excel", excel_report.getFileName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void BestResults::reportAll(bool excel)
|
void BestResults::reportAll(bool excel, bool tex)
|
||||||
{
|
{
|
||||||
auto models = getModels();
|
auto models = getModels();
|
||||||
// Build the table of results
|
// Build the table of results
|
||||||
json table = buildTableResults(models);
|
json table = buildTableResults(models);
|
||||||
std::vector<std::string> datasets = getDatasets(table.begin().value());
|
std::vector<std::string> datasets = getDatasets(table.begin().value());
|
||||||
// Print the table of results
|
// Print the table of results
|
||||||
printTableResults(models, table);
|
printTableResults(models, table, tex);
|
||||||
// Compute the Friedman test
|
// Compute the Friedman test
|
||||||
std::map<std::string, std::map<std::string, float>> ranksModels;
|
std::map<std::string, std::map<std::string, float>> ranksModels;
|
||||||
if (friedman) {
|
if (friedman) {
|
||||||
Statistics stats(models, datasets, table, significance);
|
Statistics stats(models, datasets, table, significance);
|
||||||
auto result = stats.friedmanTest();
|
auto result = stats.friedmanTest();
|
||||||
stats.postHocHolmTest(result);
|
stats.postHocHolmTest(result, tex);
|
||||||
ranksModels = stats.getRanks();
|
ranksModels = stats.getRanks();
|
||||||
}
|
}
|
||||||
|
if (tex) {
|
||||||
|
messageOutputFile("TeX", Paths::tex() + Paths::tex_output());
|
||||||
|
messageOutputFile("MarkDown", Paths::tex() + Paths::md_output());
|
||||||
|
if (friedman) {
|
||||||
|
messageOutputFile("TeX", Paths::tex() + Paths::tex_post_hoc());
|
||||||
|
messageOutputFile("MarkDown", Paths::tex() + Paths::md_post_hoc());
|
||||||
|
}
|
||||||
|
}
|
||||||
if (excel) {
|
if (excel) {
|
||||||
BestResultsExcel excel(score, datasets);
|
BestResultsExcel excel(score, datasets);
|
||||||
excel.reportAll(models, table, ranksModels, friedman, significance);
|
excel.reportAll(models, table, ranksModels, friedman, significance);
|
||||||
@@ -346,13 +369,14 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
model = models.at(idx);
|
model = models.at(idx);
|
||||||
excel.reportSingle(model, path + bestResultFile());
|
excel.reportSingle(model, path + Paths::bestResultsFile(score, model));
|
||||||
}
|
}
|
||||||
messageExcelFile(excel.getFileName());
|
messageOutputFile("Excel", excel.getFileName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void BestResults::messageExcelFile(const std::string& fileName)
|
void BestResults::messageOutputFile(const std::string& title, const std::string& fileName)
|
||||||
{
|
{
|
||||||
std::cout << Colors::YELLOW() << "** Excel file generated: " << fileName << Colors::RESET() << std::endl;
|
std::cout << Colors::YELLOW() << "** " << std::setw(5) << std::left << title
|
||||||
|
<< " file generated: " << fileName << Colors::RESET() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -13,16 +13,15 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
std::string build();
|
std::string build();
|
||||||
void reportSingle(bool excel);
|
void reportSingle(bool excel);
|
||||||
void reportAll(bool excel);
|
void reportAll(bool excel, bool tex);
|
||||||
void buildAll();
|
void buildAll();
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> getModels();
|
std::vector<std::string> getModels();
|
||||||
std::vector<std::string> getDatasets(json table);
|
std::vector<std::string> getDatasets(json table);
|
||||||
std::vector<std::string> loadResultFiles();
|
std::vector<std::string> loadResultFiles();
|
||||||
void messageExcelFile(const std::string& fileName);
|
void messageOutputFile(const std::string& title, const std::string& fileName);
|
||||||
json buildTableResults(std::vector<std::string> models);
|
json buildTableResults(std::vector<std::string> models);
|
||||||
void printTableResults(std::vector<std::string> models, json table);
|
void printTableResults(std::vector<std::string> models, json table, bool tex);
|
||||||
std::string bestResultFile();
|
|
||||||
json loadFile(const std::string& fileName);
|
json loadFile(const std::string& fileName);
|
||||||
void listFile();
|
void listFile();
|
||||||
std::string path;
|
std::string path;
|
||||||
|
@@ -32,7 +32,7 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
BestResultsExcel::BestResultsExcel(const std::string& score, const std::vector<std::string>& datasets) : score(score), datasets(datasets)
|
BestResultsExcel::BestResultsExcel(const std::string& score, const std::vector<std::string>& datasets) : score(score), datasets(datasets)
|
||||||
{
|
{
|
||||||
file_name = "BestResults.xlsx";
|
file_name = Paths::bestResultsExcel(score);
|
||||||
workbook = workbook_new(getFileName().c_str());
|
workbook = workbook_new(getFileName().c_str());
|
||||||
setProperties("Best Results");
|
setProperties("Best Results");
|
||||||
int maxDatasetName = (*max_element(datasets.begin(), datasets.end(), [](const std::string& a, const std::string& b) { return a.size() < b.size(); })).size();
|
int maxDatasetName = (*max_element(datasets.begin(), datasets.end(), [](const std::string& a, const std::string& b) { return a.size() < b.size(); })).size();
|
||||||
@@ -68,7 +68,7 @@ namespace platform {
|
|||||||
// Body header
|
// Body header
|
||||||
row = 3;
|
row = 3;
|
||||||
int col = 1;
|
int col = 1;
|
||||||
writeString(row, 0, "Nº", "bodyHeader");
|
writeString(row, 0, "#", "bodyHeader");
|
||||||
writeString(row, 1, "Dataset", "bodyHeader");
|
writeString(row, 1, "Dataset", "bodyHeader");
|
||||||
writeString(row, 2, "Score", "bodyHeader");
|
writeString(row, 2, "Score", "bodyHeader");
|
||||||
writeString(row, 3, "File", "bodyHeader");
|
writeString(row, 3, "File", "bodyHeader");
|
||||||
@@ -184,7 +184,7 @@ namespace platform {
|
|||||||
// Body header
|
// Body header
|
||||||
row = 3;
|
row = 3;
|
||||||
int col = 1;
|
int col = 1;
|
||||||
writeString(row, 0, "Nº", "bodyHeader");
|
writeString(row, 0, "#", "bodyHeader");
|
||||||
writeString(row, 1, "Dataset", "bodyHeader");
|
writeString(row, 1, "Dataset", "bodyHeader");
|
||||||
for (const auto& model : models) {
|
for (const auto& model : models) {
|
||||||
writeString(row, ++col, model.c_str(), "bodyHeader");
|
writeString(row, ++col, model.c_str(), "bodyHeader");
|
||||||
|
103
src/best/BestResultsMd.cpp
Normal file
103
src/best/BestResultsMd.cpp
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "BestResultsMd.h"
|
||||||
|
#include "common/Utils.h" // compute_std
|
||||||
|
|
||||||
|
namespace platform {
|
||||||
|
using json = nlohmann::ordered_json;
|
||||||
|
void BestResultsMd::openMdFile(const std::string& name)
|
||||||
|
{
|
||||||
|
handler.open(name);
|
||||||
|
if (!handler.is_open()) {
|
||||||
|
std::cerr << "Error opening file " << name << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void BestResultsMd::results_header(const std::vector<std::string>& models, const std::string& date)
|
||||||
|
{
|
||||||
|
this->models = models;
|
||||||
|
auto file_name = Paths::tex() + Paths::md_output();
|
||||||
|
openMdFile(file_name);
|
||||||
|
handler << "<!-- This file has been generated by the platform program" << std::endl;
|
||||||
|
handler << " Date: " << date.c_str() << std::endl;
|
||||||
|
handler << "" << std::endl;
|
||||||
|
handler << " Table of results" << std::endl;
|
||||||
|
handler << "-->" << std::endl;
|
||||||
|
handler << "| # | Dataset |";
|
||||||
|
for (const auto& model : models) {
|
||||||
|
handler << " " << model.c_str() << " |";
|
||||||
|
}
|
||||||
|
handler << std::endl;
|
||||||
|
handler << "|--: | :--- |";
|
||||||
|
for (const auto& model : models) {
|
||||||
|
handler << " :---: |";
|
||||||
|
}
|
||||||
|
handler << std::endl;
|
||||||
|
}
|
||||||
|
void BestResultsMd::results_body(const std::vector<std::string>& datasets, json& table)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (auto const& dataset : datasets) {
|
||||||
|
// Find out max value for this dataset
|
||||||
|
double max_value = 0;
|
||||||
|
// Find out the max value for this dataset
|
||||||
|
for (const auto& model : models) {
|
||||||
|
double value;
|
||||||
|
try {
|
||||||
|
value = table[model].at(dataset).at(0).get<double>();
|
||||||
|
}
|
||||||
|
catch (nlohmann::json_abi_v3_11_3::detail::out_of_range err) {
|
||||||
|
value = -1.0;
|
||||||
|
}
|
||||||
|
if (value > max_value) {
|
||||||
|
max_value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler << "| " << ++i << " | " << dataset.c_str() << " | ";
|
||||||
|
for (const auto& model : models) {
|
||||||
|
double value = table[model].at(dataset).at(0).get<double>();
|
||||||
|
double std_value = table[model].at(dataset).at(3).get<double>();
|
||||||
|
const char* bold = value == max_value ? "**" : "";
|
||||||
|
handler << bold << std::setprecision(4) << std::fixed << value << "±" << std::setprecision(3) << std_value << bold << " | ";
|
||||||
|
}
|
||||||
|
handler << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void BestResultsMd::results_footer(const std::map<std::string, std::vector<double>>& totals, const std::string& best_model)
|
||||||
|
{
|
||||||
|
handler << "| | **Average Score** | ";
|
||||||
|
int nDatasets = totals.begin()->second.size();
|
||||||
|
for (const auto& model : models) {
|
||||||
|
double value = std::reduce(totals.at(model).begin(), totals.at(model).end()) / nDatasets;
|
||||||
|
double std_value = compute_std(totals.at(model), value);
|
||||||
|
const char* bold = model == best_model ? "**" : "";
|
||||||
|
handler << bold << std::setprecision(4) << std::fixed << value << "±" << std::setprecision(3) << std::fixed << std_value << bold << " | ";
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.close();
|
||||||
|
}
|
||||||
|
void BestResultsMd::holm_test(struct HolmResult& holmResult, const std::string& date)
|
||||||
|
{
|
||||||
|
auto file_name = Paths::tex() + Paths::md_post_hoc();
|
||||||
|
openMdFile(file_name);
|
||||||
|
handler << "<!-- This file has been generated by the platform program" << std::endl;
|
||||||
|
handler << " Date: " << date.c_str() << std::endl;
|
||||||
|
handler << std::endl;
|
||||||
|
handler << " Post-hoc handler test" << std::endl;
|
||||||
|
handler << "-->" << std::endl;
|
||||||
|
handler << "Post-hoc Holm test: H<sub>0</sub>: There is no significant differences between the control model and the other models." << std::endl << std::endl;
|
||||||
|
handler << "| classifier | pvalue | rank | win | tie | loss | H<sub>0</sub> |" << std::endl;
|
||||||
|
handler << "| :-- | --: | --: | --:| --: | --: | :--: |" << std::endl;
|
||||||
|
for (auto const& line : holmResult.holmLines) {
|
||||||
|
auto textStatus = !line.reject ? "**" : " ";
|
||||||
|
if (line.model == holmResult.model) {
|
||||||
|
handler << "| " << line.model << " | - | " << std::fixed << std::setprecision(2) << line.rank << " | - | - | - |" << std::endl;
|
||||||
|
} else {
|
||||||
|
handler << "| " << line.model << " | " << textStatus << std::scientific << std::setprecision(4) << line.pvalue << textStatus << " |";
|
||||||
|
handler << std::fixed << std::setprecision(2) << line.rank << " | " << line.wtl.win << " | " << line.wtl.tie << " | " << line.wtl.loss << " |";
|
||||||
|
handler << (line.reject ? "rejected" : "**accepted**") << " |" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler << std::endl;
|
||||||
|
handler.close();
|
||||||
|
}
|
||||||
|
}
|
24
src/best/BestResultsMd.h
Normal file
24
src/best/BestResultsMd.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef BEST_RESULTS_MD_H
|
||||||
|
#define BEST_RESULTS_MD_H
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include "common/Paths.h"
|
||||||
|
#include "Statistics.h"
|
||||||
|
namespace platform {
|
||||||
|
using json = nlohmann::ordered_json;
|
||||||
|
class BestResultsMd {
|
||||||
|
public:
|
||||||
|
BestResultsMd() = default;
|
||||||
|
~BestResultsMd() = default;
|
||||||
|
void results_header(const std::vector<std::string>& models, const std::string& date);
|
||||||
|
void results_body(const std::vector<std::string>& datasets, json& table);
|
||||||
|
void results_footer(const std::map<std::string, std::vector<double>>& totals, const std::string& best_model);
|
||||||
|
void holm_test(struct HolmResult& holmResult, const std::string& date);
|
||||||
|
private:
|
||||||
|
void openMdFile(const std::string& name);
|
||||||
|
std::ofstream handler;
|
||||||
|
std::vector<std::string> models;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
117
src/best/BestResultsTex.cpp
Normal file
117
src/best/BestResultsTex.cpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "BestResultsTex.h"
|
||||||
|
#include "common/Utils.h" // compute_std
|
||||||
|
|
||||||
|
namespace platform {
|
||||||
|
using json = nlohmann::ordered_json;
|
||||||
|
void BestResultsTex::openTexFile(const std::string& name)
|
||||||
|
{
|
||||||
|
handler.open(name);
|
||||||
|
if (!handler.is_open()) {
|
||||||
|
std::cerr << "Error opening file " << name << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void BestResultsTex::results_header(const std::vector<std::string>& models, const std::string& date)
|
||||||
|
{
|
||||||
|
this->models = models;
|
||||||
|
auto file_name = Paths::tex() + Paths::tex_output();
|
||||||
|
openTexFile(file_name);
|
||||||
|
handler << "%% This file has been generated by the platform program" << std::endl;
|
||||||
|
handler << "%% Date: " << date.c_str() << std::endl;
|
||||||
|
handler << "%%" << std::endl;
|
||||||
|
handler << "%% Table of results" << std::endl;
|
||||||
|
handler << "%%" << std::endl;
|
||||||
|
handler << "\\begin{table}[htbp] " << std::endl;
|
||||||
|
handler << "\\centering " << std::endl;
|
||||||
|
handler << "\\tiny " << std::endl;
|
||||||
|
handler << "\\renewcommand{\\arraystretch }{1.2} " << std::endl;
|
||||||
|
handler << "\\renewcommand{\\tabcolsep }{0.07cm} " << std::endl;
|
||||||
|
handler << "\\caption{Accuracy results(mean $\\pm$ std) for all the algorithms and datasets} " << std::endl;
|
||||||
|
handler << "\\label{tab:results_accuracy}" << std::endl;
|
||||||
|
handler << "\\begin{tabular} {{r" << std::string(models.size(), 'c').c_str() << "}}" << std::endl;
|
||||||
|
handler << "\\hline " << std::endl;
|
||||||
|
handler << "" << std::endl;
|
||||||
|
for (const auto& model : models) {
|
||||||
|
handler << "& " << model.c_str();
|
||||||
|
}
|
||||||
|
handler << "\\\\" << std::endl;
|
||||||
|
handler << "\\hline" << std::endl;
|
||||||
|
}
|
||||||
|
void BestResultsTex::results_body(const std::vector<std::string>& datasets, json& table)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (auto const& dataset : datasets) {
|
||||||
|
// Find out max value for this dataset
|
||||||
|
double max_value = 0;
|
||||||
|
// Find out the max value for this dataset
|
||||||
|
for (const auto& model : models) {
|
||||||
|
double value;
|
||||||
|
try {
|
||||||
|
value = table[model].at(dataset).at(0).get<double>();
|
||||||
|
}
|
||||||
|
catch (nlohmann::json_abi_v3_11_3::detail::out_of_range err) {
|
||||||
|
value = -1.0;
|
||||||
|
}
|
||||||
|
if (value > max_value) {
|
||||||
|
max_value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler << ++i << " ";
|
||||||
|
for (const auto& model : models) {
|
||||||
|
double value = table[model].at(dataset).at(0).get<double>();
|
||||||
|
double std_value = table[model].at(dataset).at(3).get<double>();
|
||||||
|
const char* bold = value == max_value ? "\\bfseries" : "";
|
||||||
|
handler << "& " << bold << std::setprecision(4) << std::fixed << value << "$\\pm$" << std::setprecision(3) << std_value;
|
||||||
|
}
|
||||||
|
handler << "\\\\" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void BestResultsTex::results_footer(const std::map<std::string, std::vector<double>>& totals, const std::string& best_model)
|
||||||
|
{
|
||||||
|
handler << "\\hline" << std::endl;
|
||||||
|
handler << "Average ";
|
||||||
|
int nDatasets = totals.begin()->second.size();
|
||||||
|
for (const auto& model : models) {
|
||||||
|
double value = std::reduce(totals.at(model).begin(), totals.at(model).end()) / nDatasets;
|
||||||
|
double std_value = compute_std(totals.at(model), value);
|
||||||
|
const char* bold = model == best_model ? "\\bfseries" : "";
|
||||||
|
handler << "& " << bold << std::setprecision(4) << std::fixed << value << "$\\pm$" << std::setprecision(3) << std::fixed << std_value;
|
||||||
|
}
|
||||||
|
handler << "\\\\" << std::endl;
|
||||||
|
handler << "\\hline " << std::endl;
|
||||||
|
handler << "\\end{tabular}" << std::endl;
|
||||||
|
handler << "\\end{table}" << std::endl;
|
||||||
|
handler.close();
|
||||||
|
}
|
||||||
|
void BestResultsTex::holm_test(struct HolmResult& holmResult, const std::string& date)
|
||||||
|
{
|
||||||
|
auto file_name = Paths::tex() + Paths::tex_post_hoc();
|
||||||
|
openTexFile(file_name);
|
||||||
|
handler << "%% This file has been generated by the platform program" << std::endl;
|
||||||
|
handler << "%% Date: " << date.c_str() << std::endl;
|
||||||
|
handler << "%%" << std::endl;
|
||||||
|
handler << "%% Post-hoc handler test" << std::endl;
|
||||||
|
handler << "%%" << std::endl;
|
||||||
|
handler << "\\begin{table}[htbp]" << std::endl;
|
||||||
|
handler << "\\centering" << std::endl;
|
||||||
|
handler << "\\caption{Results of the post-hoc test for the mean accuracy of the algorithms.}\\label{tab:tests}" << std::endl;
|
||||||
|
handler << "\\begin{tabular}{lrrrrr}" << std::endl;
|
||||||
|
handler << "\\hline" << std::endl;
|
||||||
|
handler << "classifier & pvalue & rank & win & tie & loss\\\\" << std::endl;
|
||||||
|
handler << "\\hline" << std::endl;
|
||||||
|
for (auto const& line : holmResult.holmLines) {
|
||||||
|
auto textStatus = !line.reject ? "\\bf " : " ";
|
||||||
|
if (line.model == holmResult.model) {
|
||||||
|
handler << line.model << " & - & " << std::fixed << std::setprecision(2) << line.rank << " & - & - & - \\\\" << std::endl;
|
||||||
|
} else {
|
||||||
|
handler << line.model << " & " << textStatus << std::scientific << std::setprecision(4) << line.pvalue << " & ";
|
||||||
|
handler << std::fixed << std::setprecision(2) << line.rank << " & " << line.wtl.win << " & " << line.wtl.tie << " & " << line.wtl.loss << "\\\\" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handler << "\\hline " << std::endl;
|
||||||
|
handler << "\\end{tabular}" << std::endl;
|
||||||
|
handler << "\\end{table}" << std::endl;
|
||||||
|
handler.close();
|
||||||
|
}
|
||||||
|
}
|
24
src/best/BestResultsTex.h
Normal file
24
src/best/BestResultsTex.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef BEST_RESULTS_TEX_H
|
||||||
|
#define BEST_RESULTS_TEX_H
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include "common/Paths.h"
|
||||||
|
#include "Statistics.h"
|
||||||
|
namespace platform {
|
||||||
|
using json = nlohmann::ordered_json;
|
||||||
|
class BestResultsTex {
|
||||||
|
public:
|
||||||
|
BestResultsTex() = default;
|
||||||
|
~BestResultsTex() = default;
|
||||||
|
void results_header(const std::vector<std::string>& models, const std::string& date);
|
||||||
|
void results_body(const std::vector<std::string>& datasets, json& table);
|
||||||
|
void results_footer(const std::map<std::string, std::vector<double>>& totals, const std::string& best_model);
|
||||||
|
void holm_test(struct HolmResult& holmResult, const std::string& date);
|
||||||
|
private:
|
||||||
|
void openTexFile(const std::string& name);
|
||||||
|
std::ofstream handler;
|
||||||
|
std::vector<std::string> models;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
@@ -4,6 +4,8 @@
|
|||||||
#include "common/Colors.h"
|
#include "common/Colors.h"
|
||||||
#include "common/Symbols.h"
|
#include "common/Symbols.h"
|
||||||
#include "common/CLocale.h"
|
#include "common/CLocale.h"
|
||||||
|
#include "BestResultsTex.h"
|
||||||
|
#include "BestResultsMd.h"
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -113,7 +115,7 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Statistics::postHocHolmTest(bool friedmanResult)
|
void Statistics::postHocHolmTest(bool friedmanResult, bool tex)
|
||||||
{
|
{
|
||||||
if (!fitted) {
|
if (!fitted) {
|
||||||
fit();
|
fit();
|
||||||
@@ -195,6 +197,12 @@ namespace platform {
|
|||||||
if (output) {
|
if (output) {
|
||||||
std::cout << oss.str();
|
std::cout << oss.str();
|
||||||
}
|
}
|
||||||
|
if (tex) {
|
||||||
|
BestResultsTex bestResultsTex;
|
||||||
|
BestResultsMd bestResultsMd;
|
||||||
|
bestResultsTex.holm_test(holmResult, get_date() + " " + get_time());
|
||||||
|
bestResultsMd.holm_test(holmResult, get_date() + " " + get_time());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bool Statistics::friedmanTest()
|
bool Statistics::friedmanTest()
|
||||||
{
|
{
|
||||||
|
@@ -34,7 +34,7 @@ namespace platform {
|
|||||||
public:
|
public:
|
||||||
Statistics(const std::vector<std::string>& models, const std::vector<std::string>& datasets, const json& data, double significance = 0.05, bool output = true);
|
Statistics(const std::vector<std::string>& models, const std::vector<std::string>& datasets, const json& data, double significance = 0.05, bool output = true);
|
||||||
bool friedmanTest();
|
bool friedmanTest();
|
||||||
void postHocHolmTest(bool friedmanResult);
|
void postHocHolmTest(bool friedmanResult, bool tex=false);
|
||||||
FriedmanResult& getFriedmanResult();
|
FriedmanResult& getFriedmanResult();
|
||||||
HolmResult& getHolmResult();
|
HolmResult& getHolmResult();
|
||||||
std::map<std::string, std::map<std::string, float>>& getRanks();
|
std::map<std::string, std::map<std::string, float>>& getRanks();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include "common/Paths.h"
|
#include "common/Paths.h"
|
||||||
#include "common/Colors.h"
|
#include "common/Colors.h"
|
||||||
#include "best/BestResults.h"
|
#include "best/BestResults.h"
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
void manageArguments(argparse::ArgumentParser& program)
|
void manageArguments(argparse::ArgumentParser& program)
|
||||||
{
|
{
|
||||||
@@ -16,6 +16,7 @@ void manageArguments(argparse::ArgumentParser& program)
|
|||||||
program.add_argument("-s", "--score").default_value("accuracy").help("Filter results of the score name supplied");
|
program.add_argument("-s", "--score").default_value("accuracy").help("Filter results of the score name supplied");
|
||||||
program.add_argument("--friedman").help("Friedman test").default_value(false).implicit_value(true);
|
program.add_argument("--friedman").help("Friedman test").default_value(false).implicit_value(true);
|
||||||
program.add_argument("--excel").help("Output to excel").default_value(false).implicit_value(true);
|
program.add_argument("--excel").help("Output to excel").default_value(false).implicit_value(true);
|
||||||
|
program.add_argument("--tex").help("Output result table to TeX file").default_value(false).implicit_value(true);
|
||||||
program.add_argument("--level").help("significance level").default_value(0.05).scan<'g', double>().action([](const std::string& value) {
|
program.add_argument("--level").help("significance level").default_value(0.05).scan<'g', double>().action([](const std::string& value) {
|
||||||
try {
|
try {
|
||||||
auto k = std::stod(value);
|
auto k = std::stod(value);
|
||||||
@@ -37,7 +38,7 @@ int main(int argc, char** argv)
|
|||||||
argparse::ArgumentParser program("b_best", { platform_project_version.begin(), platform_project_version.end() });
|
argparse::ArgumentParser program("b_best", { platform_project_version.begin(), platform_project_version.end() });
|
||||||
manageArguments(program);
|
manageArguments(program);
|
||||||
std::string model, dataset, score;
|
std::string model, dataset, score;
|
||||||
bool build, report, friedman, excel;
|
bool build, report, friedman, excel, tex;
|
||||||
double level;
|
double level;
|
||||||
try {
|
try {
|
||||||
program.parse_args(argc, argv);
|
program.parse_args(argc, argv);
|
||||||
@@ -46,6 +47,7 @@ int main(int argc, char** argv)
|
|||||||
score = program.get<std::string>("score");
|
score = program.get<std::string>("score");
|
||||||
friedman = program.get<bool>("friedman");
|
friedman = program.get<bool>("friedman");
|
||||||
excel = program.get<bool>("excel");
|
excel = program.get<bool>("excel");
|
||||||
|
tex = program.get<bool>("tex");
|
||||||
level = program.get<double>("level");
|
level = program.get<double>("level");
|
||||||
if (model == "" || score == "") {
|
if (model == "" || score == "") {
|
||||||
throw std::runtime_error("Model and score name must be supplied");
|
throw std::runtime_error("Model and score name must be supplied");
|
||||||
@@ -65,7 +67,7 @@ int main(int argc, char** argv)
|
|||||||
auto results = platform::BestResults(platform::Paths::results(), score, model, dataset, friedman, level);
|
auto results = platform::BestResults(platform::Paths::results(), score, model, dataset, friedman, level);
|
||||||
if (model == "any") {
|
if (model == "any") {
|
||||||
results.buildAll();
|
results.buildAll();
|
||||||
results.reportAll(excel);
|
results.reportAll(excel, tex);
|
||||||
} else {
|
} else {
|
||||||
std::string fileName = results.build();
|
std::string fileName = results.build();
|
||||||
std::cout << Colors::GREEN() << fileName << " created!" << Colors::RESET() << std::endl;
|
std::cout << Colors::GREEN() << fileName << " created!" << Colors::RESET() << std::endl;
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
#include "common/Colors.h"
|
#include "common/Colors.h"
|
||||||
#include "common/DotEnv.h"
|
#include "common/DotEnv.h"
|
||||||
#include "grid/GridSearch.h"
|
#include "grid/GridSearch.h"
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
using json = nlohmann::ordered_json;
|
using json = nlohmann::ordered_json;
|
||||||
const int MAXL = 133;
|
const int MAXL = 133;
|
||||||
@@ -93,8 +93,10 @@ void list_dump(std::string& model)
|
|||||||
if (item.first.size() > max_dataset) {
|
if (item.first.size() > max_dataset) {
|
||||||
max_dataset = item.first.size();
|
max_dataset = item.first.size();
|
||||||
}
|
}
|
||||||
if (item.second.dump().size() > max_hyper) {
|
for (auto const& [key, value] : item.second.items()) {
|
||||||
max_hyper = item.second.dump().size();
|
if (value.dump().size() > max_hyper) {
|
||||||
|
max_hyper = value.dump().size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << Colors::GREEN() << left << " # " << left << setw(max_dataset) << "Dataset" << " #Com. "
|
std::cout << Colors::GREEN() << left << " # " << left << setw(max_dataset) << "Dataset" << " #Com. "
|
||||||
@@ -106,7 +108,12 @@ void list_dump(std::string& model)
|
|||||||
std::cout << color;
|
std::cout << color;
|
||||||
auto num_combinations = data.getNumCombinations(item.first);
|
auto num_combinations = data.getNumCombinations(item.first);
|
||||||
std::cout << setw(3) << fixed << right << ++index << left << " " << setw(max_dataset) << item.first
|
std::cout << setw(3) << fixed << right << ++index << left << " " << setw(max_dataset) << item.first
|
||||||
<< " " << setw(5) << right << num_combinations << " " << setw(max_hyper) << left << item.second.dump() << std::endl;
|
<< " " << setw(5) << right << num_combinations << " ";
|
||||||
|
std::string prefix = "";
|
||||||
|
for (auto const& [key, value] : item.second.items()) {
|
||||||
|
std::cout << prefix << setw(max_hyper) << std::left << value.dump() << std::endl;
|
||||||
|
prefix = string(11 + max_dataset, ' ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
std::cout << Colors::RESET() << std::endl;
|
std::cout << Colors::RESET() << std::endl;
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
#include "results/ResultsDatasetConsole.h"
|
#include "results/ResultsDatasetConsole.h"
|
||||||
#include "results/ResultsDataset.h"
|
#include "results/ResultsDataset.h"
|
||||||
#include "results/ResultsDatasetExcel.h"
|
#include "results/ResultsDatasetExcel.h"
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
|
|
||||||
void list_datasets(argparse::ArgumentParser& program)
|
void list_datasets(argparse::ArgumentParser& program)
|
||||||
|
@@ -7,11 +7,12 @@
|
|||||||
#include "common/Paths.h"
|
#include "common/Paths.h"
|
||||||
#include "main/Models.h"
|
#include "main/Models.h"
|
||||||
#include "main/modelRegister.h"
|
#include "main/modelRegister.h"
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
|
|
||||||
using json = nlohmann::ordered_json;
|
using json = nlohmann::ordered_json;
|
||||||
|
|
||||||
|
|
||||||
void manageArguments(argparse::ArgumentParser& program)
|
void manageArguments(argparse::ArgumentParser& program)
|
||||||
{
|
{
|
||||||
auto env = platform::DotEnv();
|
auto env = platform::DotEnv();
|
||||||
@@ -35,6 +36,7 @@ void manageArguments(argparse::ArgumentParser& program)
|
|||||||
program.add_argument("--hyperparameters").default_value("{}").help("Hyperparameters 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." \
|
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.");
|
"Mutually exclusive with hyperparameters. This file should contain hyperparameters for each dataset in json format.");
|
||||||
|
program.add_argument("--hyper-best").default_value(false).help("Use best results of the model as source of hyperparameters").implicit_value(true);
|
||||||
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) {
|
||||||
@@ -47,7 +49,23 @@ void manageArguments(argparse::ArgumentParser& program)
|
|||||||
);
|
);
|
||||||
program.add_argument("--title").default_value("").help("Experiment title");
|
program.add_argument("--title").default_value("").help("Experiment title");
|
||||||
program.add_argument("--discretize").help("Discretize input dataset").default_value((bool)stoi(env.get("discretize"))).implicit_value(true);
|
program.add_argument("--discretize").help("Discretize input dataset").default_value((bool)stoi(env.get("discretize"))).implicit_value(true);
|
||||||
|
auto valid_choices = env.valid_tokens("discretize_algo");
|
||||||
|
auto& disc_arg = program.add_argument("--discretize-algo").help("Algorithm to use in discretization. Valid values: " + env.valid_values("discretize_algo")).default_value(env.get("discretize_algo"));
|
||||||
|
for (auto choice : valid_choices) {
|
||||||
|
disc_arg.choices(choice);
|
||||||
|
}
|
||||||
|
valid_choices = env.valid_tokens("smooth_strat");
|
||||||
|
auto& smooth_arg = program.add_argument("--smooth-strat").help("Smooth strategy used in Bayes Network node initialization. Valid values: " + env.valid_values("smooth_strat")).default_value(env.get("smooth_strat"));
|
||||||
|
for (auto choice : valid_choices) {
|
||||||
|
smooth_arg.choices(choice);
|
||||||
|
}
|
||||||
|
auto& score_arg = program.add_argument("-s", "--score").help("Score to use. Valid values: " + env.valid_values("score")).default_value(env.get("score"));
|
||||||
|
valid_choices = env.valid_tokens("score");
|
||||||
|
for (auto choice : valid_choices) {
|
||||||
|
score_arg.choices(choice);
|
||||||
|
}
|
||||||
program.add_argument("--generate-fold-files").help("generate fold information in datasets_experiment folder").default_value(false).implicit_value(true);
|
program.add_argument("--generate-fold-files").help("generate fold information in datasets_experiment folder").default_value(false).implicit_value(true);
|
||||||
|
program.add_argument("--graph").help("generate graphviz dot files with the model").default_value(false).implicit_value(true);
|
||||||
program.add_argument("--no-train-score").help("Don't compute train score").default_value(false).implicit_value(true);
|
program.add_argument("--no-train-score").help("Don't compute train score").default_value(false).implicit_value(true);
|
||||||
program.add_argument("--quiet").help("Don't display detailed progress").default_value(false).implicit_value(true);
|
program.add_argument("--quiet").help("Don't display detailed progress").default_value(false).implicit_value(true);
|
||||||
program.add_argument("--save").help("Save result (always save if no dataset is supplied)").default_value(false).implicit_value(true);
|
program.add_argument("--save").help("Save result (always save if no dataset is supplied)").default_value(false).implicit_value(true);
|
||||||
@@ -67,16 +85,16 @@ void manageArguments(argparse::ArgumentParser& program)
|
|||||||
throw std::runtime_error("Number of folds must be an integer");
|
throw std::runtime_error("Number of folds must be an integer");
|
||||||
}});
|
}});
|
||||||
auto seed_values = env.getSeeds();
|
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);
|
program.add_argument("--seeds").nargs(1, 10).help("Random seeds. Set to -1 to have pseudo random").scan<'i', int>().default_value(seed_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
argparse::ArgumentParser program("b_main", { platform_project_version.begin(), platform_project_version.end() });
|
argparse::ArgumentParser program("b_main", { platform_project_version.begin(), platform_project_version.end() });
|
||||||
manageArguments(program);
|
manageArguments(program);
|
||||||
std::string file_name, model_name, title, hyperparameters_file, datasets_file;
|
std::string file_name, model_name, title, hyperparameters_file, datasets_file, discretize_algo, smooth_strat, score;
|
||||||
json hyperparameters_json;
|
json hyperparameters_json;
|
||||||
bool discretize_dataset, stratified, saveResults, quiet, no_train_score, generate_fold_files;
|
bool discretize_dataset, stratified, saveResults, quiet, no_train_score, generate_fold_files, graph, hyper_best;
|
||||||
std::vector<int> seeds;
|
std::vector<int> seeds;
|
||||||
std::vector<std::string> file_names;
|
std::vector<std::string> file_names;
|
||||||
std::vector<std::string> filesToTest;
|
std::vector<std::string> filesToTest;
|
||||||
@@ -88,21 +106,33 @@ int main(int argc, char** argv)
|
|||||||
datasets_file = program.get<std::string>("datasets-file");
|
datasets_file = program.get<std::string>("datasets-file");
|
||||||
model_name = program.get<std::string>("model");
|
model_name = program.get<std::string>("model");
|
||||||
discretize_dataset = program.get<bool>("discretize");
|
discretize_dataset = program.get<bool>("discretize");
|
||||||
|
discretize_algo = program.get<std::string>("discretize-algo");
|
||||||
|
smooth_strat = program.get<std::string>("smooth-strat");
|
||||||
stratified = program.get<bool>("stratified");
|
stratified = program.get<bool>("stratified");
|
||||||
quiet = program.get<bool>("quiet");
|
quiet = program.get<bool>("quiet");
|
||||||
|
graph = program.get<bool>("graph");
|
||||||
n_folds = program.get<int>("folds");
|
n_folds = program.get<int>("folds");
|
||||||
|
score = program.get<std::string>("score");
|
||||||
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");
|
hyperparameters_file = program.get<std::string>("hyper-file");
|
||||||
no_train_score = program.get<bool>("no-train-score");
|
no_train_score = program.get<bool>("no-train-score");
|
||||||
|
hyper_best = program.get<bool>("hyper-best");
|
||||||
generate_fold_files = program.get<bool>("generate-fold-files");
|
generate_fold_files = program.get<bool>("generate-fold-files");
|
||||||
if (hyperparameters_file != "" && hyperparameters != "{}") {
|
if (hyper_best) {
|
||||||
throw runtime_error("hyperparameters and hyper_file are mutually exclusive");
|
// Build the best results file_name
|
||||||
|
hyperparameters_file = platform::Paths::results() + platform::Paths::bestResultsFile(score, model_name);
|
||||||
|
// ignore this parameter
|
||||||
|
hyperparameters = "{}";
|
||||||
|
} else {
|
||||||
|
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 == "all") {
|
||||||
throw runtime_error("title is mandatory if dataset is not provided");
|
throw runtime_error("title is mandatory if all datasets are to be tested");
|
||||||
}
|
}
|
||||||
saveResults = program.get<bool>("save");
|
saveResults = program.get<bool>("save");
|
||||||
}
|
}
|
||||||
@@ -167,7 +197,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
platform::HyperParameters test_hyperparams;
|
platform::HyperParameters test_hyperparams;
|
||||||
if (hyperparameters_file != "") {
|
if (hyperparameters_file != "") {
|
||||||
test_hyperparams = platform::HyperParameters(datasets.getNames(), hyperparameters_file);
|
test_hyperparams = platform::HyperParameters(datasets.getNames(), hyperparameters_file, hyper_best);
|
||||||
} else {
|
} else {
|
||||||
test_hyperparams = platform::HyperParameters(datasets.getNames(), hyperparameters_json);
|
test_hyperparams = platform::HyperParameters(datasets.getNames(), hyperparameters_json);
|
||||||
}
|
}
|
||||||
@@ -177,18 +207,17 @@ int main(int argc, char** argv)
|
|||||||
*/
|
*/
|
||||||
auto env = platform::DotEnv();
|
auto env = platform::DotEnv();
|
||||||
auto experiment = platform::Experiment();
|
auto experiment = platform::Experiment();
|
||||||
std::string discretiz_algo = env.get("discretiz_algo");
|
experiment.setTitle(title).setLanguage("c++").setLanguageVersion("gcc 14.1.1");
|
||||||
experiment.setTitle(title).setLanguage("c++").setLanguageVersion("13.2.1");
|
experiment.setDiscretizationAlgorithm(discretize_algo).setSmoothSrategy(smooth_strat);
|
||||||
experiment.setDiscretizationAlgorithm(discretiz_algo);
|
|
||||||
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(score);
|
||||||
experiment.setHyperparameters(test_hyperparams);
|
experiment.setHyperparameters(test_hyperparams);
|
||||||
for (auto seed : seeds) {
|
for (auto seed : seeds) {
|
||||||
experiment.addRandomSeed(seed);
|
experiment.addRandomSeed(seed);
|
||||||
}
|
}
|
||||||
platform::Timer timer;
|
platform::Timer timer;
|
||||||
timer.start();
|
timer.start();
|
||||||
experiment.go(filesToTest, quiet, no_train_score, generate_fold_files);
|
experiment.go(filesToTest, quiet, no_train_score, generate_fold_files, graph);
|
||||||
experiment.setDuration(timer.getDuration());
|
experiment.setDuration(timer.getDuration());
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
// Classification report if only one dataset is tested
|
// Classification report if only one dataset is tested
|
||||||
@@ -197,6 +226,9 @@ int main(int argc, char** argv)
|
|||||||
if (saveResults) {
|
if (saveResults) {
|
||||||
experiment.saveResult();
|
experiment.saveResult();
|
||||||
}
|
}
|
||||||
|
if (graph) {
|
||||||
|
experiment.saveGraph();
|
||||||
|
}
|
||||||
std::cout << "Done!" << std::endl;
|
std::cout << "Done!" << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,10 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <argparse/argparse.hpp>
|
#include <argparse/argparse.hpp>
|
||||||
#include "manage/ManageScreen.h"
|
#include "manage/ManageScreen.h"
|
||||||
#include "config.h"
|
#include <signal.h>
|
||||||
|
#include "config_platform.h"
|
||||||
|
|
||||||
|
platform::ManageScreen* manager = nullptr;
|
||||||
|
|
||||||
void manageArguments(argparse::ArgumentParser& program, int argc, char** argv)
|
void manageArguments(argparse::ArgumentParser& program, int argc, char** argv)
|
||||||
{
|
{
|
||||||
@@ -42,6 +45,11 @@ std::pair<int, int> numRowsCols()
|
|||||||
return { ts.ws_row, ts.ws_col };
|
return { ts.ws_row, ts.ws_col };
|
||||||
#endif /* TIOCGSIZE */
|
#endif /* TIOCGSIZE */
|
||||||
}
|
}
|
||||||
|
void handleResize(int sig)
|
||||||
|
{
|
||||||
|
auto [rows, cols] = numRowsCols();
|
||||||
|
manager->updateSize(rows, cols);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
@@ -50,13 +58,15 @@ int main(int argc, char** argv)
|
|||||||
std::string model = program.get<std::string>("model");
|
std::string model = program.get<std::string>("model");
|
||||||
std::string score = program.get<std::string>("score");
|
std::string score = program.get<std::string>("score");
|
||||||
std::string platform = program.get<std::string>("platform");
|
std::string platform = program.get<std::string>("platform");
|
||||||
auto complete = program.get<bool>("complete");
|
bool complete = program.get<bool>("complete");
|
||||||
auto partial = program.get<bool>("partial");
|
bool partial = program.get<bool>("partial");
|
||||||
auto compare = program.get<bool>("compare");
|
bool compare = program.get<bool>("compare");
|
||||||
auto [rows, cols] = numRowsCols();
|
|
||||||
if (complete)
|
if (complete)
|
||||||
partial = false;
|
partial = false;
|
||||||
auto manager = platform::ManageScreen(rows, cols, model, score, platform, complete, partial, compare);
|
signal(SIGWINCH, handleResize);
|
||||||
manager.doMenu();
|
auto [rows, cols] = numRowsCols();
|
||||||
|
manager = new platform::ManageScreen(rows, cols, model, score, platform, complete, partial, compare);
|
||||||
|
manager->doMenu();
|
||||||
|
delete manager;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -131,8 +131,7 @@ namespace platform {
|
|||||||
for (int i = 0; i < features.size(); ++i) {
|
for (int i = 0; i < features.size(); ++i) {
|
||||||
auto [max_value, idx] = torch::max(X_train.index({ i, "..." }), 0);
|
auto [max_value, idx] = torch::max(X_train.index({ i, "..." }), 0);
|
||||||
states[features[i]] = std::vector<int>(max_value.item<int>() + 1);
|
states[features[i]] = std::vector<int>(max_value.item<int>() + 1);
|
||||||
auto item = states.at(features[i]);
|
iota(begin(states.at(features[i])), end(states.at(features[i])), 0);
|
||||||
iota(begin(item), end(item), 0);
|
|
||||||
}
|
}
|
||||||
auto [max_value, idx] = torch::max(y_train, 0);
|
auto [max_value, idx] = torch::max(y_train, 0);
|
||||||
states[className] = std::vector<int>(max_value.item<int>() + 1);
|
states[className] = std::vector<int>(max_value.item<int>() + 1);
|
||||||
|
@@ -5,6 +5,14 @@
|
|||||||
namespace platform {
|
namespace platform {
|
||||||
using json = nlohmann::ordered_json;
|
using json = nlohmann::ordered_json;
|
||||||
const std::string message_dataset_not_loaded = "dataset not loaded.";
|
const std::string message_dataset_not_loaded = "dataset not loaded.";
|
||||||
|
Datasets::Datasets(bool discretize, std::string sfileType, std::string discretizer_algorithm) :
|
||||||
|
discretize(discretize), sfileType(sfileType), discretizer_algorithm(discretizer_algorithm)
|
||||||
|
{
|
||||||
|
if ((discretizer_algorithm == "none" || discretizer_algorithm == "") && discretize) {
|
||||||
|
throw std::runtime_error("Can't discretize without discretization algorithm");
|
||||||
|
}
|
||||||
|
load();
|
||||||
|
}
|
||||||
void Datasets::load()
|
void Datasets::load()
|
||||||
{
|
{
|
||||||
auto sd = SourceData(sfileType);
|
auto sd = SourceData(sfileType);
|
||||||
|
@@ -4,14 +4,7 @@
|
|||||||
namespace platform {
|
namespace platform {
|
||||||
class Datasets {
|
class Datasets {
|
||||||
public:
|
public:
|
||||||
explicit Datasets(bool discretize, std::string sfileType, std::string discretizer_algorithm = "none") :
|
explicit Datasets(bool discretize, std::string sfileType, std::string discretizer_algorithm = "none");
|
||||||
discretize(discretize), sfileType(sfileType), discretizer_algorithm(discretizer_algorithm)
|
|
||||||
{
|
|
||||||
if (discretizer_algorithm == "none" && discretize) {
|
|
||||||
throw std::runtime_error("Can't discretize without discretization algorithm");
|
|
||||||
}
|
|
||||||
load();
|
|
||||||
};
|
|
||||||
std::vector<std::string> getNames();
|
std::vector<std::string> getNames();
|
||||||
bool isDataset(const std::string& name) const;
|
bool isDataset(const std::string& name) const;
|
||||||
Dataset& getDataset(const std::string& name) const { return *datasets.at(name); }
|
Dataset& getDataset(const std::string& name) const { return *datasets.at(name); }
|
||||||
|
@@ -5,9 +5,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <Discretizer.h>
|
#include <fimdlp/Discretizer.h>
|
||||||
#include <BinDisc.h>
|
#include <fimdlp/BinDisc.h>
|
||||||
#include <CPPFImdlp.h>
|
#include <fimdlp/CPPFImdlp.h>
|
||||||
namespace platform {
|
namespace platform {
|
||||||
class Discretization {
|
class Discretization {
|
||||||
public:
|
public:
|
||||||
|
@@ -11,4 +11,28 @@ static platform::RegistrarDiscretization registrarBU4("bin4u",
|
|||||||
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(4, mdlp::strategy_t::UNIFORM);});
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(4, mdlp::strategy_t::UNIFORM);});
|
||||||
static platform::RegistrarDiscretization registrarBQ4("bin4q",
|
static platform::RegistrarDiscretization registrarBQ4("bin4q",
|
||||||
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(4, mdlp::strategy_t::QUANTILE);});
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(4, mdlp::strategy_t::QUANTILE);});
|
||||||
|
static platform::RegistrarDiscretization registrarBU5("bin5u",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(5, mdlp::strategy_t::UNIFORM);});
|
||||||
|
static platform::RegistrarDiscretization registrarBQ5("bin5q",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(5, mdlp::strategy_t::QUANTILE);});
|
||||||
|
static platform::RegistrarDiscretization registrarBU6("bin6u",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(6, mdlp::strategy_t::UNIFORM);});
|
||||||
|
static platform::RegistrarDiscretization registrarBQ6("bin6q",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(6, mdlp::strategy_t::QUANTILE);});
|
||||||
|
static platform::RegistrarDiscretization registrarBU7("bin7u",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(7, mdlp::strategy_t::UNIFORM);});
|
||||||
|
static platform::RegistrarDiscretization registrarBQ7("bin7q",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(7, mdlp::strategy_t::QUANTILE);});
|
||||||
|
static platform::RegistrarDiscretization registrarBU8("bin8u",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(8, mdlp::strategy_t::UNIFORM);});
|
||||||
|
static platform::RegistrarDiscretization registrarBQ8("bin8q",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(8, mdlp::strategy_t::QUANTILE);});
|
||||||
|
static platform::RegistrarDiscretization registrarBU9("bin9u",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(9, mdlp::strategy_t::UNIFORM);});
|
||||||
|
static platform::RegistrarDiscretization registrarBQ9("bin9q",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(9, mdlp::strategy_t::QUANTILE);});
|
||||||
|
static platform::RegistrarDiscretization registrarBU10("bin10u",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(10, mdlp::strategy_t::UNIFORM);});
|
||||||
|
static platform::RegistrarDiscretization registrarBQ10("bin10q",
|
||||||
|
[](void) -> mdlp::Discretizer* { return new mdlp::BinDisc(10, mdlp::strategy_t::QUANTILE);});
|
||||||
#endif
|
#endif
|
@@ -19,29 +19,47 @@ namespace platform {
|
|||||||
{
|
{
|
||||||
valid =
|
valid =
|
||||||
{
|
{
|
||||||
{"source_data", {"Arff", "Tanveer", "Surcov"}},
|
|
||||||
{"experiment", {"discretiz", "odte", "covid"}},
|
|
||||||
{"fit_features", {"0", "1"}},
|
|
||||||
{"discretize", {"0", "1"}},
|
|
||||||
{"ignore_nan", {"0", "1"}},
|
|
||||||
{"stratified", {"0", "1"}},
|
|
||||||
{"score", {"accuracy"}},
|
|
||||||
{"framework", {"bulma", "bootstrap"}},
|
|
||||||
{"margin", {"0.1", "0.2", "0.3"}},
|
|
||||||
{"n_folds", {"5", "10"}},
|
|
||||||
{"discretiz_algo", {"mdlp", "bin3u", "bin3q", "bin4u", "bin4q"}},
|
|
||||||
{"platform", {"any"}},
|
|
||||||
{"model", {"any"}},
|
|
||||||
{"seeds", {"any"}},
|
|
||||||
{"nodes", {"any"}},
|
|
||||||
{"leaves", {"any"}},
|
|
||||||
{"depth", {"any"}},
|
{"depth", {"any"}},
|
||||||
|
{"discretize", {"0", "1"}},
|
||||||
|
{"discretize_algo", {"mdlp", "bin3u", "bin3q", "bin4u", "bin4q", "bin5q", "bin5u", "bin6q", "bin6u", "bin7q", "bin7u", "bin8q", "bin8u", "bin9q", "bin9u", "bin10q", "bin10u"}},
|
||||||
|
{"experiment", {"discretiz", "odte", "covid", "Test"}},
|
||||||
|
{"fit_features", {"0", "1"}},
|
||||||
|
{"framework", {"bulma", "bootstrap"}},
|
||||||
|
{"ignore_nan", {"0", "1"}},
|
||||||
|
{"leaves", {"any"}},
|
||||||
|
{"margin", {"0.1", "0.2", "0.3"}},
|
||||||
|
{"model", {"any"}},
|
||||||
|
{"n_folds", {"5", "10"}},
|
||||||
|
{"nodes", {"any"}},
|
||||||
|
{"platform", {"any"}},
|
||||||
|
{"stratified", {"0", "1"}},
|
||||||
|
{"score", {"accuracy", "roc-auc-ovr"}},
|
||||||
|
{"seeds", {"any"}},
|
||||||
|
{"smooth_strat", {"ORIGINAL", "LAPLACE", "CESTNIK"}},
|
||||||
|
{"source_data", {"Arff", "Tanveer", "Surcov", "Test"}},
|
||||||
};
|
};
|
||||||
if (create) {
|
if (create) {
|
||||||
// For testing purposes
|
// For testing purposes
|
||||||
std::ofstream file(".env");
|
std::ofstream file(".env");
|
||||||
file << "source_data = Test" << std::endl;
|
file << "experiment=Test" << std::endl;
|
||||||
file << "margin = 0.1" << std::endl;
|
file << "source_data=Test" << std::endl;
|
||||||
|
file << "margin=0.1" << std::endl;
|
||||||
|
file << "score=accuracy" << std::endl;
|
||||||
|
file << "platform=um790Linux" << std::endl;
|
||||||
|
file << "n_folds=5" << std::endl;
|
||||||
|
file << "discretize_algo=mdlp" << std::endl;
|
||||||
|
file << "smooth_strat=ORIGINAL" << std::endl;
|
||||||
|
file << "stratified=0" << std::endl;
|
||||||
|
file << "model=TAN" << std::endl;
|
||||||
|
file << "seeds=[271]" << std::endl;
|
||||||
|
file << "discretize=0" << std::endl;
|
||||||
|
file << "ignore_nan=0" << std::endl;
|
||||||
|
file << "nodes=Nodes" << std::endl;
|
||||||
|
file << "leaves=Edges" << std::endl;
|
||||||
|
file << "depth=States" << std::endl;
|
||||||
|
file << "fit_features=0" << std::endl;
|
||||||
|
file << "framework=bulma" << std::endl;
|
||||||
|
file << "margin=0.1" << std::endl;
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
std::ifstream file(".env");
|
std::ifstream file(".env");
|
||||||
@@ -80,22 +98,40 @@ namespace platform {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::vector<std::string> valid_tokens(const std::string& key)
|
||||||
|
{
|
||||||
|
if (valid.find(key) == valid.end()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return valid.at(key);
|
||||||
|
}
|
||||||
|
std::string valid_values(const std::string& key)
|
||||||
|
{
|
||||||
|
std::string valid_values = "{", sep = "";
|
||||||
|
if (valid.find(key) == valid.end()) {
|
||||||
|
return "{}";
|
||||||
|
}
|
||||||
|
for (const auto& value : valid.at(key)) {
|
||||||
|
valid_values += sep + value;
|
||||||
|
sep = ", ";
|
||||||
|
}
|
||||||
|
return valid_values + "}";
|
||||||
|
}
|
||||||
void parseEnv()
|
void parseEnv()
|
||||||
{
|
{
|
||||||
for (auto& [key, values] : valid) {
|
for (auto& [key, values] : valid) {
|
||||||
if (env.find(key) == env.end()) {
|
if (env.find(key) == env.end()) {
|
||||||
std::string valid_values = "", sep = "";
|
std::cerr << "Key not found in .env: " << key << ", valid values: " << valid_values(key) << std::endl;
|
||||||
for (const auto& value : values) {
|
|
||||||
valid_values += sep + value;
|
|
||||||
sep = ", ";
|
|
||||||
}
|
|
||||||
std::cerr << "Key not found in .env: " << key << ", valid values: " << valid_values << std::endl;
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string get(const std::string& key)
|
std::string get(const std::string& key)
|
||||||
{
|
{
|
||||||
|
if (env.find(key) == env.end()) {
|
||||||
|
std::cerr << "Key not found in .env: " << key << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
return env.at(key);
|
return env.at(key);
|
||||||
}
|
}
|
||||||
std::vector<int> getSeeds()
|
std::vector<int> getSeeds()
|
||||||
|
@@ -6,10 +6,19 @@
|
|||||||
namespace platform {
|
namespace platform {
|
||||||
class Paths {
|
class Paths {
|
||||||
public:
|
public:
|
||||||
static std::string results() { return "results/"; }
|
static std::string createIfNotExists(const std::string& folder)
|
||||||
static std::string hiddenResults() { return "hidden_results/"; }
|
{
|
||||||
static std::string excel() { return "excel/"; }
|
if (!std::filesystem::exists(folder)) {
|
||||||
static std::string grid() { return "grid/"; }
|
std::filesystem::create_directory(folder);
|
||||||
|
}
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
static std::string results() { return createIfNotExists("results/"); }
|
||||||
|
static std::string hiddenResults() { return createIfNotExists("hidden_results/"); }
|
||||||
|
static std::string excel() { return createIfNotExists("excel/"); }
|
||||||
|
static std::string grid() { return createIfNotExists("grid/"); }
|
||||||
|
static std::string graphs() { return createIfNotExists("graphs/"); }
|
||||||
|
static std::string tex() { return createIfNotExists("tex/"); }
|
||||||
static std::string datasets()
|
static std::string datasets()
|
||||||
{
|
{
|
||||||
auto env = platform::DotEnv();
|
auto env = platform::DotEnv();
|
||||||
@@ -31,6 +40,14 @@ namespace platform {
|
|||||||
throw std::runtime_error("Could not create directory " + path);
|
throw std::runtime_error("Could not create directory " + path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static std::string bestResultsFile(const std::string& score, const std::string& model)
|
||||||
|
{
|
||||||
|
return "best_results_" + score + "_" + model + ".json";
|
||||||
|
}
|
||||||
|
static std::string bestResultsExcel(const std::string& score)
|
||||||
|
{
|
||||||
|
return "BestResults_" + score + ".xlsx";
|
||||||
|
}
|
||||||
static std::string excelResults() { return "some_results.xlsx"; }
|
static std::string excelResults() { return "some_results.xlsx"; }
|
||||||
static std::string grid_input(const std::string& model)
|
static std::string grid_input(const std::string& model)
|
||||||
{
|
{
|
||||||
@@ -40,6 +57,22 @@ namespace platform {
|
|||||||
{
|
{
|
||||||
return grid() + "grid_" + model + "_output.json";
|
return grid() + "grid_" + model + "_output.json";
|
||||||
}
|
}
|
||||||
|
static std::string tex_output()
|
||||||
|
{
|
||||||
|
return "results.tex";
|
||||||
|
}
|
||||||
|
static std::string md_output()
|
||||||
|
{
|
||||||
|
return "results.md";
|
||||||
|
}
|
||||||
|
static std::string tex_post_hoc()
|
||||||
|
{
|
||||||
|
return "post_hoc.tex";
|
||||||
|
}
|
||||||
|
static std::string md_post_hoc()
|
||||||
|
{
|
||||||
|
return "post_hoc.md";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@@ -12,6 +12,7 @@ namespace platform {
|
|||||||
inline static const std::string downward_arrow{ "\u27B4" };
|
inline static const std::string downward_arrow{ "\u27B4" };
|
||||||
inline static const std::string up_arrow{ "\u2B06" };
|
inline static const std::string up_arrow{ "\u2B06" };
|
||||||
inline static const std::string down_arrow{ "\u2B07" };
|
inline static const std::string down_arrow{ "\u2B07" };
|
||||||
|
inline static const std::string ellipsis{ "\u2026" };
|
||||||
inline static const std::string equal_best{ check_mark };
|
inline static const std::string equal_best{ check_mark };
|
||||||
inline static const std::string better_best{ black_star };
|
inline static const std::string better_best{ black_star };
|
||||||
inline static const std::string notebook{ "\U0001F5C8" };
|
inline static const std::string notebook{ "\U0001F5C8" };
|
||||||
|
@@ -4,7 +4,17 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <torch/torch.h>
|
||||||
namespace platform {
|
namespace platform {
|
||||||
|
template <typename T>
|
||||||
|
std::vector<T> tensorToVector(const torch::Tensor& tensor)
|
||||||
|
{
|
||||||
|
torch::Tensor contig_tensor = tensor.contiguous();
|
||||||
|
auto num_elements = contig_tensor.numel();
|
||||||
|
const T* tensor_data = contig_tensor.data_ptr<T>();
|
||||||
|
std::vector<T> result(tensor_data, tensor_data + num_elements);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
static std::string trim(const std::string& str)
|
static std::string trim(const std::string& str)
|
||||||
{
|
{
|
||||||
std::string result = str;
|
std::string result = str;
|
||||||
@@ -26,5 +36,35 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
inline double compute_std(std::vector<double> values, double mean)
|
||||||
|
{
|
||||||
|
// Compute standard devation of the values
|
||||||
|
double sum = 0.0;
|
||||||
|
for (const auto& value : values) {
|
||||||
|
sum += std::pow(value - mean, 2);
|
||||||
|
}
|
||||||
|
double variance = sum / values.size();
|
||||||
|
return std::sqrt(variance);
|
||||||
|
}
|
||||||
|
inline std::string get_date()
|
||||||
|
{
|
||||||
|
time_t rawtime;
|
||||||
|
tm* timeinfo;
|
||||||
|
time(&rawtime);
|
||||||
|
timeinfo = std::localtime(&rawtime);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::put_time(timeinfo, "%Y-%m-%d");
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
|
inline std::string get_time()
|
||||||
|
{
|
||||||
|
time_t rawtime;
|
||||||
|
tm* timeinfo;
|
||||||
|
time(&rawtime);
|
||||||
|
timeinfo = std::localtime(&rawtime);
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << std::put_time(timeinfo, "%H:%M:%S");
|
||||||
|
return oss.str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@@ -5,29 +5,11 @@
|
|||||||
#include "main/Models.h"
|
#include "main/Models.h"
|
||||||
#include "common/Paths.h"
|
#include "common/Paths.h"
|
||||||
#include "common/Colors.h"
|
#include "common/Colors.h"
|
||||||
|
#include "common/Utils.h"
|
||||||
#include "GridSearch.h"
|
#include "GridSearch.h"
|
||||||
|
|
||||||
namespace platform {
|
namespace platform {
|
||||||
std::string get_date()
|
|
||||||
{
|
|
||||||
time_t rawtime;
|
|
||||||
tm* timeinfo;
|
|
||||||
time(&rawtime);
|
|
||||||
timeinfo = std::localtime(&rawtime);
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << std::put_time(timeinfo, "%Y-%m-%d");
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
std::string get_time()
|
|
||||||
{
|
|
||||||
time_t rawtime;
|
|
||||||
tm* timeinfo;
|
|
||||||
time(&rawtime);
|
|
||||||
timeinfo = std::localtime(&rawtime);
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << std::put_time(timeinfo, "%H:%M:%S");
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
std::string get_color_rank(int rank)
|
std::string get_color_rank(int rank)
|
||||||
{
|
{
|
||||||
auto colors = { Colors::WHITE(), Colors::RED(), Colors::GREEN(), Colors::BLUE(), Colors::MAGENTA(), Colors::CYAN() };
|
auto colors = { Colors::WHITE(), Colors::RED(), Colors::GREEN(), Colors::BLUE(), Colors::MAGENTA(), Colors::CYAN() };
|
||||||
@@ -103,11 +85,11 @@ namespace platform {
|
|||||||
std::mt19937 g{ 271 }; // Use fixed seed to obtain the same shuffle
|
std::mt19937 g{ 271 }; // Use fixed seed to obtain the same shuffle
|
||||||
std::shuffle(tasks.begin(), tasks.end(), g);
|
std::shuffle(tasks.begin(), tasks.end(), g);
|
||||||
std::cout << get_color_rank(rank) << "* Number of tasks: " << tasks.size() << std::endl;
|
std::cout << get_color_rank(rank) << "* Number of tasks: " << tasks.size() << std::endl;
|
||||||
std::cout << "|";
|
std::cout << separator;
|
||||||
for (int i = 0; i < tasks.size(); ++i) {
|
for (int i = 0; i < tasks.size(); ++i) {
|
||||||
std::cout << (i + 1) % 10;
|
std::cout << (i + 1) % 10;
|
||||||
}
|
}
|
||||||
std::cout << "|" << std::endl << "|" << std::flush;
|
std::cout << separator << std::endl << separator << std::flush;
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
void process_task_mpi_consumer(struct ConfigGrid& config, struct ConfigMPI& config_mpi, json& tasks, int n_task, Datasets& datasets, Task_Result* result)
|
void process_task_mpi_consumer(struct ConfigGrid& config, struct ConfigMPI& config_mpi, json& tasks, int n_task, Datasets& datasets, Task_Result* result)
|
||||||
@@ -126,6 +108,7 @@ namespace platform {
|
|||||||
// Generate the hyperparamters combinations
|
// Generate the hyperparamters combinations
|
||||||
auto& dataset = datasets.getDataset(dataset_name);
|
auto& dataset = datasets.getDataset(dataset_name);
|
||||||
auto combinations = grid.getGrid(dataset_name);
|
auto combinations = grid.getGrid(dataset_name);
|
||||||
|
dataset.load();
|
||||||
auto [X, y] = dataset.getTensors();
|
auto [X, y] = dataset.getTensors();
|
||||||
auto features = dataset.getFeatures();
|
auto features = dataset.getFeatures();
|
||||||
auto className = dataset.getClassName();
|
auto className = dataset.getClassName();
|
||||||
@@ -142,6 +125,7 @@ namespace platform {
|
|||||||
auto states = dataset.getStates(); // Get the states of the features Once they are discretized
|
auto states = dataset.getStates(); // Get the states of the features Once they are discretized
|
||||||
double best_fold_score = 0.0;
|
double best_fold_score = 0.0;
|
||||||
int best_idx_combination = -1;
|
int best_idx_combination = -1;
|
||||||
|
bayesnet::Smoothing_t smoothing = bayesnet::Smoothing_t::NONE;
|
||||||
json best_fold_hyper;
|
json best_fold_hyper;
|
||||||
for (int idx_combination = 0; idx_combination < combinations.size(); ++idx_combination) {
|
for (int idx_combination = 0; idx_combination < combinations.size(); ++idx_combination) {
|
||||||
auto hyperparam_line = combinations[idx_combination];
|
auto hyperparam_line = combinations[idx_combination];
|
||||||
@@ -167,7 +151,7 @@ namespace platform {
|
|||||||
hyperparameters.check(valid, dataset_name);
|
hyperparameters.check(valid, dataset_name);
|
||||||
clf->setHyperparameters(hyperparameters.get(dataset_name));
|
clf->setHyperparameters(hyperparameters.get(dataset_name));
|
||||||
// Train model
|
// Train model
|
||||||
clf->fit(X_nested_train, y_nested_train, features, className, states);
|
clf->fit(X_nested_train, y_nested_train, features, className, states, smoothing);
|
||||||
// Test model
|
// Test model
|
||||||
score += clf->score(X_nested_test, y_nested_test);
|
score += clf->score(X_nested_test, y_nested_test);
|
||||||
}
|
}
|
||||||
@@ -186,7 +170,7 @@ namespace platform {
|
|||||||
auto valid = clf->getValidHyperparameters();
|
auto valid = clf->getValidHyperparameters();
|
||||||
hyperparameters.check(valid, dataset_name);
|
hyperparameters.check(valid, dataset_name);
|
||||||
clf->setHyperparameters(best_fold_hyper);
|
clf->setHyperparameters(best_fold_hyper);
|
||||||
clf->fit(X_train, y_train, features, className, states);
|
clf->fit(X_train, y_train, features, className, states, smoothing);
|
||||||
best_fold_score = clf->score(X_test, y_test);
|
best_fold_score = clf->score(X_test, y_test);
|
||||||
// Return the result
|
// Return the result
|
||||||
result->idx_dataset = task["idx_dataset"].get<int>();
|
result->idx_dataset = task["idx_dataset"].get<int>();
|
||||||
@@ -370,14 +354,15 @@ namespace platform {
|
|||||||
tasks = json::parse(msg);
|
tasks = json::parse(msg);
|
||||||
delete[] msg;
|
delete[] msg;
|
||||||
auto env = platform::DotEnv();
|
auto env = platform::DotEnv();
|
||||||
auto datasets = Datasets(config.discretize, Paths::datasets(), env.get("discretiz_algo"));
|
auto datasets = Datasets(config.discretize, Paths::datasets(), env.get("discretize_algo"));
|
||||||
|
|
||||||
if (config_mpi.rank == config_mpi.manager) {
|
if (config_mpi.rank == config_mpi.manager) {
|
||||||
//
|
//
|
||||||
// 2a. Producer delivers the tasks to the consumers
|
// 2a. Producer delivers the tasks to the consumers
|
||||||
//
|
//
|
||||||
auto datasets_names = filterDatasets(datasets);
|
auto datasets_names = filterDatasets(datasets);
|
||||||
json all_results = producer(datasets_names, tasks, config_mpi, MPI_Result);
|
json all_results = producer(datasets_names, tasks, config_mpi, MPI_Result);
|
||||||
std::cout << get_color_rank(config_mpi.rank) << "|" << std::endl;
|
std::cout << get_color_rank(config_mpi.rank) << separator << std::endl;
|
||||||
//
|
//
|
||||||
// 3. Manager select the bests sccores for each dataset
|
// 3. Manager select the bests sccores for each dataset
|
||||||
//
|
//
|
||||||
|
@@ -55,6 +55,7 @@ namespace platform {
|
|||||||
struct ConfigGrid config;
|
struct ConfigGrid config;
|
||||||
json build_tasks_mpi(int rank);
|
json build_tasks_mpi(int rank);
|
||||||
Timer timer; // used to measure the time of the whole process
|
Timer timer; // used to measure the time of the whole process
|
||||||
|
const std::string separator = "|";
|
||||||
};
|
};
|
||||||
} /* namespace platform */
|
} /* namespace platform */
|
||||||
#endif
|
#endif
|
@@ -24,7 +24,24 @@ namespace platform {
|
|||||||
{
|
{
|
||||||
std::cout << result.getJson().dump(4) << std::endl;
|
std::cout << result.getJson().dump(4) << std::endl;
|
||||||
}
|
}
|
||||||
void Experiment::go(std::vector<std::string> filesToProcess, bool quiet, bool no_train_score, bool generate_fold_files)
|
void Experiment::saveGraph()
|
||||||
|
{
|
||||||
|
std::cout << "Saving graphs..." << std::endl;
|
||||||
|
auto data = result.getJson();
|
||||||
|
for (const auto& item : data["results"]) {
|
||||||
|
auto graphs = item["graph"];
|
||||||
|
int i = 0;
|
||||||
|
for (const auto& graph : graphs) {
|
||||||
|
i++;
|
||||||
|
auto fileName = Paths::graphs() + result.getFilename() + "_graph_" + item["dataset"].get<std::string>() + "_" + std::to_string(i) + ".dot";
|
||||||
|
auto file = std::ofstream(fileName);
|
||||||
|
file << graph.get<std::string>();
|
||||||
|
file.close();
|
||||||
|
std::cout << "Graph saved in " << fileName << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Experiment::go(std::vector<std::string> filesToProcess, bool quiet, bool no_train_score, bool generate_fold_files, bool graph)
|
||||||
{
|
{
|
||||||
for (auto fileName : filesToProcess) {
|
for (auto fileName : filesToProcess) {
|
||||||
if (fileName.size() > max_name)
|
if (fileName.size() > max_name)
|
||||||
@@ -41,14 +58,14 @@ namespace platform {
|
|||||||
std::cout << " ( " << Colors::GREEN() << "b" << Colors::RESET() << " ) Scoring train dataset" << std::endl;
|
std::cout << " ( " << Colors::GREEN() << "b" << Colors::RESET() << " ) Scoring train dataset" << std::endl;
|
||||||
std::cout << " ( " << Colors::GREEN() << "c" << Colors::RESET() << " ) Scoring test dataset" << std::endl << std::endl;
|
std::cout << " ( " << Colors::GREEN() << "c" << Colors::RESET() << " ) Scoring test dataset" << std::endl << std::endl;
|
||||||
std::cout << Colors::YELLOW() << "Note: fold number in this color means fitting had issues such as not using all features in BoostAODE classifier" << std::endl << std::endl;
|
std::cout << Colors::YELLOW() << "Note: fold number in this color means fitting had issues such as not using all features in BoostAODE classifier" << std::endl << std::endl;
|
||||||
std::cout << Colors::GREEN() << left << " # " << setw(max_name) << "Dataset" << " #Samp #Feat Seed Status" << std::endl;
|
std::cout << Colors::GREEN() << left << " # " << setw(max_name) << "Dataset" << " #Samp #Feat Seed Status" << string(3 * nfolds - 2, ' ') << " Time" << std::endl;
|
||||||
std::cout << " --- " << string(max_name, '-') << " ----- ----- ---- " << string(4 + 3 * nfolds, '-') << Colors::RESET() << std::endl;
|
std::cout << " --- " << string(max_name, '-') << " ----- ----- ---- " << string(4 + 3 * nfolds, '-') << " ----------" << Colors::RESET() << std::endl;
|
||||||
}
|
}
|
||||||
int num = 0;
|
int num = 0;
|
||||||
for (auto fileName : filesToProcess) {
|
for (auto fileName : filesToProcess) {
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
std::cout << " " << setw(3) << right << num++ << " " << setw(max_name) << left << fileName << right << flush;
|
std::cout << " " << setw(3) << right << num++ << " " << setw(max_name) << left << fileName << right << flush;
|
||||||
cross_validation(fileName, quiet, no_train_score, generate_fold_files);
|
cross_validation(fileName, quiet, no_train_score, generate_fold_files, graph);
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
@@ -68,10 +85,17 @@ namespace platform {
|
|||||||
return Colors::RESET();
|
return Colors::RESET();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
score_t Experiment::parse_score() const
|
||||||
|
{
|
||||||
|
if (result.getScoreName() == "accuracy")
|
||||||
|
return score_t::ACCURACY;
|
||||||
|
if (result.getScoreName() == "roc-auc-ovr")
|
||||||
|
return score_t::ROC_AUC_OVR;
|
||||||
|
throw std::runtime_error("Unknown score: " + result.getScoreName());
|
||||||
|
}
|
||||||
void showProgress(int fold, const std::string& color, const std::string& phase)
|
void showProgress(int fold, const std::string& color, const std::string& phase)
|
||||||
{
|
{
|
||||||
std::string prefix = phase == "a" ? "" : "\b\b\b\b";
|
std::string prefix = phase == "-" ? "" : "\b\b\b\b";
|
||||||
std::cout << prefix << color << fold << Colors::RESET() << "(" << color << phase << Colors::RESET() << ")" << flush;
|
std::cout << prefix << color << fold << Colors::RESET() << "(" << color << phase << Colors::RESET() << ")" << flush;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -113,7 +137,7 @@ namespace platform {
|
|||||||
file << output.dump(4);
|
file << output.dump(4);
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
void Experiment::cross_validation(const std::string& fileName, bool quiet, bool no_train_score, bool generate_fold_files)
|
void Experiment::cross_validation(const std::string& fileName, bool quiet, bool no_train_score, bool generate_fold_files, bool graph)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Load dataset and prepare data
|
// Load dataset and prepare data
|
||||||
@@ -141,8 +165,8 @@ namespace platform {
|
|||||||
// 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 score_test = torch::zeros({ nResults }, torch::kFloat64);
|
||||||
auto accuracy_train = torch::zeros({ nResults }, torch::kFloat64);
|
auto score_train = torch::zeros({ nResults }, torch::kFloat64);
|
||||||
auto train_time = torch::zeros({ nResults }, torch::kFloat64);
|
auto train_time = torch::zeros({ nResults }, torch::kFloat64);
|
||||||
auto test_time = torch::zeros({ nResults }, torch::kFloat64);
|
auto test_time = torch::zeros({ nResults }, torch::kFloat64);
|
||||||
auto nodes = torch::zeros({ nResults }, torch::kFloat64);
|
auto nodes = torch::zeros({ nResults }, torch::kFloat64);
|
||||||
@@ -151,13 +175,16 @@ namespace platform {
|
|||||||
json confusion_matrices = json::array();
|
json confusion_matrices = json::array();
|
||||||
json confusion_matrices_train = json::array();
|
json confusion_matrices_train = json::array();
|
||||||
std::vector<std::string> notes;
|
std::vector<std::string> notes;
|
||||||
Timer train_timer, test_timer;
|
std::vector<std::string> graphs;
|
||||||
|
Timer train_timer, test_timer, seed_timer;
|
||||||
int item = 0;
|
int item = 0;
|
||||||
bool first_seed = true;
|
bool first_seed = true;
|
||||||
//
|
//
|
||||||
// Loop over random seeds
|
// Loop over random seeds
|
||||||
//
|
//
|
||||||
|
auto score = parse_score();
|
||||||
for (auto seed : randomSeeds) {
|
for (auto seed : randomSeeds) {
|
||||||
|
seed_timer.start();
|
||||||
if (!quiet) {
|
if (!quiet) {
|
||||||
string prefix = " ";
|
string prefix = " ";
|
||||||
if (!first_seed) {
|
if (!first_seed) {
|
||||||
@@ -176,6 +203,8 @@ namespace platform {
|
|||||||
//
|
//
|
||||||
for (int nfold = 0; nfold < nfolds; nfold++) {
|
for (int nfold = 0; nfold < nfolds; nfold++) {
|
||||||
auto clf = Models::instance()->create(result.getModel());
|
auto clf = Models::instance()->create(result.getModel());
|
||||||
|
if (!quiet)
|
||||||
|
showProgress(nfold + 1, getColor(clf->getStatus()), "-");
|
||||||
setModelVersion(clf->getVersion());
|
setModelVersion(clf->getVersion());
|
||||||
auto valid = clf->getValidHyperparameters();
|
auto valid = clf->getValidHyperparameters();
|
||||||
hyperparameters.check(valid, fileName);
|
hyperparameters.check(valid, fileName);
|
||||||
@@ -194,15 +223,7 @@ namespace platform {
|
|||||||
//
|
//
|
||||||
// Train model
|
// Train model
|
||||||
//
|
//
|
||||||
std::cout << "X_Train.dtype: " << X_train.dtype() << "\n";
|
clf->fit(X_train, y_train, features, className, states, smooth_type);
|
||||||
std::cout << "y_Train.dtype: " << y_train.dtype() << "\n";
|
|
||||||
std::cout << "X_Test.dtype: " << X_test.dtype() << "\n";
|
|
||||||
std::cout << "y_Test.dtype: " << y_test.dtype() << "\n";
|
|
||||||
for (int i = 0; i < features.size(); i++) {
|
|
||||||
std::cout << "Feature: " << features[i] << " states: " << states[features[i]].size() << "\n";
|
|
||||||
}
|
|
||||||
std::cout << "className: " << className << " states: " << states[className].size() << "\n";
|
|
||||||
clf->fit(X_train, y_train, features, className, states);
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
showProgress(nfold + 1, getColor(clf->getStatus()), "b");
|
showProgress(nfold + 1, getColor(clf->getStatus()), "b");
|
||||||
auto clf_notes = clf->getNotes();
|
auto clf_notes = clf->getNotes();
|
||||||
@@ -212,14 +233,14 @@ namespace platform {
|
|||||||
edges[item] = clf->getNumberOfEdges();
|
edges[item] = clf->getNumberOfEdges();
|
||||||
num_states[item] = clf->getNumberOfStates();
|
num_states[item] = clf->getNumberOfStates();
|
||||||
train_time[item] = train_timer.getDuration();
|
train_time[item] = train_timer.getDuration();
|
||||||
double accuracy_train_value = 0.0;
|
double score_train_value = 0.0;
|
||||||
//
|
//
|
||||||
// Score train
|
// Score train
|
||||||
//
|
//
|
||||||
if (!no_train_score) {
|
if (!no_train_score) {
|
||||||
auto y_predict = clf->predict(X_train);
|
auto y_proba_train = clf->predict_proba(X_train);
|
||||||
Scores scores(y_train, y_predict, num_classes, labels);
|
Scores scores(y_train, y_proba_train, num_classes, labels);
|
||||||
accuracy_train_value = scores.accuracy();
|
score_train_value = score == score_t::ACCURACY ? scores.accuracy() : scores.auc();
|
||||||
confusion_matrices_train.push_back(scores.get_confusion_matrix_json(true));
|
confusion_matrices_train.push_back(scores.get_confusion_matrix_json(true));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@@ -228,33 +249,44 @@ namespace platform {
|
|||||||
if (!quiet)
|
if (!quiet)
|
||||||
showProgress(nfold + 1, getColor(clf->getStatus()), "c");
|
showProgress(nfold + 1, getColor(clf->getStatus()), "c");
|
||||||
test_timer.start();
|
test_timer.start();
|
||||||
auto y_predict = clf->predict(X_test);
|
// auto y_predict = clf->predict(X_test);
|
||||||
Scores scores(y_test, y_predict, num_classes, labels);
|
auto y_proba_test = clf->predict_proba(X_test);
|
||||||
auto accuracy_test_value = scores.accuracy();
|
Scores scores(y_test, y_proba_test, num_classes, labels);
|
||||||
|
auto score_test_value = score == score_t::ACCURACY ? scores.accuracy() : scores.auc();
|
||||||
test_time[item] = test_timer.getDuration();
|
test_time[item] = test_timer.getDuration();
|
||||||
accuracy_train[item] = accuracy_train_value;
|
score_train[item] = score_train_value;
|
||||||
accuracy_test[item] = accuracy_test_value;
|
score_test[item] = score_test_value;
|
||||||
confusion_matrices.push_back(scores.get_confusion_matrix_json(true));
|
confusion_matrices.push_back(scores.get_confusion_matrix_json(true));
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
std::cout << "\b\b\b, " << flush;
|
std::cout << "\b\b\b, " << flush;
|
||||||
//
|
//
|
||||||
// Store results and times in std::vector
|
// Store results and times in std::vector
|
||||||
//
|
//
|
||||||
partial_result.addScoreTrain(accuracy_train_value);
|
partial_result.addScoreTrain(score_train_value);
|
||||||
partial_result.addScoreTest(accuracy_test_value);
|
partial_result.addScoreTest(score_test_value);
|
||||||
partial_result.addTimeTrain(train_time[item].item<double>());
|
partial_result.addTimeTrain(train_time[item].item<double>());
|
||||||
partial_result.addTimeTest(test_time[item].item<double>());
|
partial_result.addTimeTest(test_time[item].item<double>());
|
||||||
item++;
|
item++;
|
||||||
|
if (graph) {
|
||||||
|
std::string result = "";
|
||||||
|
for (const auto& line : clf->graph()) {
|
||||||
|
result += line + "\n";
|
||||||
|
}
|
||||||
|
graphs.push_back(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!quiet) {
|
||||||
|
seed_timer.stop();
|
||||||
|
std::cout << "end. [" << seed_timer.getDurationString() << "]" << std::endl;
|
||||||
}
|
}
|
||||||
if (!quiet)
|
|
||||||
std::cout << "end. " << flush;
|
|
||||||
delete fold;
|
delete fold;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Store result totals in Result
|
// Store result totals in Result
|
||||||
//
|
//
|
||||||
partial_result.setScoreTest(torch::mean(accuracy_test).item<double>()).setScoreTrain(torch::mean(accuracy_train).item<double>());
|
partial_result.setGraph(graphs);
|
||||||
partial_result.setScoreTestStd(torch::std(accuracy_test).item<double>()).setScoreTrainStd(torch::std(accuracy_train).item<double>());
|
partial_result.setScoreTest(torch::mean(score_test).item<double>()).setScoreTrain(torch::mean(score_train).item<double>());
|
||||||
|
partial_result.setScoreTestStd(torch::std(score_test).item<double>()).setScoreTrainStd(torch::std(score_train).item<double>());
|
||||||
partial_result.setTrainTime(torch::mean(train_time).item<double>()).setTestTime(torch::mean(test_time).item<double>());
|
partial_result.setTrainTime(torch::mean(train_time).item<double>()).setTestTime(torch::mean(test_time).item<double>());
|
||||||
partial_result.setTestTimeStd(torch::std(test_time).item<double>()).setTrainTimeStd(torch::std(train_time).item<double>());
|
partial_result.setTestTimeStd(torch::std(test_time).item<double>()).setTrainTimeStd(torch::std(train_time).item<double>());
|
||||||
partial_result.setNodes(torch::mean(nodes).item<double>()).setLeaves(torch::mean(edges).item<double>()).setDepth(torch::mean(num_states).item<double>());
|
partial_result.setNodes(torch::mean(nodes).item<double>()).setLeaves(torch::mean(edges).item<double>()).setDepth(torch::mean(num_states).item<double>());
|
||||||
|
@@ -7,10 +7,11 @@
|
|||||||
#include "bayesnet/BaseClassifier.h"
|
#include "bayesnet/BaseClassifier.h"
|
||||||
#include "HyperParameters.h"
|
#include "HyperParameters.h"
|
||||||
#include "results/Result.h"
|
#include "results/Result.h"
|
||||||
|
#include "bayesnet/network/Network.h"
|
||||||
|
|
||||||
namespace platform {
|
namespace platform {
|
||||||
using json = nlohmann::ordered_json;
|
using json = nlohmann::ordered_json;
|
||||||
|
enum class score_t { NONE, ACCURACY, ROC_AUC_OVR };
|
||||||
class Experiment {
|
class Experiment {
|
||||||
public:
|
public:
|
||||||
Experiment() = default;
|
Experiment() = default;
|
||||||
@@ -24,6 +25,21 @@ namespace platform {
|
|||||||
{
|
{
|
||||||
this->discretization_algo = discretization_algo; this->result.setDiscretizationAlgorithm(discretization_algo); return *this;
|
this->discretization_algo = discretization_algo; this->result.setDiscretizationAlgorithm(discretization_algo); return *this;
|
||||||
}
|
}
|
||||||
|
Experiment& setSmoothSrategy(const std::string& smooth_strategy)
|
||||||
|
{
|
||||||
|
this->smooth_strategy = smooth_strategy; this->result.setSmoothStrategy(smooth_strategy);
|
||||||
|
if (smooth_strategy == "ORIGINAL")
|
||||||
|
smooth_type = bayesnet::Smoothing_t::ORIGINAL;
|
||||||
|
else if (smooth_strategy == "LAPLACE")
|
||||||
|
smooth_type = bayesnet::Smoothing_t::LAPLACE;
|
||||||
|
else if (smooth_strategy == "CESTNIK")
|
||||||
|
smooth_type = bayesnet::Smoothing_t::CESTNIK;
|
||||||
|
else {
|
||||||
|
std::cerr << "Experiment: Unknown smoothing strategy: " << smooth_strategy << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
Experiment& setLanguageVersion(const std::string& language_version) { this->result.setLanguageVersion(language_version); return *this; }
|
Experiment& setLanguageVersion(const std::string& language_version) { this->result.setLanguageVersion(language_version); return *this; }
|
||||||
Experiment& setDiscretized(bool discretized) { this->discretized = discretized; result.setDiscretized(discretized); return *this; }
|
Experiment& setDiscretized(bool discretized) { this->discretized = discretized; result.setDiscretized(discretized); return *this; }
|
||||||
Experiment& setStratified(bool stratified) { this->stratified = stratified; result.setStratified(stratified); return *this; }
|
Experiment& setStratified(bool stratified) { this->stratified = stratified; result.setStratified(stratified); return *this; }
|
||||||
@@ -32,17 +48,21 @@ namespace platform {
|
|||||||
Experiment& addRandomSeed(int randomSeed) { randomSeeds.push_back(randomSeed); result.addSeed(randomSeed); return *this; }
|
Experiment& addRandomSeed(int randomSeed) { randomSeeds.push_back(randomSeed); result.addSeed(randomSeed); return *this; }
|
||||||
Experiment& setDuration(float duration) { this->result.setDuration(duration); return *this; }
|
Experiment& setDuration(float duration) { this->result.setDuration(duration); return *this; }
|
||||||
Experiment& setHyperparameters(const HyperParameters& hyperparameters_) { this->hyperparameters = hyperparameters_; return *this; }
|
Experiment& setHyperparameters(const HyperParameters& hyperparameters_) { this->hyperparameters = hyperparameters_; return *this; }
|
||||||
void cross_validation(const std::string& fileName, bool quiet, bool no_train_score, bool generate_fold_files);
|
void cross_validation(const std::string& fileName, bool quiet, bool no_train_score, bool generate_fold_files, bool graph);
|
||||||
void go(std::vector<std::string> filesToProcess, bool quiet, bool no_train_score, bool generate_fold_files);
|
void go(std::vector<std::string> filesToProcess, bool quiet, bool no_train_score, bool generate_fold_files, bool graph);
|
||||||
void saveResult();
|
void saveResult();
|
||||||
void show();
|
void show();
|
||||||
|
void saveGraph();
|
||||||
void report(bool classification_report = false);
|
void report(bool classification_report = false);
|
||||||
private:
|
private:
|
||||||
|
score_t parse_score() const;
|
||||||
Result result;
|
Result result;
|
||||||
bool discretized{ false }, stratified{ false };
|
bool discretized{ false }, stratified{ false };
|
||||||
std::vector<PartialResult> results;
|
std::vector<PartialResult> results;
|
||||||
std::vector<int> randomSeeds;
|
std::vector<int> randomSeeds;
|
||||||
std::string discretization_algo;
|
std::string discretization_algo;
|
||||||
|
std::string smooth_strategy;
|
||||||
|
bayesnet::Smoothing_t smooth_type{ bayesnet::Smoothing_t::NONE };
|
||||||
HyperParameters hyperparameters;
|
HyperParameters hyperparameters;
|
||||||
int nfolds{ 0 };
|
int nfolds{ 0 };
|
||||||
int max_name{ 7 }; // max length of dataset name for formatting (default 7)
|
int max_name{ 7 }; // max length of dataset name for formatting (default 7)
|
||||||
|
@@ -10,16 +10,9 @@ namespace platform {
|
|||||||
for (const auto& item : datasets) {
|
for (const auto& item : datasets) {
|
||||||
hyperparameters[item] = hyperparameters_;
|
hyperparameters[item] = hyperparameters_;
|
||||||
}
|
}
|
||||||
|
normalize_nested(datasets);
|
||||||
}
|
}
|
||||||
// https://www.techiedelight.com/implode-a-vector-of-strings-into-a-comma-separated-string-in-cpp/
|
HyperParameters::HyperParameters(const std::vector<std::string>& datasets, const std::string& hyperparameters_file, bool best)
|
||||||
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
|
// Check if file exists
|
||||||
std::ifstream file(hyperparameters_file);
|
std::ifstream file(hyperparameters_file);
|
||||||
@@ -28,7 +21,14 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
// Check if file is a json
|
// Check if file is a json
|
||||||
json file_hyperparameters = json::parse(file);
|
json file_hyperparameters = json::parse(file);
|
||||||
auto input_hyperparameters = file_hyperparameters["results"];
|
json input_hyperparameters;
|
||||||
|
if (best) {
|
||||||
|
for (const auto& [key, value] : file_hyperparameters.items()) {
|
||||||
|
input_hyperparameters[key]["hyperparameters"] = value[1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
input_hyperparameters = file_hyperparameters["results"];
|
||||||
|
}
|
||||||
// Check if hyperparameters are valid
|
// Check if hyperparameters are valid
|
||||||
for (const auto& dataset : datasets) {
|
for (const auto& dataset : datasets) {
|
||||||
if (!input_hyperparameters.contains(dataset)) {
|
if (!input_hyperparameters.contains(dataset)) {
|
||||||
@@ -38,6 +38,24 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
hyperparameters[dataset] = input_hyperparameters[dataset]["hyperparameters"].get<json>();
|
hyperparameters[dataset] = input_hyperparameters[dataset]["hyperparameters"].get<json>();
|
||||||
}
|
}
|
||||||
|
normalize_nested(datasets);
|
||||||
|
}
|
||||||
|
void HyperParameters::normalize_nested(const std::vector<std::string>& datasets)
|
||||||
|
{
|
||||||
|
// for (const auto& dataset : datasets) {
|
||||||
|
// if (hyperparameters[dataset].contains("be_hyperparams")) {
|
||||||
|
// // Odte has base estimator hyperparameters set this way
|
||||||
|
// hyperparameters[dataset]["be_hyperparams"] = hyperparameters[dataset]["be_hyperparams"].dump();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
// 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();
|
||||||
}
|
}
|
||||||
void HyperParameters::check(const std::vector<std::string>& valid, const std::string& fileName)
|
void HyperParameters::check(const std::vector<std::string>& valid, const std::string& fileName)
|
||||||
{
|
{
|
||||||
|
@@ -10,14 +10,18 @@ namespace platform {
|
|||||||
class HyperParameters {
|
class HyperParameters {
|
||||||
public:
|
public:
|
||||||
HyperParameters() = default;
|
HyperParameters() = default;
|
||||||
|
// Constructor to use command line hyperparameters
|
||||||
explicit HyperParameters(const std::vector<std::string>& datasets, const json& hyperparameters_);
|
explicit HyperParameters(const std::vector<std::string>& datasets, const json& hyperparameters_);
|
||||||
explicit HyperParameters(const std::vector<std::string>& datasets, const std::string& hyperparameters_file);
|
// Constructor to use hyperparameters file generated by grid or by best results
|
||||||
|
explicit HyperParameters(const std::vector<std::string>& datasets, const std::string& hyperparameters_file, bool best = false);
|
||||||
~HyperParameters() = default;
|
~HyperParameters() = default;
|
||||||
bool notEmpty(const std::string& key) const { return !hyperparameters.at(key).empty(); }
|
bool notEmpty(const std::string& key) const { return !hyperparameters.at(key).empty(); }
|
||||||
void check(const std::vector<std::string>& valid, const std::string& fileName);
|
void check(const std::vector<std::string>& valid, const std::string& fileName);
|
||||||
json get(const std::string& fileName);
|
json get(const std::string& fileName);
|
||||||
private:
|
private:
|
||||||
|
void normalize_nested(const std::vector<std::string>& datasets);
|
||||||
std::map<std::string, json> hyperparameters;
|
std::map<std::string, json> hyperparameters;
|
||||||
|
bool best = false; // Used to separate grid/best hyperparameters as the format of those files are different
|
||||||
};
|
};
|
||||||
} /* namespace platform */
|
} /* namespace platform */
|
||||||
#endif
|
#endif
|
@@ -15,6 +15,7 @@ namespace platform {
|
|||||||
data["times_train"] = json::array();
|
data["times_train"] = json::array();
|
||||||
data["times_test"] = json::array();
|
data["times_test"] = json::array();
|
||||||
data["notes"] = json::array();
|
data["notes"] = json::array();
|
||||||
|
data["graph"] = json::array();
|
||||||
data["train_time"] = 0.0;
|
data["train_time"] = 0.0;
|
||||||
data["train_time_std"] = 0.0;
|
data["train_time_std"] = 0.0;
|
||||||
data["test_time"] = 0.0;
|
data["test_time"] = 0.0;
|
||||||
@@ -27,6 +28,12 @@ namespace platform {
|
|||||||
data["notes"].insert(data["notes"].end(), notes_.begin(), notes_.end());
|
data["notes"].insert(data["notes"].end(), notes_.begin(), notes_.end());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
PartialResult& setGraph(const std::vector<std::string>& graph)
|
||||||
|
{
|
||||||
|
json graph_ = graph;
|
||||||
|
data["graph"].insert(data["graph"].end(), graph_.begin(), graph_.end());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
PartialResult& setConfusionMatrices(const json& confusion_matrices) { data["confusion_matrices"] = confusion_matrices; return *this; }
|
PartialResult& setConfusionMatrices(const json& confusion_matrices) { data["confusion_matrices"] = confusion_matrices; return *this; }
|
||||||
PartialResult& setConfusionMatricesTrain(const json& confusion_matrices) { data["confusion_matrices_train"] = confusion_matrices; return *this; }
|
PartialResult& setConfusionMatricesTrain(const json& confusion_matrices) { data["confusion_matrices_train"] = confusion_matrices; return *this; }
|
||||||
PartialResult& setHyperparameters(const json& hyperparameters) { data["hyperparameters"] = hyperparameters; return *this; }
|
PartialResult& setHyperparameters(const json& hyperparameters) { data["hyperparameters"] = hyperparameters; return *this; }
|
||||||
|
67
src/main/RocAuc.cpp
Normal file
67
src/main/RocAuc.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <numeric>
|
||||||
|
#include <utility>
|
||||||
|
#include "RocAuc.h"
|
||||||
|
namespace platform {
|
||||||
|
|
||||||
|
double RocAuc::compute(const torch::Tensor& y_proba, const torch::Tensor& labels)
|
||||||
|
{
|
||||||
|
size_t nClasses = y_proba.size(1);
|
||||||
|
// In binary classification problem there's no need to calculate the average of the AUCs
|
||||||
|
if (nClasses == 2)
|
||||||
|
nClasses = 1;
|
||||||
|
size_t nSamples = y_proba.size(0);
|
||||||
|
y_test = tensorToVector(labels);
|
||||||
|
std::vector<double> aucScores(nClasses, 0.0);
|
||||||
|
for (size_t classIdx = 0; classIdx < nClasses; ++classIdx) {
|
||||||
|
scoresAndLabels.clear();
|
||||||
|
for (size_t i = 0; i < nSamples; ++i) {
|
||||||
|
scoresAndLabels.emplace_back(y_proba[i][classIdx].item<float>(), y_test[i] == classIdx ? 1 : 0);
|
||||||
|
}
|
||||||
|
aucScores[classIdx] = compute_common(nSamples, classIdx);
|
||||||
|
}
|
||||||
|
return std::accumulate(aucScores.begin(), aucScores.end(), 0.0) / nClasses;
|
||||||
|
}
|
||||||
|
double RocAuc::compute(const std::vector<std::vector<double>>& y_proba, const std::vector<int>& labels)
|
||||||
|
{
|
||||||
|
y_test = labels;
|
||||||
|
size_t nClasses = y_proba[0].size();
|
||||||
|
// In binary classification problem there's no need to calculate the average of the AUCs
|
||||||
|
if (nClasses == 2)
|
||||||
|
nClasses = 1;
|
||||||
|
size_t nSamples = y_proba.size();
|
||||||
|
std::vector<double> aucScores(nClasses, 0.0);
|
||||||
|
for (size_t classIdx = 0; classIdx < nClasses; ++classIdx) {
|
||||||
|
scoresAndLabels.clear();
|
||||||
|
for (size_t i = 0; i < nSamples; ++i) {
|
||||||
|
scoresAndLabels.emplace_back(y_proba[i][classIdx], labels[i] == classIdx ? 1 : 0);
|
||||||
|
}
|
||||||
|
aucScores[classIdx] = compute_common(nSamples, classIdx);
|
||||||
|
}
|
||||||
|
return std::accumulate(aucScores.begin(), aucScores.end(), 0.0) / nClasses;
|
||||||
|
}
|
||||||
|
double RocAuc::compute_common(size_t nSamples, size_t classIdx)
|
||||||
|
{
|
||||||
|
std::sort(scoresAndLabels.begin(), scoresAndLabels.end(), std::greater<>());
|
||||||
|
std::vector<double> tpr, fpr;
|
||||||
|
double tp = 0, fp = 0;
|
||||||
|
double totalPos = std::count(y_test.begin(), y_test.end(), classIdx);
|
||||||
|
double totalNeg = nSamples - totalPos;
|
||||||
|
|
||||||
|
for (const auto& [score, label] : scoresAndLabels) {
|
||||||
|
if (label == 1) {
|
||||||
|
tp += 1;
|
||||||
|
} else {
|
||||||
|
fp += 1;
|
||||||
|
}
|
||||||
|
tpr.push_back(tp / totalPos);
|
||||||
|
fpr.push_back(fp / totalNeg);
|
||||||
|
}
|
||||||
|
double auc = 0.0;
|
||||||
|
for (size_t i = 1; i < tpr.size(); ++i) {
|
||||||
|
auc += 0.5 * (fpr[i] - fpr[i - 1]) * (tpr[i] + tpr[i - 1]);
|
||||||
|
}
|
||||||
|
return auc;
|
||||||
|
}
|
||||||
|
}
|
21
src/main/RocAuc.h
Normal file
21
src/main/RocAuc.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef ROCAUC_H
|
||||||
|
#define ROCAUC_H
|
||||||
|
#include <torch/torch.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
namespace platform {
|
||||||
|
using json = nlohmann::ordered_json;
|
||||||
|
class RocAuc {
|
||||||
|
public:
|
||||||
|
RocAuc() = default;
|
||||||
|
double compute(const std::vector<std::vector<double>>& y_proba, const std::vector<int>& y_test);
|
||||||
|
double compute(const torch::Tensor& y_proba, const torch::Tensor& y_test);
|
||||||
|
private:
|
||||||
|
double compute_common(size_t nSamples, size_t classIdx);
|
||||||
|
std::vector<std::pair<double, int>> scoresAndLabels;
|
||||||
|
std::vector<int> y_test;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,13 +1,15 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "Scores.h"
|
#include "Scores.h"
|
||||||
|
#include "common/Utils.h" // tensorToVector
|
||||||
#include "common/Colors.h"
|
#include "common/Colors.h"
|
||||||
namespace platform {
|
namespace platform {
|
||||||
Scores::Scores(torch::Tensor& y_test, torch::Tensor& y_pred, int num_classes, std::vector<std::string> labels) : num_classes(num_classes), labels(labels)
|
Scores::Scores(torch::Tensor& y_test, torch::Tensor& y_proba, int num_classes, std::vector<std::string> labels) : num_classes(num_classes), labels(labels), y_test(y_test), y_proba(y_proba)
|
||||||
{
|
{
|
||||||
if (labels.size() == 0) {
|
if (labels.size() == 0) {
|
||||||
init_default_labels();
|
init_default_labels();
|
||||||
}
|
}
|
||||||
total = y_test.size(0);
|
total = y_test.size(0);
|
||||||
|
auto y_pred = y_proba.argmax(1);
|
||||||
accuracy_value = (y_pred == y_test).sum().item<float>() / total;
|
accuracy_value = (y_pred == y_test).sum().item<float>() / total;
|
||||||
init_confusion_matrix();
|
init_confusion_matrix();
|
||||||
for (int i = 0; i < total; i++) {
|
for (int i = 0; i < total; i++) {
|
||||||
@@ -40,6 +42,48 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
compute_accuracy_value();
|
compute_accuracy_value();
|
||||||
}
|
}
|
||||||
|
float Scores::auc()
|
||||||
|
{
|
||||||
|
size_t nSamples = y_test.numel();
|
||||||
|
if (nSamples == 0) return 0;
|
||||||
|
// In binary classification problem there's no need to calculate the average of the AUCs
|
||||||
|
auto nClasses = num_classes;
|
||||||
|
if (num_classes == 2)
|
||||||
|
nClasses = 1;
|
||||||
|
auto y_testv = tensorToVector<int>(y_test);
|
||||||
|
std::vector<double> aucScores(nClasses, 0.0);
|
||||||
|
std::vector<std::pair<double, int>> scoresAndLabels;
|
||||||
|
for (size_t classIdx = 0; classIdx < nClasses; ++classIdx) {
|
||||||
|
if (classIdx >= y_proba.size(1)) {
|
||||||
|
std::cerr << "AUC warning - class index out of range" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
scoresAndLabels.clear();
|
||||||
|
for (size_t i = 0; i < nSamples; ++i) {
|
||||||
|
scoresAndLabels.emplace_back(y_proba[i][classIdx].item<float>(), y_testv[i] == classIdx ? 1 : 0);
|
||||||
|
}
|
||||||
|
std::sort(scoresAndLabels.begin(), scoresAndLabels.end(), std::greater<>());
|
||||||
|
std::vector<double> tpr, fpr;
|
||||||
|
double tp = 0, fp = 0;
|
||||||
|
double totalPos = std::count(y_testv.begin(), y_testv.end(), classIdx);
|
||||||
|
double totalNeg = nSamples - totalPos;
|
||||||
|
for (const auto& [score, label] : scoresAndLabels) {
|
||||||
|
if (label == 1) {
|
||||||
|
tp += 1;
|
||||||
|
} else {
|
||||||
|
fp += 1;
|
||||||
|
}
|
||||||
|
tpr.push_back(tp / totalPos);
|
||||||
|
fpr.push_back(fp / totalNeg);
|
||||||
|
}
|
||||||
|
double auc = 0.0;
|
||||||
|
for (size_t i = 1; i < tpr.size(); ++i) {
|
||||||
|
auc += 0.5 * (fpr[i] - fpr[i - 1]) * (tpr[i] + tpr[i - 1]);
|
||||||
|
}
|
||||||
|
aucScores[classIdx] = auc;
|
||||||
|
}
|
||||||
|
return std::accumulate(aucScores.begin(), aucScores.end(), 0.0) / nClasses;
|
||||||
|
}
|
||||||
Scores Scores::create_aggregate(const json& data, const std::string key)
|
Scores Scores::create_aggregate(const json& data, const std::string key)
|
||||||
{
|
{
|
||||||
auto scores = Scores(data[key][0]);
|
auto scores = Scores(data[key][0]);
|
||||||
|
@@ -9,10 +9,11 @@ namespace platform {
|
|||||||
using json = nlohmann::ordered_json;
|
using json = nlohmann::ordered_json;
|
||||||
class Scores {
|
class Scores {
|
||||||
public:
|
public:
|
||||||
Scores(torch::Tensor& y_test, torch::Tensor& y_pred, int num_classes, std::vector<std::string> labels = {});
|
Scores(torch::Tensor& y_test, torch::Tensor& y_proba, int num_classes, std::vector<std::string> labels = {});
|
||||||
explicit Scores(const json& confusion_matrix_);
|
explicit Scores(const json& confusion_matrix_);
|
||||||
static Scores create_aggregate(const json& data, const std::string key);
|
static Scores create_aggregate(const json& data, const std::string key);
|
||||||
float accuracy();
|
float accuracy();
|
||||||
|
float auc();
|
||||||
float f1_score(int num_class);
|
float f1_score(int num_class);
|
||||||
float f1_weighted();
|
float f1_weighted();
|
||||||
float f1_macro();
|
float f1_macro();
|
||||||
@@ -34,6 +35,9 @@ namespace platform {
|
|||||||
int total;
|
int total;
|
||||||
std::vector<std::string> labels;
|
std::vector<std::string> labels;
|
||||||
torch::Tensor confusion_matrix; // Rows ar actual, columns are predicted
|
torch::Tensor confusion_matrix; // Rows ar actual, columns are predicted
|
||||||
|
torch::Tensor null_t; // Covenient null tensor needed when confusion_matrix constructor is used
|
||||||
|
torch::Tensor& y_test = null_t; // for ROC AUC
|
||||||
|
torch::Tensor& y_proba = null_t; // for ROC AUC
|
||||||
int label_len = 16;
|
int label_len = 16;
|
||||||
int dlen = 9;
|
int dlen = 9;
|
||||||
int ndec = 7;
|
int ndec = 7;
|
||||||
|
@@ -1,21 +0,0 @@
|
|||||||
#ifndef COMMAND_PARSER_H
|
|
||||||
#define COMMAND_PARSER_H
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <tuple>
|
|
||||||
|
|
||||||
namespace platform {
|
|
||||||
class CommandParser {
|
|
||||||
public:
|
|
||||||
CommandParser() = default;
|
|
||||||
std::tuple<char, int, bool> parse(const std::string& color, const std::vector<std::tuple<std::string, char, bool>>& options, const char defaultCommand, const int minIndex, const int maxIndex);
|
|
||||||
char getCommand() const { return command; };
|
|
||||||
int getIndex() const { return index; };
|
|
||||||
std::string getErrorMessage() const { return errorMessage; };
|
|
||||||
private:
|
|
||||||
std::string errorMessage;
|
|
||||||
char command;
|
|
||||||
int index;
|
|
||||||
};
|
|
||||||
} /* namespace platform */
|
|
||||||
#endif
|
|
@@ -3,29 +3,33 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "folding.hpp"
|
#include "folding.hpp"
|
||||||
#include "common/Colors.h"
|
|
||||||
#include "common/CLocale.h"
|
#include "common/CLocale.h"
|
||||||
#include "common/Paths.h"
|
#include "common/Paths.h"
|
||||||
#include "CommandParser.h"
|
#include "OptionsMenu.h"
|
||||||
#include "ManageScreen.h"
|
#include "ManageScreen.h"
|
||||||
#include "reports/DatasetsConsole.h"
|
#include "reports/DatasetsConsole.h"
|
||||||
#include "reports/ReportConsole.h"
|
#include "reports/ReportConsole.h"
|
||||||
#include "reports/ReportExcel.h"
|
#include "reports/ReportExcel.h"
|
||||||
#include "reports/ReportExcelCompared.h"
|
#include "reports/ReportExcelCompared.h"
|
||||||
#include <bayesnet/classifiers/TAN.h>
|
#include <bayesnet/classifiers/TAN.h>
|
||||||
#include "CPPFImdlp.h"
|
#include <fimdlp/CPPFImdlp.h>
|
||||||
|
|
||||||
namespace platform {
|
namespace platform {
|
||||||
const std::string STATUS_OK = "Ok.";
|
const std::string STATUS_OK = "Ok.";
|
||||||
const std::string STATUS_COLOR = Colors::GREEN();
|
const std::string STATUS_COLOR = Colors::GREEN();
|
||||||
|
|
||||||
ManageScreen::ManageScreen(int rows, int cols, const std::string& model, const std::string& score, const std::string& platform, bool complete, bool partial, bool compare) :
|
ManageScreen::ManageScreen(int rows, int cols, const std::string& model, const std::string& score, const std::string& platform, bool complete, bool partial, bool compare) :
|
||||||
rows{ rows }, cols{ cols }, complete{ complete }, partial{ partial }, compare{ compare }, didExcel(false), results(ResultsManager(model, score, platform, complete, partial))
|
rows{ rows }, cols{ cols }, complete{ complete }, partial{ partial }, compare{ compare }, didExcel(false), results(ResultsManager(model, score, platform, complete, partial))
|
||||||
{
|
{
|
||||||
results.load();
|
results.load();
|
||||||
openExcel = false;
|
openExcel = false;
|
||||||
workbook = NULL;
|
workbook = NULL;
|
||||||
this->rows = std::max(0, rows - 6); // 6 is the number of lines used by the menu & header
|
maxModel = results.maxModelSize();
|
||||||
cols = std::max(cols, 140);
|
maxTitle = results.maxTitleSize();
|
||||||
|
header_lengths = { 3, 10, maxModel, 11, 10, 12, 2, 3, 7, maxTitle };
|
||||||
|
header_labels = { " #", "Date", "Model", "Score Name", "Score", "Platform", "SD", "C/P", "Time", "Title" };
|
||||||
|
sort_fields = { "Date", "Model", "Score", "Time" };
|
||||||
|
updateSize(rows, cols);
|
||||||
// Initializes the paginator for each output type (experiments, datasets, result)
|
// Initializes the paginator for each output type (experiments, datasets, result)
|
||||||
for (int i = 0; i < static_cast<int>(OutputType::Count); i++) {
|
for (int i = 0; i < static_cast<int>(OutputType::Count); i++) {
|
||||||
paginator.push_back(Paginator(this->rows, results.size()));
|
paginator.push_back(Paginator(this->rows, results.size()));
|
||||||
@@ -36,12 +40,41 @@ namespace platform {
|
|||||||
subIndex = -1;
|
subIndex = -1;
|
||||||
output_type = OutputType::EXPERIMENTS;
|
output_type = OutputType::EXPERIMENTS;
|
||||||
}
|
}
|
||||||
|
void ManageScreen::computeSizes()
|
||||||
|
{
|
||||||
|
int minTitle = 10;
|
||||||
|
// set 10 chars as minimum for Title
|
||||||
|
auto header_title = header_lengths[header_lengths.size() - 1];
|
||||||
|
min_columns = std::accumulate(header_lengths.begin(), header_lengths.end(), 0) + header_lengths.size() - header_title + minTitle;
|
||||||
|
maxTitle = minTitle + cols - min_columns;
|
||||||
|
header_lengths[header_lengths.size() - 1] = maxTitle;
|
||||||
|
cols = std::min(cols, min_columns + maxTitle);
|
||||||
|
for (auto& paginator_ : paginator) {
|
||||||
|
paginator_.setPageSize(rows);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool ManageScreen::checkWrongColumns()
|
||||||
|
{
|
||||||
|
if (min_columns > cols) {
|
||||||
|
std::cerr << Colors::MAGENTA() << "Make screen bigger to fit the results! " + std::to_string(min_columns - cols) + " columns needed! " << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void ManageScreen::updateSize(int rows_, int cols_)
|
||||||
|
{
|
||||||
|
rows = std::max(6, rows_ - 6); // 6 is the number of lines used by the menu & header
|
||||||
|
cols = cols_;
|
||||||
|
computeSizes();
|
||||||
|
}
|
||||||
void ManageScreen::doMenu()
|
void ManageScreen::doMenu()
|
||||||
{
|
{
|
||||||
if (results.empty()) {
|
if (results.empty()) {
|
||||||
std::cout << Colors::MAGENTA() << "No results found!" << Colors::RESET() << std::endl;
|
std::cerr << Colors::MAGENTA() << "No results found!" << Colors::RESET() << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (checkWrongColumns())
|
||||||
|
return;
|
||||||
results.sortResults(sort_field, sort_type);
|
results.sortResults(sort_field, sort_type);
|
||||||
list(STATUS_OK, STATUS_COLOR);
|
list(STATUS_OK, STATUS_COLOR);
|
||||||
menu();
|
menu();
|
||||||
@@ -115,7 +148,6 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
void ManageScreen::list_result(const std::string& status_message, const std::string& status_color)
|
void ManageScreen::list_result(const std::string& status_message, const std::string& status_color)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto data = results.at(index).getJson();
|
auto data = results.at(index).getJson();
|
||||||
ReportConsole report(data, compare);
|
ReportConsole report(data, compare);
|
||||||
auto header_text = report.getHeader();
|
auto header_text = report.getHeader();
|
||||||
@@ -140,11 +172,9 @@ namespace platform {
|
|||||||
// Status Area
|
// Status Area
|
||||||
//
|
//
|
||||||
footer(status_message, status_color);
|
footer(status_message, status_color);
|
||||||
|
|
||||||
}
|
}
|
||||||
void ManageScreen::list_detail(const std::string& status_message, const std::string& status_color)
|
void ManageScreen::list_detail(const std::string& status_message, const std::string& status_color)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto data = results.at(index).getJson();
|
auto data = results.at(index).getJson();
|
||||||
ReportConsole report(data, compare, subIndex);
|
ReportConsole report(data, compare, subIndex);
|
||||||
auto header_text = report.getHeader();
|
auto header_text = report.getHeader();
|
||||||
@@ -169,7 +199,6 @@ namespace platform {
|
|||||||
// Status Area
|
// Status Area
|
||||||
//
|
//
|
||||||
footer(status_message, status_color);
|
footer(status_message, status_color);
|
||||||
|
|
||||||
}
|
}
|
||||||
void ManageScreen::list_datasets(const std::string& status_message, const std::string& status_color)
|
void ManageScreen::list_datasets(const std::string& status_message, const std::string& status_color)
|
||||||
{
|
{
|
||||||
@@ -193,7 +222,6 @@ namespace platform {
|
|||||||
// Status Area
|
// Status Area
|
||||||
//
|
//
|
||||||
footer(status_message, status_color);
|
footer(status_message, status_color);
|
||||||
|
|
||||||
}
|
}
|
||||||
void ManageScreen::list_experiments(const std::string& status_message, const std::string& status_color)
|
void ManageScreen::list_experiments(const std::string& status_message, const std::string& status_color)
|
||||||
{
|
{
|
||||||
@@ -201,17 +229,9 @@ namespace platform {
|
|||||||
// header
|
// header
|
||||||
//
|
//
|
||||||
header();
|
header();
|
||||||
//
|
|
||||||
// Field names
|
|
||||||
//
|
|
||||||
int maxModel = results.maxModelSize();
|
|
||||||
int maxTitle = results.maxTitleSize();
|
|
||||||
std::vector<int> header_lengths = { 3, 10, maxModel, 11, 10, 12, 2, 3, 7, maxTitle };
|
|
||||||
std::cout << Colors::RESET();
|
std::cout << Colors::RESET();
|
||||||
std::string arrow_dn = Symbols::down_arrow + " ";
|
std::string arrow_dn = Symbols::down_arrow + " ";
|
||||||
std::string arrow_up = Symbols::up_arrow + " ";
|
std::string arrow_up = Symbols::up_arrow + " ";
|
||||||
std::vector<std::string> header_labels = { " #", "Date", "Model", "Score Name", "Score", "Platform", "SD", "C/P", "Time", "Title" };
|
|
||||||
std::vector<std::string> sort_fields = { "Date", "Model", "Score", "Time" };
|
|
||||||
for (int i = 0; i < header_labels.size(); i++) {
|
for (int i = 0; i < header_labels.size(); i++) {
|
||||||
std::string suffix = "", color = Colors::GREEN();
|
std::string suffix = "", color = Colors::GREEN();
|
||||||
int diff = 0;
|
int diff = 0;
|
||||||
@@ -230,11 +250,15 @@ namespace platform {
|
|||||||
//
|
//
|
||||||
// Results
|
// Results
|
||||||
//
|
//
|
||||||
|
if (results.empty()) {
|
||||||
|
std::cout << "No results found!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto [index_from, index_to] = paginator[static_cast<int>(output_type)].getOffset();
|
auto [index_from, index_to] = paginator[static_cast<int>(output_type)].getOffset();
|
||||||
for (int i = index_from; i <= index_to; i++) {
|
for (int i = index_from; i <= index_to; i++) {
|
||||||
auto color = (i % 2) ? Colors::BLUE() : Colors::CYAN();
|
auto color = (i % 2) ? Colors::BLUE() : Colors::CYAN();
|
||||||
std::cout << color << std::setw(3) << std::fixed << std::right << i << " ";
|
std::cout << color << std::setw(3) << std::fixed << std::right << i << " ";
|
||||||
std::cout << results.at(i).to_string(maxModel) << std::endl;
|
std::cout << results.at(i).to_string(maxModel, maxTitle) << std::endl;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Status Area
|
// Status Area
|
||||||
@@ -289,16 +313,28 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
std::pair<std::string, std::string> ManageScreen::sortList()
|
std::pair<std::string, std::string> ManageScreen::sortList()
|
||||||
{
|
{
|
||||||
std::cout << Colors::YELLOW() << "Choose sorting field (date='d', score='s', time='t', model='m', ascending='+', descending='-'): ";
|
std::vector<std::tuple<std::string, char, bool>> sortOptions = {
|
||||||
std::vector<std::string> fields = { "Date", "Model", "Score", "Time" };
|
{"date", 'd', false},
|
||||||
|
{"score", 's', false},
|
||||||
|
{"time", 't', false},
|
||||||
|
{"model", 'm', false},
|
||||||
|
{"ascending+", '+', false},
|
||||||
|
{"descending-", '-', false}
|
||||||
|
};
|
||||||
|
auto sortMenu = OptionsMenu(sortOptions, Colors::YELLOW(), Colors::RED(), cols);
|
||||||
std::string invalid_option = "Invalid sorting option";
|
std::string invalid_option = "Invalid sorting option";
|
||||||
std::string line;
|
|
||||||
char option;
|
char option;
|
||||||
getline(std::cin, line);
|
bool parserError = true; // force the first iteration
|
||||||
if (line.size() == 0 || line.size() > 1) {
|
while (parserError) {
|
||||||
return { Colors::RED(), invalid_option };
|
if (checkWrongColumns())
|
||||||
|
return { Colors::RED(), "Invalid column size" };
|
||||||
|
auto [min_index, max_index] = paginator[static_cast<int>(output_type)].getOffset();
|
||||||
|
std::tie(option, index, parserError) = sortMenu.parse(' ', 0, 0);
|
||||||
|
sortMenu.updateColumns(cols);
|
||||||
|
if (parserError) {
|
||||||
|
return { Colors::RED(), invalid_option };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
option = line[0];
|
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case 'd':
|
case 'd':
|
||||||
sort_field = SortField::DATE;
|
sort_field = SortField::DATE;
|
||||||
@@ -322,7 +358,7 @@ namespace platform {
|
|||||||
return { Colors::RED(), invalid_option };
|
return { Colors::RED(), invalid_option };
|
||||||
}
|
}
|
||||||
results.sortResults(sort_field, sort_type);
|
results.sortResults(sort_field, sort_type);
|
||||||
return { Colors::GREEN(), "Sorted by " + fields[static_cast<int>(sort_field)] + " " + (sort_type == SortType::ASC ? "ascending" : "descending") };
|
return { Colors::GREEN(), "Sorted by " + sort_fields[static_cast<int>(sort_field)] + " " + (sort_type == SortType::ASC ? "ascending" : "descending") };
|
||||||
}
|
}
|
||||||
void ManageScreen::menu()
|
void ManageScreen::menu()
|
||||||
{
|
{
|
||||||
@@ -333,17 +369,17 @@ namespace platform {
|
|||||||
std::vector<std::tuple<std::string, char, bool>> mainOptions = {
|
std::vector<std::tuple<std::string, char, bool>> mainOptions = {
|
||||||
{"quit", 'q', false},
|
{"quit", 'q', false},
|
||||||
{"list", 'l', false},
|
{"list", 'l', false},
|
||||||
{"delete", 'D', true},
|
{"Delete", 'D', true},
|
||||||
{"datasets", 'd', false},
|
{"datasets", 'd', false},
|
||||||
{"hide", 'h', true},
|
{"hide", 'h', true},
|
||||||
{"sort", 's', false},
|
{"sort", 's', false},
|
||||||
{"report", 'r', true},
|
{"report", 'r', true},
|
||||||
{"excel", 'e', true},
|
{"excel", 'e', true},
|
||||||
{"title", 't', true},
|
{"title", 't', true},
|
||||||
{"set A", 'a', true},
|
{"set A", 'A', true},
|
||||||
{"set B", 'b', true},
|
{"set B", 'B', true},
|
||||||
{"compare A~B", 'c', false},
|
{"compare A~B", 'c', false},
|
||||||
{"Page", 'p', true},
|
{"page", 'p', true},
|
||||||
{"Page+", '+', false },
|
{"Page+", '+', false },
|
||||||
{"Page-", '-', false}
|
{"Page-", '-', false}
|
||||||
};
|
};
|
||||||
@@ -352,25 +388,33 @@ namespace platform {
|
|||||||
{"quit", 'q', false},
|
{"quit", 'q', false},
|
||||||
{"report", 'r', true},
|
{"report", 'r', true},
|
||||||
{"list", 'l', false},
|
{"list", 'l', false},
|
||||||
{"excel", 'e', false},
|
{"excel", 'e', true},
|
||||||
{"back", 'b', false},
|
{"back", 'b', false},
|
||||||
{"Page", 'p', true},
|
{"page", 'p', true},
|
||||||
{"Page+", '+', false},
|
{"Page+", '+', false},
|
||||||
{"Page-", '-', false}
|
{"Page-", '-', false}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto parser = CommandParser();
|
|
||||||
while (!finished) {
|
while (!finished) {
|
||||||
|
auto main_menu = OptionsMenu(mainOptions, Colors::IGREEN(), Colors::YELLOW(), cols);
|
||||||
|
auto list_menu = OptionsMenu(listOptions, Colors::IBLUE(), Colors::YELLOW(), cols);
|
||||||
|
OptionsMenu& menu = output_type == OutputType::EXPERIMENTS ? main_menu : list_menu;
|
||||||
bool parserError = true; // force the first iteration
|
bool parserError = true; // force the first iteration
|
||||||
while (parserError) {
|
while (parserError) {
|
||||||
|
int index_menu;
|
||||||
auto [min_index, max_index] = paginator[static_cast<int>(output_type)].getOffset();
|
auto [min_index, max_index] = paginator[static_cast<int>(output_type)].getOffset();
|
||||||
|
std::tie(option, index_menu, parserError) = menu.parse('r', min_index, max_index);
|
||||||
if (output_type == OutputType::EXPERIMENTS) {
|
if (output_type == OutputType::EXPERIMENTS) {
|
||||||
std::tie(option, index, parserError) = parser.parse(Colors::IGREEN(), mainOptions, 'r', min_index, max_index);
|
index = index_menu;
|
||||||
} else {
|
} else {
|
||||||
std::tie(option, subIndex, parserError) = parser.parse(Colors::IBLUE(), listOptions, 'r', min_index, max_index);
|
subIndex = index_menu;
|
||||||
}
|
}
|
||||||
|
if (min_columns > cols) {
|
||||||
|
std::cerr << "Make screen bigger to fit the results! " + std::to_string(min_columns - cols) + " columns needed! " << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
menu.updateColumns(cols);
|
||||||
if (parserError) {
|
if (parserError) {
|
||||||
list(parser.getErrorMessage(), Colors::RED());
|
list(menu.getErrorMessage(), Colors::RED());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (option) {
|
switch (option) {
|
||||||
@@ -405,7 +449,7 @@ namespace platform {
|
|||||||
case 'q':
|
case 'q':
|
||||||
finished = true;
|
finished = true;
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'A':
|
||||||
if (index == index_B) {
|
if (index == index_B) {
|
||||||
list("A and B cannot be the same!", Colors::RED());
|
list("A and B cannot be the same!", Colors::RED());
|
||||||
break;
|
break;
|
||||||
@@ -413,7 +457,7 @@ namespace platform {
|
|||||||
index_A = index;
|
index_A = index;
|
||||||
list("A set to " + std::to_string(index), Colors::GREEN());
|
list("A set to " + std::to_string(index), Colors::GREEN());
|
||||||
break;
|
break;
|
||||||
case 'b': // set_b or back to list
|
case 'B': // set_b or back to list
|
||||||
if (output_type == OutputType::EXPERIMENTS) {
|
if (output_type == OutputType::EXPERIMENTS) {
|
||||||
if (index == index_A) {
|
if (index == index_A) {
|
||||||
list("A and B cannot be the same!", Colors::RED());
|
list("A and B cannot be the same!", Colors::RED());
|
||||||
@@ -465,6 +509,7 @@ namespace platform {
|
|||||||
std::cout << "Hiding " << filename << std::endl;
|
std::cout << "Hiding " << filename << std::endl;
|
||||||
results.hideResult(index, Paths::hiddenResults());
|
results.hideResult(index, Paths::hiddenResults());
|
||||||
status_message = filename + " hidden! (moved to " + Paths::hiddenResults() + ")";
|
status_message = filename + " hidden! (moved to " + Paths::hiddenResults() + ")";
|
||||||
|
paginator[static_cast<int>(OutputType::EXPERIMENTS)].setTotal(results.size());
|
||||||
list(status_message, Colors::YELLOW());
|
list(status_message, Colors::YELLOW());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#define MANAGE_SCREEN_H
|
#define MANAGE_SCREEN_H
|
||||||
#include <xlsxwriter.h>
|
#include <xlsxwriter.h>
|
||||||
#include "ResultsManager.h"
|
#include "ResultsManager.h"
|
||||||
|
#include "common/Colors.h"
|
||||||
#include "Paginator.hpp"
|
#include "Paginator.hpp"
|
||||||
|
|
||||||
namespace platform {
|
namespace platform {
|
||||||
@@ -17,6 +18,7 @@ namespace platform {
|
|||||||
ManageScreen(int rows, int cols, const std::string& model, const std::string& score, const std::string& platform, bool complete, bool partial, bool compare);
|
ManageScreen(int rows, int cols, const std::string& model, const std::string& score, const std::string& platform, bool complete, bool partial, bool compare);
|
||||||
~ManageScreen() = default;
|
~ManageScreen() = default;
|
||||||
void doMenu();
|
void doMenu();
|
||||||
|
void updateSize(int rows, int cols);
|
||||||
private:
|
private:
|
||||||
void list(const std::string& status, const std::string& color);
|
void list(const std::string& status, const std::string& color);
|
||||||
void list_experiments(const std::string& status, const std::string& color);
|
void list_experiments(const std::string& status, const std::string& color);
|
||||||
@@ -28,12 +30,15 @@ namespace platform {
|
|||||||
std::string report_compared();
|
std::string report_compared();
|
||||||
std::pair<std::string, std::string> sortList();
|
std::pair<std::string, std::string> sortList();
|
||||||
std::string getVersions();
|
std::string getVersions();
|
||||||
|
void computeSizes();
|
||||||
|
bool checkWrongColumns();
|
||||||
void menu();
|
void menu();
|
||||||
void header();
|
void header();
|
||||||
void footer(const std::string& status, const std::string& color);
|
void footer(const std::string& status, const std::string& color);
|
||||||
OutputType output_type;
|
OutputType output_type;
|
||||||
int rows;
|
int rows;
|
||||||
int cols;
|
int cols;
|
||||||
|
int min_columns;
|
||||||
int index;
|
int index;
|
||||||
int subIndex;
|
int subIndex;
|
||||||
int index_A, index_B; // used for comparison of experiments
|
int index_A, index_B; // used for comparison of experiments
|
||||||
@@ -43,6 +48,10 @@ namespace platform {
|
|||||||
bool complete;
|
bool complete;
|
||||||
bool partial;
|
bool partial;
|
||||||
bool compare;
|
bool compare;
|
||||||
|
int maxModel, maxTitle;
|
||||||
|
std::vector<std::string> header_labels;
|
||||||
|
std::vector<int> header_lengths;
|
||||||
|
std::vector<std::string> sort_fields;
|
||||||
SortField sort_field = SortField::DATE;
|
SortField sort_field = SortField::DATE;
|
||||||
SortType sort_type = SortType::DESC;
|
SortType sort_type = SortType::DESC;
|
||||||
std::vector<Paginator> paginator;
|
std::vector<Paginator> paginator;
|
||||||
|
@@ -1,30 +1,46 @@
|
|||||||
#include "CommandParser.h"
|
#include "OptionsMenu.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "common/Colors.h"
|
|
||||||
#include "common/Utils.h"
|
#include "common/Utils.h"
|
||||||
|
|
||||||
namespace platform {
|
namespace platform {
|
||||||
|
std::string OptionsMenu::to_string()
|
||||||
std::tuple<char, int, bool> CommandParser::parse(const std::string& color, const std::vector<std::tuple<std::string, char, bool>>& options, const char defaultCommand, const int minIndex, const int maxIndex)
|
{
|
||||||
|
bool first = true;
|
||||||
|
std::string result = color_normal + "Options: (";
|
||||||
|
size_t size = 10; // Size of "Options: ("
|
||||||
|
for (auto& option : options) {
|
||||||
|
if (!first) {
|
||||||
|
result += ", ";
|
||||||
|
size += 2;
|
||||||
|
}
|
||||||
|
std::string title = std::get<0>(option);
|
||||||
|
auto pos = title.find(std::get<1>(option));
|
||||||
|
result += color_normal + title.substr(0, pos) + color_bold + title.substr(pos, 1) + color_normal + title.substr(pos + 1);
|
||||||
|
size += title.size();
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if (size + 3 > cols) { // 3 is the size of the "): " at the end
|
||||||
|
result = "";
|
||||||
|
first = true;
|
||||||
|
for (auto& option : options) {
|
||||||
|
if (!first) {
|
||||||
|
result += color_normal + ", ";
|
||||||
|
}
|
||||||
|
result += color_bold + std::get<1>(option);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += "): ";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
std::tuple<char, int, bool> OptionsMenu::parse(char defaultCommand, int minIndex, int maxIndex)
|
||||||
{
|
{
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
while (!finished) {
|
while (!finished) {
|
||||||
std::stringstream oss;
|
std::cout << to_string();
|
||||||
std::string line;
|
std::string line;
|
||||||
oss << color << "Options (";
|
|
||||||
bool first = true;
|
|
||||||
for (auto& option : options) {
|
|
||||||
if (first) {
|
|
||||||
first = false;
|
|
||||||
} else {
|
|
||||||
oss << ", ";
|
|
||||||
}
|
|
||||||
oss << std::get<char>(option) << "=" << std::get<std::string>(option);
|
|
||||||
}
|
|
||||||
oss << "): ";
|
|
||||||
std::cout << oss.str();
|
|
||||||
getline(std::cin, line);
|
getline(std::cin, line);
|
||||||
line = trim(line);
|
line = trim(line);
|
||||||
if (line.size() == 0) {
|
if (line.size() == 0) {
|
26
src/manage/OptionsMenu.h
Normal file
26
src/manage/OptionsMenu.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef OPTIONS_MENU_H
|
||||||
|
#define OPTIONS_MENU_H
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
namespace platform {
|
||||||
|
class OptionsMenu {
|
||||||
|
public:
|
||||||
|
OptionsMenu(std::vector<std::tuple<std::string, char, bool>>& options, std::string color_normal, std::string color_bold, int cols) : options(options), color_normal(color_normal), color_bold(color_bold), cols(cols) {}
|
||||||
|
std::string to_string();
|
||||||
|
std::tuple<char, int, bool> parse(char defaultCommand, int minIndex, int maxIndex);
|
||||||
|
char getCommand() const { return command; };
|
||||||
|
int getIndex() const { return index; };
|
||||||
|
std::string getErrorMessage() const { return errorMessage; };
|
||||||
|
void updateColumns(int cols) { this->cols = cols; }
|
||||||
|
private:
|
||||||
|
std::vector<std::tuple<std::string, char, bool>>& options;
|
||||||
|
std::string color_normal, color_bold;
|
||||||
|
int cols;
|
||||||
|
std::string errorMessage;
|
||||||
|
char command;
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
} /* namespace platform */
|
||||||
|
#endif
|
@@ -21,7 +21,7 @@ namespace platform {
|
|||||||
// Body header
|
// Body header
|
||||||
row = 2;
|
row = 2;
|
||||||
int col = 0;
|
int col = 0;
|
||||||
for (const auto& name : { "Nº", "Dataset", "Samples", "Features", "#Numer.", "Classes", "Balance" }) {
|
for (const auto& name : { "#", "Dataset", "Samples", "Features", "#Numer.", "Classes", "Balance" }) {
|
||||||
writeString(row, col++, name, "bodyHeader");
|
writeString(row, col++, name, "bodyHeader");
|
||||||
}
|
}
|
||||||
// Body
|
// Body
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#include <locale>
|
#include <locale>
|
||||||
#include "best/BestScore.h"
|
#include "best/BestScore.h"
|
||||||
#include "common/CLocale.h"
|
#include "common/CLocale.h"
|
||||||
|
#include "common/Timer.h"
|
||||||
#include "ReportConsole.h"
|
#include "ReportConsole.h"
|
||||||
#include "main/Scores.h"
|
#include "main/Scores.h"
|
||||||
|
|
||||||
@@ -23,12 +24,30 @@ namespace platform {
|
|||||||
+ " random seeds. " + data["date"].get<std::string>() + " " + data["time"].get<std::string>()
|
+ " random seeds. " + data["date"].get<std::string>() + " " + data["time"].get<std::string>()
|
||||||
);
|
);
|
||||||
sheader << headerLine(data["title"].get<std::string>());
|
sheader << headerLine(data["title"].get<std::string>());
|
||||||
|
std::string discretize_algo = data.find("discretization_algorithm") != data.end() ? data["discretization_algorithm"].get<std::string>() : "ORIGINAL";
|
||||||
|
std::string algorithm = data["discretized"].get<bool>() ? " (" + discretize_algo + ")" : "";
|
||||||
|
std::string smooth = data.find("smooth_strategy") != data.end() ? data["smooth_strategy"].get<std::string>() : "ORIGINAL";
|
||||||
|
std::string stratified;
|
||||||
|
try {
|
||||||
|
stratified = data["stratified"].get<bool>() ? "True" : "False";
|
||||||
|
}
|
||||||
|
catch (nlohmann::json::type_error) {
|
||||||
|
stratified = data["stratified"].get<int>() == 1 ? "True" : "False";
|
||||||
|
}
|
||||||
|
std::string discretized;
|
||||||
|
try {
|
||||||
|
discretized = data["discretized"].get<bool>() ? "True" : "False";
|
||||||
|
}
|
||||||
|
catch (nlohmann::json::type_error) {
|
||||||
|
discretized = data["discretized"].get<int>() == 1 ? "True" : "False";
|
||||||
|
}
|
||||||
sheader << headerLine(
|
sheader << headerLine(
|
||||||
"Random seeds: " + fromVector("seeds") + " Discretized: " + (data["discretized"].get<bool>() ? "True" : "False")
|
"Random seeds: " + fromVector("seeds") + " Discretized: " + discretized + " " + algorithm
|
||||||
+ " Stratified: " + (data["stratified"].get<bool>() ? "True" : "False")
|
+ " Stratified: " + stratified + " Smooth Strategy: " + smooth
|
||||||
);
|
);
|
||||||
oss << "Execution took " << std::setprecision(2) << std::fixed << data["duration"].get<float>()
|
Timer timer;
|
||||||
<< " seconds, " << data["duration"].get<float>() / 3600 << " hours, on " << data["platform"].get<std::string>();
|
oss << "Execution took " << timer.translate2String(data["duration"].get<float>())
|
||||||
|
<< " on " << data["platform"].get<std::string>() << " Language: " << data["language"].get<std::string>();
|
||||||
sheader << headerLine(oss.str());
|
sheader << headerLine(oss.str());
|
||||||
sheader << headerLine("Score is " + data["score_name"].get<std::string>());
|
sheader << headerLine("Score is " + data["score_name"].get<std::string>());
|
||||||
sheader << std::string(MAXL, '*') << std::endl;
|
sheader << std::string(MAXL, '*') << std::endl;
|
||||||
@@ -121,12 +140,35 @@ namespace platform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
line.str("");
|
||||||
|
if (lastResult.find("score_train") == lastResult.end()) {
|
||||||
|
line << headerLine("Train score: -");
|
||||||
|
} else {
|
||||||
|
line << headerLine("Train score: " + std::to_string(lastResult["score_train"].get<double>()));
|
||||||
|
}
|
||||||
|
vbody.push_back(line.str()); sbody << line.str();
|
||||||
line.str(""); line << headerLine(fVector("Train scores: ", lastResult["scores_train"], 14, 12));
|
line.str(""); line << headerLine(fVector("Train scores: ", lastResult["scores_train"], 14, 12));
|
||||||
vbody.push_back(line.str()); sbody << line.str();
|
vbody.push_back(line.str()); sbody << line.str();
|
||||||
|
line.str(""); line << headerLine("Test score: " + std::to_string(lastResult["score"].get<double>()));
|
||||||
|
vbody.push_back(line.str()); sbody << line.str();
|
||||||
line.str(""); line << headerLine(fVector("Test scores: ", lastResult["scores_test"], 14, 12));
|
line.str(""); line << headerLine(fVector("Test scores: ", lastResult["scores_test"], 14, 12));
|
||||||
vbody.push_back(line.str()); sbody << line.str();
|
vbody.push_back(line.str()); sbody << line.str();
|
||||||
|
line.str("");
|
||||||
|
if (lastResult.find("train_time") == lastResult.end()) {
|
||||||
|
line << headerLine("Train time: -");
|
||||||
|
} else {
|
||||||
|
line << headerLine("Train time: " + std::to_string(lastResult["train_time"].get<double>()));
|
||||||
|
}
|
||||||
|
vbody.push_back(line.str()); sbody << line.str();
|
||||||
line.str(""); line << headerLine(fVector("Train times: ", lastResult["times_train"], 10, 3));
|
line.str(""); line << headerLine(fVector("Train times: ", lastResult["times_train"], 10, 3));
|
||||||
vbody.push_back(line.str()); sbody << line.str();
|
vbody.push_back(line.str()); sbody << line.str();
|
||||||
|
line.str("");
|
||||||
|
if (lastResult.find("test_time") == lastResult.end()) {
|
||||||
|
line << headerLine("Test time: -");
|
||||||
|
} else {
|
||||||
|
line << headerLine("Test time: " + std::to_string(lastResult["test_time"].get<double>()));
|
||||||
|
}
|
||||||
|
vbody.push_back(line.str()); sbody << line.str();
|
||||||
line.str(""); line << headerLine(fVector("Test times: ", lastResult["times_test"], 10, 3));
|
line.str(""); line << headerLine(fVector("Test times: ", lastResult["times_test"], 10, 3));
|
||||||
vbody.push_back(line.str()); sbody << line.str();
|
vbody.push_back(line.str()); sbody << line.str();
|
||||||
|
|
||||||
|
@@ -49,7 +49,10 @@ namespace platform {
|
|||||||
worksheet_merge_range(worksheet, 0, 0, 0, 12, message.c_str(), styles["headerFirst"]);
|
worksheet_merge_range(worksheet, 0, 0, 0, 12, message.c_str(), styles["headerFirst"]);
|
||||||
worksheet_merge_range(worksheet, 1, 0, 1, 12, data["title"].get<std::string>().c_str(), styles["headerRest"]);
|
worksheet_merge_range(worksheet, 1, 0, 1, 12, data["title"].get<std::string>().c_str(), styles["headerRest"]);
|
||||||
worksheet_merge_range(worksheet, 2, 0, 3, 0, ("Score is " + data["score_name"].get<std::string>()).c_str(), styles["headerRest"]);
|
worksheet_merge_range(worksheet, 2, 0, 3, 0, ("Score is " + data["score_name"].get<std::string>()).c_str(), styles["headerRest"]);
|
||||||
worksheet_merge_range(worksheet, 2, 1, 3, 3, "Execution time", styles["headerRest"]);
|
writeString(2, 1, "Smooth", "headerRest");
|
||||||
|
std::string smooth = data.find("smooth_strategy") != data.end() ? data["smooth_strategy"].get<std::string>() : "ORIGINAL";
|
||||||
|
writeString(3, 1, smooth, "headerSmall");
|
||||||
|
worksheet_merge_range(worksheet, 2, 2, 3, 3, "Execution time", styles["headerRest"]);
|
||||||
oss << std::setprecision(2) << std::fixed << data["duration"].get<float>() << " s";
|
oss << std::setprecision(2) << std::fixed << data["duration"].get<float>() << " s";
|
||||||
worksheet_merge_range(worksheet, 2, 4, 2, 5, oss.str().c_str(), styles["headerRest"]);
|
worksheet_merge_range(worksheet, 2, 4, 2, 5, oss.str().c_str(), styles["headerRest"]);
|
||||||
oss.str("");
|
oss.str("");
|
||||||
@@ -65,7 +68,9 @@ namespace platform {
|
|||||||
worksheet_merge_range(worksheet, 3, 10, 3, 11, oss.str().c_str(), styles["headerSmall"]);
|
worksheet_merge_range(worksheet, 3, 10, 3, 11, oss.str().c_str(), styles["headerSmall"]);
|
||||||
oss.str("");
|
oss.str("");
|
||||||
oss.clear();
|
oss.clear();
|
||||||
oss << "Discretized: " << (data["discretized"].get<bool>() ? "True" : "False");
|
std::string discretize_algo = data.find("discretization_algorithm") != data.end() ? data["discretization_algorithm"].get<std::string>() : "mdlp";
|
||||||
|
std::string algorithm = data["discretized"].get<bool>() ? " (" + discretize_algo + ")" : "";
|
||||||
|
oss << "Discretized: " << (data["discretized"].get<bool>() ? "True" : "False") << algorithm;
|
||||||
worksheet_write_string(worksheet, 3, 12, oss.str().c_str(), styles["headerSmall"]);
|
worksheet_write_string(worksheet, 3, 12, oss.str().c_str(), styles["headerSmall"]);
|
||||||
}
|
}
|
||||||
void ReportExcel::header_notes(int row)
|
void ReportExcel::header_notes(int row)
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include "common/DotEnv.h"
|
#include "common/DotEnv.h"
|
||||||
#include "common/CLocale.h"
|
#include "common/CLocale.h"
|
||||||
#include "common/Paths.h"
|
#include "common/Paths.h"
|
||||||
|
#include "common/Symbols.h"
|
||||||
#include "Result.h"
|
#include "Result.h"
|
||||||
|
|
||||||
namespace platform {
|
namespace platform {
|
||||||
@@ -71,20 +72,39 @@ namespace platform {
|
|||||||
std::string Result::getFilename() const
|
std::string Result::getFilename() const
|
||||||
{
|
{
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
oss << "results_" << data.at("score_name").get<std::string>() << "_" << data.at("model").get<std::string>() << "_"
|
std::string stratified;
|
||||||
<< data.at("platform").get<std::string>() << "_" << data["date"].get<std::string>() << "_"
|
try {
|
||||||
<< data["time"].get<std::string>() << "_" << (data["stratified"] ? "1" : "0") << ".json";
|
stratified = data["stratified"].get<bool>() ? "1" : "0";
|
||||||
|
}
|
||||||
|
catch (nlohmann::json_abi_v3_11_3::detail::type_error) {
|
||||||
|
stratified = data["stratified"].get<int>() == 1 ? "1" : "0";
|
||||||
|
}
|
||||||
|
oss << "results_"
|
||||||
|
<< data.at("score_name").get<std::string>() << "_"
|
||||||
|
<< data.at("model").get<std::string>() << "_"
|
||||||
|
<< data.at("platform").get<std::string>() << "_"
|
||||||
|
<< data["date"].get<std::string>() << "_"
|
||||||
|
<< data["time"].get<std::string>() << "_"
|
||||||
|
<< stratified << ".json";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
std::string Result::to_string(int maxModel, int maxTitle) const
|
||||||
|
|
||||||
std::string Result::to_string(int maxModel) const
|
|
||||||
{
|
{
|
||||||
auto tmp = ConfigLocale();
|
auto tmp = ConfigLocale();
|
||||||
std::stringstream oss;
|
std::stringstream oss;
|
||||||
std::string s = data["stratified"].get<bool>() ? "S" : "";
|
std::string s, d;
|
||||||
std::string d = data["discretized"].get<bool>() ? "D" : "";
|
try {
|
||||||
std::string sd = s + d;
|
s = data["stratified"].get<bool>() ? "S" : " ";
|
||||||
|
}
|
||||||
|
catch (nlohmann::json_abi_v3_11_3::detail::type_error) {
|
||||||
|
s = data["stratified"].get<int>() == 1 ? "S" : " ";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
d = data["discretized"].get<bool>() ? "D" : " ";
|
||||||
|
}
|
||||||
|
catch (nlohmann::json_abi_v3_11_3::detail::type_error) {
|
||||||
|
d = data["discretized"].get<int>() == 1 ? "D" : " ";
|
||||||
|
}
|
||||||
auto duration = data["duration"].get<double>();
|
auto duration = data["duration"].get<double>();
|
||||||
double durationShow = duration > 3600 ? duration / 3600 : duration > 60 ? duration / 60 : duration;
|
double durationShow = duration > 3600 ? duration / 3600 : duration > 60 ? duration / 60 : duration;
|
||||||
std::string durationUnit = duration > 3600 ? "h" : duration > 60 ? "m" : "s";
|
std::string durationUnit = duration > 3600 ? "h" : duration > 60 ? "m" : "s";
|
||||||
@@ -93,11 +113,15 @@ namespace platform {
|
|||||||
oss << std::setw(11) << std::left << data["score_name"].get<std::string>() << " ";
|
oss << std::setw(11) << std::left << data["score_name"].get<std::string>() << " ";
|
||||||
oss << std::right << std::setw(10) << std::setprecision(7) << std::fixed << score << " ";
|
oss << std::right << std::setw(10) << std::setprecision(7) << std::fixed << score << " ";
|
||||||
oss << std::left << std::setw(12) << data["platform"].get<std::string>() << " ";
|
oss << std::left << std::setw(12) << data["platform"].get<std::string>() << " ";
|
||||||
oss << std::left << std::setw(2) << sd << " ";
|
oss << s << d << " ";
|
||||||
auto completeString = isComplete() ? "C" : "P";
|
auto completeString = isComplete() ? "C" : "P";
|
||||||
oss << std::setw(1) << " " << completeString << " ";
|
oss << std::setw(1) << " " << completeString << " ";
|
||||||
oss << std::setw(5) << std::right << std::setprecision(2) << std::fixed << durationShow << " " << durationUnit << " ";
|
oss << std::setw(5) << std::right << std::setprecision(2) << std::fixed << durationShow << " " << durationUnit << " ";
|
||||||
oss << std::setw(50) << std::left << data["title"].get<std::string>() << " ";
|
auto title = data["title"].get<std::string>();
|
||||||
|
if (title.size() > maxTitle) {
|
||||||
|
title = title.substr(0, maxTitle - 1) + Symbols::ellipsis;
|
||||||
|
}
|
||||||
|
oss << std::setw(maxTitle) << std::left << title;
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -18,7 +18,7 @@ namespace platform {
|
|||||||
void save();
|
void save();
|
||||||
// Getters
|
// Getters
|
||||||
json getJson();
|
json getJson();
|
||||||
std::string to_string(int maxModel) const;
|
std::string to_string(int maxModel, int maxTitle) const;
|
||||||
std::string getFilename() const;
|
std::string getFilename() const;
|
||||||
std::string getDate() const { return data["date"].get<std::string>(); };
|
std::string getDate() const { return data["date"].get<std::string>(); };
|
||||||
std::string getTime() const { return data["time"].get<std::string>(); };
|
std::string getTime() const { return data["time"].get<std::string>(); };
|
||||||
@@ -28,10 +28,12 @@ namespace platform {
|
|||||||
std::string getModel() const { return data["model"].get<std::string>(); };
|
std::string getModel() const { return data["model"].get<std::string>(); };
|
||||||
std::string getPlatform() const { return data["platform"].get<std::string>(); };
|
std::string getPlatform() const { return data["platform"].get<std::string>(); };
|
||||||
std::string getScoreName() const { return data["score_name"].get<std::string>(); };
|
std::string getScoreName() const { return data["score_name"].get<std::string>(); };
|
||||||
|
|
||||||
bool isComplete() const { return complete; };
|
bool isComplete() const { return complete; };
|
||||||
json getData() const { return data; }
|
json getData() const { return data; }
|
||||||
// Setters
|
// Setters
|
||||||
void setTitle(const std::string& title) { data["title"] = title; };
|
void setTitle(const std::string& title) { data["title"] = title; };
|
||||||
|
void setSmoothStrategy(const std::string& smooth_strategy) { data["smooth_strategy"] = smooth_strategy; };
|
||||||
void setDiscretizationAlgorithm(const std::string& discretization_algo) { data["discretization_algorithm"] = discretization_algo; };
|
void setDiscretizationAlgorithm(const std::string& discretization_algo) { data["discretization_algorithm"] = discretization_algo; };
|
||||||
void setLanguage(const std::string& language) { data["language"] = language; };
|
void setLanguage(const std::string& language) { data["language"] = language; };
|
||||||
void setLanguageVersion(const std::string& language_version) { data["language_version"] = language_version; };
|
void setLanguageVersion(const std::string& language_version) { data["language_version"] = language_version; };
|
||||||
@@ -45,7 +47,6 @@ namespace platform {
|
|||||||
void setStratified(bool stratified) { data["stratified"] = stratified; };
|
void setStratified(bool stratified) { data["stratified"] = stratified; };
|
||||||
void setNFolds(int nfolds) { data["folds"] = nfolds; };
|
void setNFolds(int nfolds) { data["folds"] = nfolds; };
|
||||||
void setPlatform(const std::string& platform_name) { data["platform"] = platform_name; };
|
void setPlatform(const std::string& platform_name) { data["platform"] = platform_name; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
json data;
|
json data;
|
||||||
bool complete;
|
bool complete;
|
||||||
|
@@ -20,7 +20,7 @@ namespace platform {
|
|||||||
// Body header
|
// Body header
|
||||||
row = 2;
|
row = 2;
|
||||||
int col = 0;
|
int col = 0;
|
||||||
for (const auto& name : { "Nº", "Model", "Date", "Time", "Score", "Hyperparameters" }) {
|
for (const auto& name : { "#", "Model", "Date", "Time", "Score", "Hyperparameters" }) {
|
||||||
writeString(row, col++, name, "bodyHeader");
|
writeString(row, col++, name, "bodyHeader");
|
||||||
}
|
}
|
||||||
// Body
|
// Body
|
||||||
|
@@ -3,7 +3,7 @@ if(ENABLE_TESTING)
|
|||||||
include_directories(
|
include_directories(
|
||||||
${Platform_SOURCE_DIR}/src
|
${Platform_SOURCE_DIR}/src
|
||||||
${Platform_SOURCE_DIR}/lib/argparse/include
|
${Platform_SOURCE_DIR}/lib/argparse/include
|
||||||
${Platform_SOURCE_DIR}/lib/mdlp
|
${Platform_SOURCE_DIR}/lib/mdlp/src
|
||||||
${Platform_SOURCE_DIR}/lib/Files
|
${Platform_SOURCE_DIR}/lib/Files
|
||||||
${Platform_SOURCE_DIR}/lib/json/include
|
${Platform_SOURCE_DIR}/lib/json/include
|
||||||
${Platform_SOURCE_DIR}/lib/folding
|
${Platform_SOURCE_DIR}/lib/folding
|
||||||
@@ -13,10 +13,10 @@ if(ENABLE_TESTING)
|
|||||||
)
|
)
|
||||||
set(TEST_SOURCES_PLATFORM
|
set(TEST_SOURCES_PLATFORM
|
||||||
TestUtils.cpp TestPlatform.cpp TestResult.cpp TestScores.cpp
|
TestUtils.cpp TestPlatform.cpp TestResult.cpp TestScores.cpp
|
||||||
${Platform_SOURCE_DIR}/src/common/Datasets.cpp ${Platform_SOURCE_DIR}/src/common/Dataset.cpp
|
${Platform_SOURCE_DIR}/src/common/Datasets.cpp ${Platform_SOURCE_DIR}/src/common/Dataset.cpp ${Platform_SOURCE_DIR}/src/common/Discretization.cpp
|
||||||
${Platform_SOURCE_DIR}/src/main/Scores.cpp
|
${Platform_SOURCE_DIR}/src/main/Scores.cpp
|
||||||
)
|
)
|
||||||
add_executable(${TEST_PLATFORM} ${TEST_SOURCES_PLATFORM})
|
add_executable(${TEST_PLATFORM} ${TEST_SOURCES_PLATFORM})
|
||||||
target_link_libraries(${TEST_PLATFORM} PUBLIC "${TORCH_LIBRARIES}" ArffFiles mdlp Catch2::Catch2WithMain BayesNet)
|
target_link_libraries(${TEST_PLATFORM} PUBLIC "${TORCH_LIBRARIES}" mdlp Catch2::Catch2WithMain BayesNet)
|
||||||
add_test(NAME ${TEST_PLATFORM} COMMAND ${TEST_PLATFORM})
|
add_test(NAME ${TEST_PLATFORM} COMMAND ${TEST_PLATFORM})
|
||||||
endif(ENABLE_TESTING)
|
endif(ENABLE_TESTING)
|
||||||
|
@@ -7,14 +7,15 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "TestUtils.h"
|
#include "TestUtils.h"
|
||||||
#include "folding.hpp"
|
#include "folding.hpp"
|
||||||
|
#include <ArffFiles.hpp>
|
||||||
#include <bayesnet/classifiers/TAN.h>
|
#include <bayesnet/classifiers/TAN.h>
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("Test Platform version", "[Platform]")
|
TEST_CASE("Test Platform version", "[Platform]")
|
||||||
{
|
{
|
||||||
std::string version = { platform_project_version.begin(), platform_project_version.end() };
|
std::string version = { platform_project_version.begin(), platform_project_version.end() };
|
||||||
REQUIRE(version == "1.0.4");
|
REQUIRE(version == "1.1.0");
|
||||||
}
|
}
|
||||||
TEST_CASE("Test Folding library version", "[Folding]")
|
TEST_CASE("Test Folding library version", "[Folding]")
|
||||||
{
|
{
|
||||||
@@ -24,10 +25,15 @@ TEST_CASE("Test Folding library version", "[Folding]")
|
|||||||
TEST_CASE("Test BayesNet version", "[BayesNet]")
|
TEST_CASE("Test BayesNet version", "[BayesNet]")
|
||||||
{
|
{
|
||||||
std::string version = bayesnet::TAN().getVersion();
|
std::string version = bayesnet::TAN().getVersion();
|
||||||
REQUIRE(version == "1.0.5.1");
|
REQUIRE(version == "1.0.6");
|
||||||
}
|
}
|
||||||
TEST_CASE("Test mdlp version", "[mdlp]")
|
TEST_CASE("Test mdlp version", "[mdlp]")
|
||||||
{
|
{
|
||||||
std::string version = mdlp::CPPFImdlp::version();
|
std::string version = mdlp::CPPFImdlp::version();
|
||||||
REQUIRE(version == "1.1.2");
|
REQUIRE(version == "2.0.0");
|
||||||
|
}
|
||||||
|
TEST_CASE("Test Arff version", "[Arff]")
|
||||||
|
{
|
||||||
|
std::string version = ArffFiles().version();
|
||||||
|
REQUIRE(version == "1.1.0");
|
||||||
}
|
}
|
@@ -7,19 +7,20 @@
|
|||||||
#include "common/DotEnv.h"
|
#include "common/DotEnv.h"
|
||||||
#include "common/Datasets.h"
|
#include "common/Datasets.h"
|
||||||
#include "common/Paths.h"
|
#include "common/Paths.h"
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("ZeroR comparison in reports", "[Report]")
|
TEST_CASE("ZeroR comparison in reports", "[Report]")
|
||||||
{
|
{
|
||||||
auto dotEnv = platform::DotEnv(true);
|
auto dotEnv = platform::DotEnv(true);
|
||||||
auto margin = 1e-2;
|
auto margin = 1e-4;
|
||||||
std::string dataset = "liver-disorders";
|
std::string dataset_name = "liver-disorders";
|
||||||
auto dt = platform::Datasets(false, platform::Paths::datasets());
|
auto dt = platform::Datasets(false, platform::Paths::datasets());
|
||||||
dt.loadDataset(dataset);
|
auto& dataset = dt.getDataset(dataset_name);
|
||||||
std::vector<int> distribution = dt.getClassesCounts(dataset);
|
dataset.load();
|
||||||
double nSamples = dt.getNSamples(dataset);
|
std::vector<int> distribution = dataset.getClassesCounts();
|
||||||
|
double nSamples = dataset.getNSamples();
|
||||||
std::vector<int>::iterator maxValue = max_element(distribution.begin(), distribution.end());
|
std::vector<int>::iterator maxValue = max_element(distribution.begin(), distribution.end());
|
||||||
double mark = *maxValue / nSamples * (1 + margin);
|
double mark = *maxValue / nSamples * (1 + margin);
|
||||||
REQUIRE(mark == Catch::Approx(0.585507f).epsilon(1e-5));
|
REQUIRE(mark == Catch::Approx(0.57976811f).epsilon(margin));
|
||||||
}
|
}
|
@@ -9,7 +9,7 @@
|
|||||||
#include "common/Paths.h"
|
#include "common/Paths.h"
|
||||||
#include "common/Colors.h"
|
#include "common/Colors.h"
|
||||||
#include "main/Scores.h"
|
#include "main/Scores.h"
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
using json = nlohmann::ordered_json;
|
using json = nlohmann::ordered_json;
|
||||||
auto epsilon = 1e-4;
|
auto epsilon = 1e-4;
|
||||||
@@ -128,7 +128,7 @@ TEST_CASE("Confusion Matrix JSON", "[Scores]")
|
|||||||
REQUIRE(res_json_str["Car"][1] == 2);
|
REQUIRE(res_json_str["Car"][1] == 2);
|
||||||
REQUIRE(res_json_str["Car"][2] == 3);
|
REQUIRE(res_json_str["Car"][2] == 3);
|
||||||
}
|
}
|
||||||
TEST_CASE("Classification Report", "[Scores]") -
|
TEST_CASE("Classification Report", "[Scores]")
|
||||||
{
|
{
|
||||||
std::vector<int> y_test = { 0, 2, 2, 2, 2, 0, 1, 2, 0, 2 };
|
std::vector<int> y_test = { 0, 2, 2, 2, 2, 0, 1, 2, 0, 2 };
|
||||||
std::vector<int> y_pred = { 0, 1, 2, 2, 1, 1, 1, 0, 0, 2 };
|
std::vector<int> y_pred = { 0, 1, 2, 2, 1, 1, 1, 0, 0, 2 };
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#include "TestUtils.h"
|
#include "TestUtils.h"
|
||||||
#include "config.h"
|
#include "config_platform.h"
|
||||||
|
|
||||||
class Paths {
|
class Paths {
|
||||||
public:
|
public:
|
||||||
|
@@ -5,8 +5,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include "ArffFiles.h"
|
#include <ArffFiles.hpp>
|
||||||
#include "CPPFImdlp.h"
|
#include <fimdlp/CPPFImdlp.h>
|
||||||
|
|
||||||
bool file_exists(const std::string& name);
|
bool file_exists(const std::string& name);
|
||||||
std::pair<vector<mdlp::labels_t>, map<std::string, int>> discretize(std::vector<mdlp::samples_t>& X, mdlp::labels_t& y, std::vector<string> features);
|
std::pair<vector<mdlp::labels_t>, map<std::string, int>> discretize(std::vector<mdlp::samples_t>& X, mdlp::labels_t& y, std::vector<string> features);
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
diabetes,class, all
|
diabetes;class;all
|
||||||
ecoli,class, all
|
ecoli;class;all
|
||||||
glass,Type, all
|
glass;Type,all
|
||||||
iris,class, all
|
iris;class;all
|
||||||
kdd_JapaneseVowels,speaker, [2,3,4,5,6,7,8,9,10,11,12,13]
|
kdd_JapaneseVowels;speaker;[2,3,4,5,6,7,8,9,10,11,12,13]
|
||||||
letter,class, all
|
letter;class;all
|
||||||
liver-disorders,selector, all
|
liver-disorders;selector;all
|
||||||
mfeat-factors,class, all
|
mfeat-factors;class;all
|
Reference in New Issue
Block a user