Refactor Result & PartialResult classes

Add title modification to b_manage
This commit is contained in:
2024-02-17 19:09:43 +01:00
parent a1c7dbfea1
commit 53dafa3404
12 changed files with 203 additions and 233 deletions

View File

@@ -22,7 +22,7 @@ set(grid_sources GridSearch.cc GridData.cc HyperParameters.cc Datasets.cc Datase
list(TRANSFORM grid_sources PREPEND ${Platform_MODULES}) list(TRANSFORM grid_sources PREPEND ${Platform_MODULES})
add_executable(b_grid b_grid.cc ${grid_sources}) add_executable(b_grid b_grid.cc ${grid_sources})
add_executable(b_list b_list.cc ${Platform_MODULES}Datasets.cc ${Platform_MODULES}Dataset.cc) add_executable(b_list b_list.cc ${Platform_MODULES}Datasets.cc ${Platform_MODULES}Dataset.cc)
set(main_sources Experiment.cc Datasets.cc Dataset.cc Models.cc HyperParameters.cc ReportConsole.cc ReportBase.cc) set(main_sources Experiment.cc Datasets.cc Dataset.cc Models.cc HyperParameters.cc ReportConsole.cc ReportBase.cc Result.cc)
list(TRANSFORM main_sources PREPEND ${Platform_MODULES}) list(TRANSFORM main_sources PREPEND ${Platform_MODULES})
add_executable(b_main b_main.cc ${main_sources}) add_executable(b_main b_main.cc ${main_sources})
set(manage_sources Results.cc ManageResults.cc CommandParser.cc Result.cc ReportConsole.cc ReportExcel.cc ReportBase.cc Datasets.cc Dataset.cc ExcelFile.cc) set(manage_sources Results.cc ManageResults.cc CommandParser.cc Result.cc ReportConsole.cc ReportExcel.cc ReportBase.cc Datasets.cc Dataset.cc ExcelFile.cc)

View File

@@ -128,7 +128,7 @@ int main(int argc, char** argv)
experiment.go(filesToTest, quiet, no_train_score); experiment.go(filesToTest, quiet, no_train_score);
experiment.setDuration(timer.getDuration()); experiment.setDuration(timer.getDuration());
if (saveResults) { if (saveResults) {
experiment.save(platform::Paths::results()); experiment.saveResult();
} }
if (!quiet) if (!quiet)
experiment.report(); experiment.report();

View File

@@ -36,8 +36,9 @@ namespace platform {
} }
json bests; json bests;
for (const auto& file : files) { for (const auto& file : files) {
auto result = Result(path, file); auto result = Result();
auto data = result.load(); result.load(path, file);
auto data = result.getJson();
for (auto const& item : data.at("results")) { for (auto const& item : data.at("results")) {
bool update = true; bool update = true;
auto datasetName = item.at("dataset").get<std::string>(); auto datasetName = item.at("dataset").get<std::string>();

View File

@@ -1,4 +1,3 @@
#include <fstream>
#include "Experiment.h" #include "Experiment.h"
#include "Datasets.h" #include "Datasets.h"
#include "Models.h" #include "Models.h"
@@ -6,109 +5,27 @@
#include "Paths.h" #include "Paths.h"
namespace platform { namespace platform {
using json = nlohmann::json; using json = nlohmann::json;
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 Experiment::get_file_name()
{
std::string result = "results_" + score_name + "_" + model + "_" + platform + "_" + get_date() + "_" + get_time() + "_" + (stratified ? "1" : "0") + ".json";
return result;
}
json Experiment::build_json() void Experiment::saveResult()
{ {
json result; result.save();
result["title"] = title;
result["date"] = get_date();
result["time"] = get_time();
result["model"] = model;
result["version"] = model_version;
result["platform"] = platform;
result["score_name"] = score_name;
result["language"] = language;
result["language_version"] = language_version;
result["discretized"] = discretized;
result["stratified"] = stratified;
result["folds"] = nfolds;
result["seeds"] = randomSeeds;
result["duration"] = duration;
result["results"] = json::array();
for (const auto& r : results) {
json j;
j["dataset"] = r.getDataset();
j["hyperparameters"] = r.getHyperparameters();
j["samples"] = r.getSamples();
j["features"] = r.getFeatures();
j["classes"] = r.getClasses();
j["score_train"] = r.getScoreTrain();
j["score_test"] = r.getScoreTest();
j["score"] = r.getScoreTest();
j["score_std"] = r.getScoreTestStd();
j["score_train_std"] = r.getScoreTrainStd();
j["score_test_std"] = r.getScoreTestStd();
j["train_time"] = r.getTrainTime();
j["train_time_std"] = r.getTrainTimeStd();
j["test_time"] = r.getTestTime();
j["test_time_std"] = r.getTestTimeStd();
j["time"] = r.getTestTime() + r.getTrainTime();
j["time_std"] = r.getTestTimeStd() + r.getTrainTimeStd();
j["scores_train"] = r.getScoresTrain();
j["scores_test"] = r.getScoresTest();
j["times_train"] = r.getTimesTrain();
j["times_test"] = r.getTimesTest();
j["nodes"] = r.getNodes();
j["leaves"] = r.getLeaves();
j["depth"] = r.getDepth();
j["notes"] = r.getNotes();
result["results"].push_back(j);
}
return result;
} }
void Experiment::save(const std::string& path)
{
json data = build_json();
ofstream file(path + "/" + get_file_name());
file << data;
file.close();
}
void Experiment::report() void Experiment::report()
{ {
json data = build_json(); ReportConsole report(result.getJson());
ReportConsole report(data);
report.show(); report.show();
} }
void Experiment::show() void Experiment::show()
{ {
json data = build_json(); std::cout << result.getJson().dump(4) << std::endl;
std::cout << data.dump(4) << std::endl;
} }
void Experiment::go(std::vector<std::string> filesToProcess, bool quiet, bool no_train_score) void Experiment::go(std::vector<std::string> filesToProcess, bool quiet, bool no_train_score)
{ {
for (auto fileName : filesToProcess) { for (auto fileName : filesToProcess) {
if (fileName.size() > max_name) if (fileName.size() > max_name)
max_name = fileName.size(); max_name = fileName.size();
} }
std::cout << Colors::MAGENTA() << "*** Starting experiment: " << title << " ***" << Colors::RESET() << std::endl << std::endl; std::cout << Colors::MAGENTA() << "*** Starting experiment: " << result.getTitle() << " ***" << Colors::RESET() << std::endl << std::endl;
if (!quiet) { if (!quiet) {
std::cout << Colors::GREEN() << " Status Meaning" << std::endl; std::cout << Colors::GREEN() << " Status Meaning" << std::endl;
std::cout << " ------ -----------------------------" << Colors::RESET() << std::endl; std::cout << " ------ -----------------------------" << Colors::RESET() << std::endl;
@@ -130,7 +47,6 @@ namespace platform {
if (!quiet) if (!quiet)
std::cout << std::endl; std::cout << std::endl;
} }
std::string getColor(bayesnet::status_t status) std::string getColor(bayesnet::status_t status)
{ {
switch (status) { switch (status) {
@@ -163,11 +79,11 @@ namespace platform {
if (!quiet) { if (!quiet) {
std::cout << " " << setw(5) << samples << " " << setw(5) << features.size() << flush; std::cout << " " << setw(5) << samples << " " << setw(5) << features.size() << flush;
} }
// Prepare Resu lt // Prepare Result
auto result = Result(); auto partial_result = PartialResult();
auto [values, counts] = at::_unique(y); auto [values, counts] = at::_unique(y);
result.setSamples(X.size(1)).setFeatures(X.size(0)).setClasses(values.size(0)); partial_result.setSamples(X.size(1)).setFeatures(X.size(0)).setClasses(values.size(0));
result.setHyperparameters(hyperparameters.get(fileName)); partial_result.setHyperparameters(hyperparameters.get(fileName));
// Initialize results std::vectors // Initialize results std::vectors
int nResults = nfolds * static_cast<int>(randomSeeds.size()); int nResults = nfolds * static_cast<int>(randomSeeds.size());
auto accuracy_test = torch::zeros({ nResults }, torch::kFloat64); auto accuracy_test = torch::zeros({ nResults }, torch::kFloat64);
@@ -196,7 +112,7 @@ namespace platform {
else else
fold = new folding::KFold(nfolds, y.size(0), seed); fold = new folding::KFold(nfolds, y.size(0), seed);
for (int nfold = 0; nfold < nfolds; nfold++) { for (int nfold = 0; nfold < nfolds; nfold++) {
auto clf = Models::instance()->create(model); auto clf = Models::instance()->create(result.getModel());
setModelVersion(clf->getVersion()); setModelVersion(clf->getVersion());
auto valid = clf->getValidHyperparameters(); auto valid = clf->getValidHyperparameters();
hyperparameters.check(valid, fileName); hyperparameters.check(valid, fileName);
@@ -238,22 +154,22 @@ namespace platform {
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
result.addScoreTrain(accuracy_train_value); partial_result.addScoreTrain(accuracy_train_value);
result.addScoreTest(accuracy_test_value); partial_result.addScoreTest(accuracy_test_value);
result.addTimeTrain(train_time[item].item<double>()); partial_result.addTimeTrain(train_time[item].item<double>());
result.addTimeTest(test_time[item].item<double>()); partial_result.addTimeTest(test_time[item].item<double>());
item++; item++;
} }
if (!quiet) if (!quiet)
std::cout << "end. " << flush; std::cout << "end. " << flush;
delete fold; delete fold;
} }
result.setScoreTest(torch::mean(accuracy_test).item<double>()).setScoreTrain(torch::mean(accuracy_train).item<double>()); partial_result.setScoreTest(torch::mean(accuracy_test).item<double>()).setScoreTrain(torch::mean(accuracy_train).item<double>());
result.setScoreTestStd(torch::std(accuracy_test).item<double>()).setScoreTrainStd(torch::std(accuracy_train).item<double>()); partial_result.setScoreTestStd(torch::std(accuracy_test).item<double>()).setScoreTrainStd(torch::std(accuracy_train).item<double>());
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>());
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>());
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>());
result.setDataset(fileName).setNotes(notes); partial_result.setDataset(fileName).setNotes(notes);
addResult(result); addResult(partial_result);
} }
} }

View File

@@ -6,102 +6,41 @@
#include "folding.hpp" #include "folding.hpp"
#include "BaseClassifier.h" #include "BaseClassifier.h"
#include "HyperParameters.h" #include "HyperParameters.h"
#include "TAN.h" #include "Result.h"
#include "KDB.h"
#include "AODE.h"
#include "Timer.h"
namespace platform { namespace platform {
using json = nlohmann::json; using json = nlohmann::json;
class Result {
private:
std::string dataset, model_version;
json hyperparameters;
int samples{ 0 }, features{ 0 }, classes{ 0 };
double score_train{ 0 }, score_test{ 0 }, score_train_std{ 0 }, score_test_std{ 0 }, train_time{ 0 }, train_time_std{ 0 }, test_time{ 0 }, test_time_std{ 0 };
float nodes{ 0 }, leaves{ 0 }, depth{ 0 };
std::vector<double> scores_train, scores_test, times_train, times_test;
std::vector<std::string> notes;
public:
Result() = default;
Result& setDataset(const std::string& dataset) { this->dataset = dataset; return *this; }
Result& setNotes(const std::vector<std::string>& notes) { this->notes.insert(this->notes.end(), notes.begin(), notes.end()); return *this; }
Result& setHyperparameters(const json& hyperparameters) { this->hyperparameters = hyperparameters; return *this; }
Result& setSamples(int samples) { this->samples = samples; return *this; }
Result& setFeatures(int features) { this->features = features; return *this; }
Result& setClasses(int classes) { this->classes = classes; return *this; }
Result& setScoreTrain(double score) { this->score_train = score; return *this; }
Result& setScoreTest(double score) { this->score_test = score; return *this; }
Result& setScoreTrainStd(double score_std) { this->score_train_std = score_std; return *this; }
Result& setScoreTestStd(double score_std) { this->score_test_std = score_std; return *this; }
Result& setTrainTime(double train_time) { this->train_time = train_time; return *this; }
Result& setTrainTimeStd(double train_time_std) { this->train_time_std = train_time_std; return *this; }
Result& setTestTime(double test_time) { this->test_time = test_time; return *this; }
Result& setTestTimeStd(double test_time_std) { this->test_time_std = test_time_std; return *this; }
Result& setNodes(float nodes) { this->nodes = nodes; return *this; }
Result& setLeaves(float leaves) { this->leaves = leaves; return *this; }
Result& setDepth(float depth) { this->depth = depth; return *this; }
Result& addScoreTrain(double score) { scores_train.push_back(score); return *this; }
Result& addScoreTest(double score) { scores_test.push_back(score); return *this; }
Result& addTimeTrain(double time) { times_train.push_back(time); return *this; }
Result& addTimeTest(double time) { times_test.push_back(time); return *this; }
const float get_score_train() const { return score_train; }
float get_score_test() { return score_test; }
const std::string& getDataset() const { return dataset; }
const json& getHyperparameters() const { return hyperparameters; }
const int getSamples() const { return samples; }
const int getFeatures() const { return features; }
const int getClasses() const { return classes; }
const double getScoreTrain() const { return score_train; }
const double getScoreTest() const { return score_test; }
const double getScoreTrainStd() const { return score_train_std; }
const double getScoreTestStd() const { return score_test_std; }
const double getTrainTime() const { return train_time; }
const double getTrainTimeStd() const { return train_time_std; }
const double getTestTime() const { return test_time; }
const double getTestTimeStd() const { return test_time_std; }
const float getNodes() const { return nodes; }
const float getLeaves() const { return leaves; }
const float getDepth() const { return depth; }
const std::vector<std::string>& getNotes() const { return notes; }
const std::vector<double>& getScoresTrain() const { return scores_train; }
const std::vector<double>& getScoresTest() const { return scores_test; }
const std::vector<double>& getTimesTrain() const { return times_train; }
const std::vector<double>& getTimesTest() const { return times_test; }
};
class Experiment { class Experiment {
public: public:
Experiment() = default; Experiment() = default;
Experiment& setTitle(const std::string& title) { this->title = title; return *this; } Experiment& setPlatform(const std::string& platform) { this->result.setPlatform(platform); return *this; }
Experiment& setModel(const std::string& model) { this->model = model; return *this; } Experiment& setScoreName(const std::string& score_name) { this->result.setScoreName(score_name); return *this; }
Experiment& setPlatform(const std::string& platform) { this->platform = platform; return *this; } Experiment& setTitle(const std::string& title) { this->result.setTitle(title); return *this; }
Experiment& setScoreName(const std::string& score_name) { this->score_name = score_name; return *this; } Experiment& setModelVersion(const std::string& model_version) { this->result.setModelVersion(model_version); return *this; }
Experiment& setModelVersion(const std::string& model_version) { this->model_version = model_version; return *this; } Experiment& setModel(const std::string& model) { this->result.setModel(model); return *this; }
Experiment& setLanguage(const std::string& language) { this->language = language; return *this; } Experiment& setLanguage(const std::string& language) { this->result.setLanguage(language); return *this; }
Experiment& setLanguageVersion(const std::string& language_version) { this->language_version = 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; return *this; } Experiment& setDiscretized(bool discretized) { this->discretized = discretized; result.setDiscretized(discretized); return *this; }
Experiment& setStratified(bool stratified) { this->stratified = stratified; return *this; } Experiment& setStratified(bool stratified) { this->stratified = stratified; result.setStratified(stratified); return *this; }
Experiment& setNFolds(int nfolds) { this->nfolds = nfolds; return *this; } Experiment& setNFolds(int nfolds) { this->nfolds = nfolds; result.setNFolds(nfolds); return *this; }
Experiment& addResult(Result result) { results.push_back(result); return *this; } Experiment& addResult(PartialResult result_) { result.addPartial(result_); return *this; }
Experiment& addRandomSeed(int randomSeed) { randomSeeds.push_back(randomSeed); return *this; } Experiment& addRandomSeed(int randomSeed) { randomSeeds.push_back(randomSeed); result.addSeed(randomSeed); return *this; }
Experiment& setDuration(float duration) { this->duration = 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; }
std::string get_file_name();
void save(const std::string& path);
void cross_validation(const std::string& fileName, bool quiet, bool no_train_score); void cross_validation(const std::string& fileName, bool quiet, bool no_train_score);
void go(std::vector<std::string> filesToProcess, bool quiet, bool no_train_score); void go(std::vector<std::string> filesToProcess, bool quiet, bool no_train_score);
void saveResult();
void show(); void show();
void report(); void report();
private: private:
std::string title, model, platform, score_name, model_version, language_version, language; Result result;
bool discretized{ false }, stratified{ false }; bool discretized{ false }, stratified{ false };
std::vector<Result> results; std::vector<PartialResult> results;
std::vector<int> randomSeeds; std::vector<int> randomSeeds;
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)
float duration{ 0 };
json build_json();
}; };
} }
#endif #endif

View File

@@ -87,7 +87,7 @@ namespace platform {
void ManageResults::report(const int index, const bool excelReport) void ManageResults::report(const int index, const bool excelReport)
{ {
std::cout << Colors::YELLOW() << "Reporting " << results.at(index).getFilename() << std::endl; std::cout << Colors::YELLOW() << "Reporting " << results.at(index).getFilename() << std::endl;
auto data = results.at(index).load(); auto data = results.at(index).getJson();
if (excelReport) { if (excelReport) {
ReportExcel reporter(data, compare, workbook); ReportExcel reporter(data, compare, workbook);
reporter.show(); reporter.show();
@@ -102,7 +102,7 @@ namespace platform {
void ManageResults::showIndex(const int index, const int idx) void ManageResults::showIndex(const int index, const int idx)
{ {
// Show a dataset result inside a report // Show a dataset result inside a report
auto data = results.at(index).load(); auto data = results.at(index).getJson();
std::cout << Colors::YELLOW() << "Showing " << results.at(index).getFilename() << std::endl; std::cout << Colors::YELLOW() << "Showing " << results.at(index).getFilename() << std::endl;
ReportConsole reporter(data, compare, idx); ReportConsole reporter(data, compare, idx);
reporter.show(); reporter.show();
@@ -151,7 +151,8 @@ namespace platform {
{"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}
}; };
std::vector<std::tuple<std::string, char, bool>> listOptions = { std::vector<std::tuple<std::string, char, bool>> listOptions = {
{"report", 'r', true}, {"report", 'r', true},
@@ -163,7 +164,7 @@ namespace platform {
if (indexList) { if (indexList) {
std::tie(option, index) = parser.parse(Colors::GREEN(), mainOptions, 'r', numFiles - 1); std::tie(option, index) = parser.parse(Colors::GREEN(), mainOptions, 'r', numFiles - 1);
} else { } else {
std::tie(option, subIndex) = parser.parse(Colors::MAGENTA(), listOptions, 'r', results.at(index).load()["results"].size() - 1); std::tie(option, subIndex) = parser.parse(Colors::MAGENTA(), listOptions, 'r', results.at(index).getJson()["results"].size() - 1);
} }
switch (option) { switch (option) {
case 'q': case 'q':
@@ -207,6 +208,17 @@ namespace platform {
case 'e': case 'e':
report(index, true); report(index, true);
break; break;
case 't':
std::cout << "Title: " << results.at(index).getTitle() << std::endl;
std::cout << "New title: ";
std::string newTitle;
getline(std::cin, newTitle);
if (!newTitle.empty()) {
results.at(index).setTitle(newTitle);
results.at(index).save();
std::cout << "Title changed to " << newTitle << std::endl;
}
break;
} }
} }
} }

View File

@@ -27,7 +27,7 @@ namespace platform {
if (instance != nullptr) if (instance != nullptr)
return unique_ptr<bayesnet::BaseClassifier>(instance); return unique_ptr<bayesnet::BaseClassifier>(instance);
else else
return nullptr; throw std::runtime_error("Model not found: " + name);
} }
std::vector<std::string> Models::getNames() std::vector<std::string> Models::getNames()
{ {

View File

@@ -0,0 +1,42 @@
#pragma once
#include <string>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
class PartialResult {
public:
PartialResult() { data["scores_train"] = json::array(); data["scores_test"] = json::array(); data["times_train"] = json::array(); data["times_test"] = json::array(); };
PartialResult& setDataset(const std::string& dataset) { data["dataset"] = dataset; return *this; }
PartialResult& setNotes(const std::vector<std::string>& notes) { this->notes.insert(this->notes.end(), notes.begin(), notes.end()); return *this; }
PartialResult& setHyperparameters(const json& hyperparameters) { data["hyperparameters"] = hyperparameters; return *this; }
PartialResult& setSamples(int samples) { data["samples"] = samples; return *this; }
PartialResult& setFeatures(int features) { data["features"] = features; return *this; }
PartialResult& setClasses(int classes) { data["classes"] = classes; return *this; }
PartialResult& setScoreTrain(double score) { data["score_train"] = score; return *this; }
PartialResult& setScoreTrainStd(double score_std) { data["score_train_std"] = score_std; return *this; }
PartialResult& setScoreTest(double score) { data["score"] = score; return *this; }
PartialResult& setScoreTestStd(double score_std) { data["score_std"] = score_std; return *this; }
PartialResult& setTrainTime(double train_time) { data["train_time"] = train_time; return *this; }
PartialResult& setTrainTimeStd(double train_time_std) { data["train_time_std"] = train_time_std; return *this; }
PartialResult& setTestTime(double test_time) { data["test_time"] = test_time; return *this; }
PartialResult& setTestTimeStd(double test_time_std) { data["test_time_std"] = test_time_std; return *this; }
PartialResult& setNodes(float nodes) { data["nodes"] = nodes; return *this; }
PartialResult& setLeaves(float leaves) { data["leaves"] = leaves; return *this; }
PartialResult& setDepth(float depth) { data["depth"] = depth; return *this; }
PartialResult& addScoreTrain(double score) { data["scores_train"].push_back(score); return *this; }
PartialResult& addScoreTest(double score) { data["scores_test"].push_back(score); return *this; }
PartialResult& addTimeTrain(double time) { data["times_train"].push_back(time); return *this; }
PartialResult& addTimeTest(double time) { data["times_test"].push_back(time); return *this; }
json getJson()
{
data["time"] = data["test_time"].get<double>() + data["train_time"].get<double>();
data["time_std"] = data["test_time_std"].get<double>() + data["train_time_std"].get<double>();
data["notes"] = notes;
return data;
}
private:
json data;
std::vector<std::string> notes;
};

View File

@@ -1,58 +1,98 @@
#include "Result.h" #include "Result.h"
#include "BestScore.h"
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include "BestScore.h"
#include "Colors.h" #include "Colors.h"
#include "DotEnv.h" #include "DotEnv.h"
#include "CLocale.h" #include "CLocale.h"
#include "Paths.h"
namespace platform { namespace platform {
Result::Result(const std::string& path, const std::string& filename) std::string get_actual_date()
: path(path)
, filename(filename)
{ {
auto data = load(); time_t rawtime;
date = data["date"]; 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_actual_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();
}
Result::Result()
{
data["date"] = get_actual_date();
data["time"] = get_actual_time();
data["results"] = json::array();
data["seeds"] = json::array();
}
Result& Result::load(const std::string& path, const std::string& fileName)
{
std::ifstream resultData(path + "/" + fileName);
if (resultData.is_open()) {
data = json::parse(resultData);
} else {
throw std::invalid_argument("Unable to open result file. [" + path + "/" + fileName + "]");
}
score = 0; score = 0;
for (const auto& result : data["results"]) { for (const auto& result : data["results"]) {
score += result["score"].get<double>(); score += result["score"].get<double>();
} }
scoreName = data["score_name"]; auto scoreName = data["score_name"];
auto best = BestScore::getScore(scoreName); auto best = BestScore::getScore(scoreName);
if (best.first != "") { if (best.first != "") {
score /= best.second; score /= best.second;
} }
title = data["title"];
duration = data["duration"];
model = data["model"];
complete = data["results"].size() > 1; complete = data["results"].size() > 1;
return *this;
}
json Result::getJson()
{
return data;
} }
json Result::load() const void Result::save()
{ {
std::ifstream resultData(path + "/" + filename); std::ofstream file(Paths::results() + "/" + getFilename());
if (resultData.is_open()) { file << data;
json data = json::parse(resultData); file.close();
return data;
}
throw std::invalid_argument("Unable to open result file. [" + path + "/" + filename + "]");
} }
std::string Result::getFilename() const
{
std::ostringstream oss;
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>() << "_" << (data["stratified"] ? "1" : "0") << ".json";
return oss.str();
}
std::string Result::to_string(int maxModel) const std::string Result::to_string(int maxModel) const
{ {
auto tmp = ConfigLocale(); auto tmp = ConfigLocale();
std::stringstream oss; std::stringstream oss;
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";
oss << date << " "; oss << data["date"].get<std::string>() << " ";
oss << std::setw(maxModel) << std::left << model << " "; oss << std::setw(maxModel) << std::left << data["model"].get<std::string>() << " ";
oss << std::setw(11) << std::left << scoreName << " "; oss << std::setw(11) << std::left << data["score_name"].get<std::string>() << " ";
oss << std::right << std::setw(11) << std::setprecision(7) << std::fixed << score << " "; oss << std::right << std::setw(11) << std::setprecision(7) << std::fixed << score << " ";
auto completeString = isComplete() ? "C" : "P"; auto completeString = isComplete() ? "C" : "P";
oss << std::setw(1) << " " << completeString << " "; oss << std::setw(1) << " " << completeString << " ";
oss << std::setw(7) << std::setprecision(2) << std::fixed << durationShow << " " << durationUnit << " "; oss << std::setw(7) << std::setprecision(2) << std::fixed << durationShow << " " << durationUnit << " ";
oss << std::setw(50) << std::left << title << " "; oss << std::setw(50) << std::left << data["title"].get<std::string>() << " ";
return oss.str(); return oss.str();
} }
} }

View File

@@ -4,32 +4,48 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "HyperParameters.h"
#include "PartialResult.h"
#include "Timer.h"
namespace platform { namespace platform {
using json = nlohmann::json; using json = nlohmann::json;
class Result { class Result {
public: public:
Result(const std::string& path, const std::string& filename); Result();
json load() const; Result& load(const std::string& path, const std::string& filename);
void save();
// Getters
json getJson();
std::string to_string(int maxModel) const; std::string to_string(int maxModel) const;
std::string getFilename() const { return filename; }; std::string getFilename() const;
std::string getDate() const { return date; }; std::string getDate() const { return data["date"].get<std::string>(); };
double getScore() const { return score; }; double getScore() const { return score; };
std::string getTitle() const { return title; }; std::string getTitle() const { return data["title"].get<std::string>(); };
double getDuration() const { return duration; }; double getDuration() const { return data["duration"]; };
std::string getModel() const { return model; }; std::string getModel() const { return data["model"].get<std::string>(); };
std::string getScoreName() const { return scoreName; }; std::string getScoreName() const { return data["score_name"].get<std::string>(); };
bool isComplete() const { return complete; }; bool isComplete() const { return complete; };
// Setters
void setTitle(const std::string& title) { data["title"] = title; };
void setLanguage(const std::string& language) { data["language"] = language; };
void setLanguageVersion(const std::string& language_version) { data["language_version"] = language_version; };
void setDuration(double duration) { data["duration"] = duration; };
void setModel(const std::string& model) { data["model"] = model; };
void setModelVersion(const std::string& model_version) { data["version"] = model_version; };
void setScoreName(const std::string& scoreName) { data["score_name"] = scoreName; };
void setDiscretized(bool discretized) { data["discretized"] = discretized; };
void addSeed(int seed) { data["seeds"].push_back(seed); };
void addPartial(PartialResult& partial_result) { data["results"].push_back(partial_result.getJson()); };
void setStratified(bool stratified) { data["stratified"] = stratified; };
void setNFolds(int nfolds) { data["folds"] = nfolds; };
void setPlatform(const std::string& platform_name) { data["platform"] = platform_name; };
private: private:
std::string path; json data;
std::string filename;
std::string date;
double score;
std::string title;
double duration;
std::string model;
std::string scoreName;
bool complete; bool complete;
double score = 0.0;
}; };
}; };
#endif #endif

View File

@@ -18,7 +18,8 @@ namespace platform {
for (const auto& file : directory_iterator(path)) { for (const auto& file : directory_iterator(path)) {
auto filename = file.path().filename().string(); auto filename = file.path().filename().string();
if (filename.find(".json") != std::string::npos && filename.find("results_") == 0) { if (filename.find(".json") != std::string::npos && filename.find("results_") == 0) {
auto result = Result(path, filename); auto result = Result();
result.load(path, filename);
bool addResult = true; bool addResult = true;
if (model != "any" && result.getModel() != model || scoreName != "any" && scoreName != result.getScoreName() || complete && !result.isComplete() || partial && result.isComplete()) if (model != "any" && result.getModel() != model || scoreName != "any" && scoreName != result.getScoreName() || complete && !result.isComplete() || partial && result.isComplete())
addResult = false; addResult = false;

View File

@@ -10,7 +10,8 @@ TEST_CASE("Result class tests", "[Result]")
SECTION("Constructor and load method") SECTION("Constructor and load method")
{ {
platform::Result result(testPath, testFile); platform::Result result;
result.load(testPath, testFile);
REQUIRE(result.date != ""); REQUIRE(result.date != "");
REQUIRE(result.score >= 0); REQUIRE(result.score >= 0);
REQUIRE(result.scoreName != ""); REQUIRE(result.scoreName != "");
@@ -22,6 +23,7 @@ TEST_CASE("Result class tests", "[Result]")
SECTION("to_string method") SECTION("to_string method")
{ {
platform::Result result(testPath, testFile); platform::Result result(testPath, testFile);
result.load();
std::string resultStr = result.to_string(1); std::string resultStr = result.to_string(1);
REQUIRE(resultStr != ""); REQUIRE(resultStr != "");
} }
@@ -29,6 +31,7 @@ TEST_CASE("Result class tests", "[Result]")
SECTION("Exception handling in load method") SECTION("Exception handling in load method")
{ {
std::string invalidFile = "invalid.json"; std::string invalidFile = "invalid.json";
REQUIRE_THROWS_AS(platform::Result(testPath, invalidFile), std::invalid_argument); auto result = platform::Result();
REQUIRE_THROWS_AS(platform::result.load(testPath, invalidFile), std::invalid_argument);
} }
} }