mirror of
https://github.com/Doctorado-ML/benchmark.git
synced 2025-08-17 00:15:55 +00:00
Benchmark only with best experiments results
This commit is contained in:
231
src/Results.py
231
src/Results.py
@@ -5,7 +5,6 @@ import json
|
|||||||
import abc
|
import abc
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from tqdm import tqdm
|
|
||||||
import xlsxwriter
|
import xlsxwriter
|
||||||
from Experiments import Datasets, BestResults
|
from Experiments import Datasets, BestResults
|
||||||
from Utils import Folders, Files, Symbols, BEST_ACCURACY_STREE, TextColor
|
from Utils import Folders, Files, Symbols, BEST_ACCURACY_STREE, TextColor
|
||||||
@@ -456,49 +455,56 @@ class SQL(BaseReport):
|
|||||||
|
|
||||||
|
|
||||||
class Benchmark:
|
class Benchmark:
|
||||||
@staticmethod
|
def __init__(self, score):
|
||||||
def get_result_file_name(score):
|
self._score = score
|
||||||
return os.path.join(Folders.results, Files.exreport(score))
|
self._results = []
|
||||||
|
self._models = []
|
||||||
|
self._report = {}
|
||||||
|
self._datasets = set()
|
||||||
|
|
||||||
@staticmethod
|
def get_result_file_name(self):
|
||||||
def _process_dataset(results, data):
|
return os.path.join(Folders.results, Files.exreport(self._score))
|
||||||
model = data["model"]
|
|
||||||
for record in data["results"]:
|
|
||||||
dataset = record["dataset"]
|
|
||||||
if (model, dataset) in results:
|
|
||||||
if record["score"] > results[model, dataset][0]:
|
|
||||||
results[model, dataset] = (
|
|
||||||
record["score"],
|
|
||||||
record["score_std"],
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
results[model, dataset] = (
|
|
||||||
record["score"],
|
|
||||||
record["score_std"],
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
def compile_results(self):
|
||||||
def compile_results(score):
|
summary = Summary()
|
||||||
|
summary.acquire(given_score=self._score)
|
||||||
|
self._models = summary.get_models()
|
||||||
|
for model in self._models:
|
||||||
|
best = summary.best_result(
|
||||||
|
criterion="model", value=model, score=self._score
|
||||||
|
)
|
||||||
|
file_name = os.path.join(Folders.results, best["file"])
|
||||||
|
with open(file_name) as fi:
|
||||||
|
experiment = json.load(fi)
|
||||||
|
for result in experiment["results"]:
|
||||||
|
dataset = result["dataset"]
|
||||||
|
record = {
|
||||||
|
"model": model,
|
||||||
|
"dataset": dataset,
|
||||||
|
"score": result["score"],
|
||||||
|
"score_std": result["score_std"],
|
||||||
|
"file_name": file_name,
|
||||||
|
}
|
||||||
|
self._results.append(record)
|
||||||
|
if model not in self._report:
|
||||||
|
self._report[model] = {}
|
||||||
|
self._report[model][dataset] = record
|
||||||
|
self._datasets.add(dataset)
|
||||||
|
self._datasets = sorted(self._datasets)
|
||||||
|
|
||||||
|
def save_results(self):
|
||||||
# build Files.exreport
|
# build Files.exreport
|
||||||
result_file_name = Benchmark.get_result_file_name(score)
|
result_file_name = self.get_result_file_name()
|
||||||
results = {}
|
|
||||||
init_suffix, end_suffix = Files.results_suffixes(score=score)
|
|
||||||
all_files = list(os.walk(Folders.results))
|
|
||||||
for root, _, files in tqdm(all_files, desc="files"):
|
|
||||||
for name in files:
|
|
||||||
if name.startswith(init_suffix) and name.endswith(end_suffix):
|
|
||||||
file_name = os.path.join(root, name)
|
|
||||||
with open(file_name) as fp:
|
|
||||||
data = json.load(fp)
|
|
||||||
Benchmark._process_dataset(results, data)
|
|
||||||
|
|
||||||
with open(result_file_name, "w") as f:
|
with open(result_file_name, "w") as f:
|
||||||
f.write(f"classifier, dataset, {score}, stdev\n")
|
f.write(f"classifier, dataset, {self._score}, stdev, file_name\n")
|
||||||
for (model, dataset), (accuracy, stdev) in results.items():
|
for record in self._results:
|
||||||
f.write(f"{model}, {dataset}, {accuracy}, {stdev}\n")
|
f.write(
|
||||||
|
f"{record['model']}, {record['dataset']}, "
|
||||||
|
f"{record['score']}, {record['score_std']}, "
|
||||||
|
f"{record['file_name']}\n"
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
def exreport(self):
|
||||||
def exreport(score):
|
|
||||||
def end_message(message, file):
|
def end_message(message, file):
|
||||||
length = 100
|
length = 100
|
||||||
print("*" * length)
|
print("*" * length)
|
||||||
@@ -515,74 +521,67 @@ class Benchmark:
|
|||||||
os.remove(Files.exreport_pdf)
|
os.remove(Files.exreport_pdf)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
except OSError as e:
|
except OSError as os_error:
|
||||||
print("Error: %s : %s" % (Folders.report, e.strerror))
|
print("Error: %s : %s" % (Folders.report, os_error.strerror))
|
||||||
# Compute Friedman & Holm Tests
|
# Compute Friedman & Holm Tests
|
||||||
fout = open(
|
fout = open(
|
||||||
os.path.join(Folders.results, Files.exreport_output(score)), "w"
|
os.path.join(Folders.results, Files.exreport_output(self._score)),
|
||||||
|
"w",
|
||||||
)
|
)
|
||||||
ferr = open(
|
ferr = open(
|
||||||
os.path.join(Folders.results, Files.exreport_err(score)), "w"
|
os.path.join(Folders.results, Files.exreport_err(self._score)), "w"
|
||||||
)
|
)
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["Rscript", os.path.join(Folders.src, Files.benchmark_r), score],
|
[
|
||||||
|
"Rscript",
|
||||||
|
os.path.join(Folders.src, Files.benchmark_r),
|
||||||
|
self._score,
|
||||||
|
],
|
||||||
stdout=fout,
|
stdout=fout,
|
||||||
stderr=ferr,
|
stderr=ferr,
|
||||||
)
|
)
|
||||||
fout.close()
|
fout.close()
|
||||||
ferr.close()
|
ferr.close()
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
end_message("Error computing benchmark", Files.exreport_err(score))
|
end_message(
|
||||||
|
"Error computing benchmark", Files.exreport_err(self._score)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
end_message("Benchmark Ok", Files.exreport_output(score))
|
end_message("Benchmark Ok", Files.exreport_output(self._score))
|
||||||
Files.open(Files.exreport_pdf)
|
Files.open(Files.exreport_pdf)
|
||||||
|
|
||||||
@staticmethod
|
def report(self):
|
||||||
def build_results(score):
|
|
||||||
# Build results data structure
|
|
||||||
file_name = Benchmark.get_result_file_name(score)
|
|
||||||
results = {}
|
|
||||||
with open(file_name) as f:
|
|
||||||
data = f.read().splitlines()
|
|
||||||
data = data[1:]
|
|
||||||
for line in data:
|
|
||||||
model, dataset, accuracy, stdev = line.split(", ")
|
|
||||||
if model not in results:
|
|
||||||
results[model] = {}
|
|
||||||
results[model][dataset] = (accuracy, stdev)
|
|
||||||
return results
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def report(score):
|
|
||||||
def show(results):
|
|
||||||
datasets = results[list(results)[0]]
|
|
||||||
print(f"{'Dataset':30s} ", end="")
|
print(f"{'Dataset':30s} ", end="")
|
||||||
lines = "=" * 30 + " "
|
lines = "=" * 30 + " "
|
||||||
for model in results:
|
for model in self._models:
|
||||||
print(f"{model:^13s} ", end="")
|
print(f"{model:^13s} ", end="")
|
||||||
lines += "=" * 13 + " "
|
lines += "=" * 13 + " "
|
||||||
print(f"\n{lines}")
|
print(f"\n{lines}")
|
||||||
for dataset, _ in datasets.items():
|
for dataset in self._datasets:
|
||||||
print(f"{dataset:30s} ", end="")
|
print(f"{dataset:30s} ", end="")
|
||||||
for model in results:
|
for model in self._models:
|
||||||
print(f"{float(results[model][dataset][0]):.5f}±", end="")
|
result = self._report[model][dataset]
|
||||||
print(f"{float(results[model][dataset][1]):.3f} ", end="")
|
print(f"{float(result['score']):.5f}±", end="")
|
||||||
|
print(f"{float(result['score_std']):.3f} ", end="")
|
||||||
print("")
|
print("")
|
||||||
|
d_name = next(iter(self._datasets))
|
||||||
|
print(f"\n{'Model':30s} {'File Name':75s} Score")
|
||||||
|
print("=" * 30 + " " + "=" * 75 + " ========")
|
||||||
|
for model in self._models:
|
||||||
|
file_name = self._report[model][d_name]["file_name"]
|
||||||
|
report = StubReport(file_name)
|
||||||
|
report.report()
|
||||||
|
print(f"{model:^30s} {file_name:75s} {report.score:8.5f}")
|
||||||
|
|
||||||
print(f"* Score is: {score}")
|
def get_excel_file_name(self):
|
||||||
show(Benchmark.build_results(score))
|
return os.path.join(
|
||||||
|
Folders.exreport, Files.exreport_excel(self._score)
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
def excel(self):
|
||||||
def get_excel_file_name(score):
|
book = xlsxwriter.Workbook(self.get_excel_file_name())
|
||||||
return os.path.join(Folders.exreport, Files.exreport_excel(score))
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def excel(score):
|
|
||||||
results = Benchmark.build_results(score)
|
|
||||||
book = xlsxwriter.Workbook(Benchmark.get_excel_file_name(score))
|
|
||||||
sheet = book.add_worksheet("Benchmark")
|
sheet = book.add_worksheet("Benchmark")
|
||||||
normal = book.add_format({"font_size": 14})
|
normal = book.add_format({"font_size": 14})
|
||||||
bold = book.add_format({"bold": True, "font_size": 14})
|
|
||||||
decimal = book.add_format({"num_format": "0.000000", "font_size": 14})
|
decimal = book.add_format({"num_format": "0.000000", "font_size": 14})
|
||||||
merge_format = book.add_format(
|
merge_format = book.add_format(
|
||||||
{
|
{
|
||||||
@@ -592,22 +591,30 @@ class Benchmark:
|
|||||||
"font_size": 14,
|
"font_size": 14,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
merge_format_normal = book.add_format(
|
||||||
|
{
|
||||||
|
"valign": "vcenter",
|
||||||
|
"font_size": 14,
|
||||||
|
}
|
||||||
|
)
|
||||||
row = row_init = 4
|
row = row_init = 4
|
||||||
|
|
||||||
def header():
|
def header():
|
||||||
nonlocal row
|
nonlocal row
|
||||||
sheet.merge_range(0, 0, 1, 0, "Benchmark of Models", merge_format)
|
sheet.merge_range(0, 0, 1, 0, "Benchmark of Models", merge_format)
|
||||||
sheet.write(1, 2, f"Score is {score}", bold)
|
sheet.merge_range(
|
||||||
|
0, 1, 1, 2, f"Score is {self._score}", merge_format
|
||||||
|
)
|
||||||
sheet.set_row(1, 20)
|
sheet.set_row(1, 20)
|
||||||
# Set columns width
|
# Set columns width
|
||||||
sheet.set_column(0, 0, 40)
|
sheet.set_column(0, 0, 40)
|
||||||
for column in range(2 * len(results)):
|
for column in range(2 * len(self._results)):
|
||||||
sheet.set_column(column + 1, column + 1, 15)
|
sheet.set_column(column + 1, column + 1, 15)
|
||||||
# Set report header
|
# Set report header
|
||||||
# Merge 2 rows
|
# Merge 2 rows
|
||||||
sheet.merge_range(row, 0, row + 1, 0, "Dataset", merge_format)
|
sheet.merge_range(row, 0, row + 1, 0, "Dataset", merge_format)
|
||||||
column = 1
|
column = 1
|
||||||
for model in results:
|
for model in self._models:
|
||||||
# Merge 2 columns
|
# Merge 2 columns
|
||||||
sheet.merge_range(
|
sheet.merge_range(
|
||||||
row, column, row, column + 1, model, merge_format
|
row, column, row, column + 1, model, merge_format
|
||||||
@@ -615,42 +622,73 @@ class Benchmark:
|
|||||||
column += 2
|
column += 2
|
||||||
row += 1
|
row += 1
|
||||||
column = 1
|
column = 1
|
||||||
for _ in range(len(results)):
|
for _ in range(len(self._results)):
|
||||||
sheet.write(row, column, "Score", merge_format)
|
sheet.write(row, column, "Score", merge_format)
|
||||||
sheet.write(row, column + 1, "Stdev", merge_format)
|
sheet.write(row, column + 1, "Stdev", merge_format)
|
||||||
column += 2
|
column += 2
|
||||||
|
|
||||||
def body():
|
def body():
|
||||||
nonlocal row
|
nonlocal row
|
||||||
datasets = results[list(results)[0]]
|
for dataset in self._datasets:
|
||||||
for dataset, _ in datasets.items():
|
|
||||||
row += 1
|
row += 1
|
||||||
sheet.write(row, 0, f"{dataset:30s}", normal)
|
sheet.write(row, 0, f"{dataset:30s}", normal)
|
||||||
column = 1
|
column = 1
|
||||||
for model in results:
|
for model in self._models:
|
||||||
sheet.write(
|
sheet.write(
|
||||||
row,
|
row,
|
||||||
column,
|
column,
|
||||||
float(results[model][dataset][0]),
|
float(self._report[model][dataset]["score"]),
|
||||||
decimal,
|
decimal,
|
||||||
)
|
)
|
||||||
column += 1
|
column += 1
|
||||||
sheet.write(
|
sheet.write(
|
||||||
row,
|
row,
|
||||||
column,
|
column,
|
||||||
float(results[model][dataset][1]),
|
float(self._report[model][dataset]["score_std"]),
|
||||||
decimal,
|
decimal,
|
||||||
)
|
)
|
||||||
column += 1
|
column += 1
|
||||||
|
|
||||||
def footer():
|
def footer():
|
||||||
|
nonlocal row
|
||||||
for c in range(row_init, row + 1):
|
for c in range(row_init, row + 1):
|
||||||
sheet.set_row(c, 20)
|
sheet.set_row(c, 20)
|
||||||
|
|
||||||
|
def models_files():
|
||||||
|
nonlocal row
|
||||||
|
row += 2
|
||||||
|
# Set report header
|
||||||
|
# Merge 2 rows
|
||||||
|
sheet.merge_range(row, 0, row + 1, 0, "Model", merge_format)
|
||||||
|
sheet.merge_range(row, 1, row + 1, 5, "File", merge_format)
|
||||||
|
sheet.merge_range(row, 6, row + 1, 6, "Score", merge_format)
|
||||||
|
row += 1
|
||||||
|
d_name = next(iter(self._datasets))
|
||||||
|
for model in self._models:
|
||||||
|
file_name = self._report[model][d_name]["file_name"]
|
||||||
|
report = StubReport(file_name)
|
||||||
|
report.report()
|
||||||
|
row += 1
|
||||||
|
sheet.write(
|
||||||
|
row,
|
||||||
|
0,
|
||||||
|
model,
|
||||||
|
normal,
|
||||||
|
)
|
||||||
|
sheet.merge_range(
|
||||||
|
row, 1, row, 5, file_name, merge_format_normal
|
||||||
|
)
|
||||||
|
sheet.write(
|
||||||
|
row,
|
||||||
|
6,
|
||||||
|
report.score,
|
||||||
|
decimal,
|
||||||
|
)
|
||||||
|
|
||||||
header()
|
header()
|
||||||
body()
|
body()
|
||||||
footer()
|
footer()
|
||||||
|
models_files()
|
||||||
book.close()
|
book.close()
|
||||||
|
|
||||||
|
|
||||||
@@ -667,6 +705,7 @@ class StubReport(BaseReport):
|
|||||||
|
|
||||||
def footer(self, accuracy: float) -> None:
|
def footer(self, accuracy: float) -> None:
|
||||||
self.accuracy = accuracy
|
self.accuracy = accuracy
|
||||||
|
self.score = accuracy / BEST_ACCURACY_STREE
|
||||||
|
|
||||||
|
|
||||||
class Summary:
|
class Summary:
|
||||||
@@ -674,8 +713,12 @@ class Summary:
|
|||||||
self.results = Files().get_all_results()
|
self.results = Files().get_all_results()
|
||||||
self.data = []
|
self.data = []
|
||||||
self.datasets = {}
|
self.datasets = {}
|
||||||
|
self.models = set()
|
||||||
|
|
||||||
def acquire(self) -> None:
|
def get_models(self):
|
||||||
|
return self.models
|
||||||
|
|
||||||
|
def acquire(self, given_score="any") -> None:
|
||||||
"""Get all results"""
|
"""Get all results"""
|
||||||
for result in self.results:
|
for result in self.results:
|
||||||
(
|
(
|
||||||
@@ -686,6 +729,8 @@ class Summary:
|
|||||||
time,
|
time,
|
||||||
stratified,
|
stratified,
|
||||||
) = Files().split_file_name(result)
|
) = Files().split_file_name(result)
|
||||||
|
if given_score in ("any", score):
|
||||||
|
self.models.add(model)
|
||||||
report = StubReport(os.path.join(Folders.results, result))
|
report = StubReport(os.path.join(Folders.results, result))
|
||||||
report.report()
|
report.report()
|
||||||
entry = dict(
|
entry = dict(
|
||||||
@@ -697,7 +742,7 @@ class Summary:
|
|||||||
time=time,
|
time=time,
|
||||||
stratified=stratified,
|
stratified=stratified,
|
||||||
file=result,
|
file=result,
|
||||||
metric=report.accuracy / BEST_ACCURACY_STREE,
|
metric=report.score,
|
||||||
duration=report.duration,
|
duration=report.duration,
|
||||||
)
|
)
|
||||||
self.datasets[result] = report.lines
|
self.datasets[result] = report.lines
|
||||||
|
@@ -27,10 +27,11 @@ def parse_arguments():
|
|||||||
|
|
||||||
|
|
||||||
(score, excel) = parse_arguments()
|
(score, excel) = parse_arguments()
|
||||||
benchmark = Benchmark()
|
benchmark = Benchmark(score)
|
||||||
benchmark.compile_results(score)
|
benchmark.compile_results()
|
||||||
benchmark.report(score)
|
benchmark.save_results()
|
||||||
benchmark.exreport(score)
|
benchmark.report()
|
||||||
|
benchmark.exreport()
|
||||||
if excel:
|
if excel:
|
||||||
benchmark.excel(score)
|
benchmark.excel()
|
||||||
Files.open(benchmark.get_excel_file_name(score))
|
Files.open(benchmark.get_excel_file_name())
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
from Results import Summary, StubReport
|
from Results import Summary, StubReport
|
||||||
from Utils import EnvDefault, Folders, BEST_ACCURACY_STREE
|
from Utils import EnvDefault, Folders
|
||||||
|
|
||||||
"""Check best results of two models giving scores and win-tie-loose results
|
"""Check best results of two models giving scores and win-tie-loose results
|
||||||
"""
|
"""
|
||||||
@@ -66,12 +66,9 @@ for result1, result2 in zip(report_1.lines, report_2.lines):
|
|||||||
tie += 1
|
tie += 1
|
||||||
print(f"{'Model':<20} {'File':<70} {'Score':<10} Win Tie Loose")
|
print(f"{'Model':<20} {'File':<70} {'Score':<10} Win Tie Loose")
|
||||||
print("=" * 20 + " " + "=" * 70 + " " + "=" * 10 + " === === =====")
|
print("=" * 20 + " " + "=" * 70 + " " + "=" * 10 + " === === =====")
|
||||||
print(
|
print(f"{model1:<20} {best_1['file']:<70} {report_1.score:10.5f}")
|
||||||
f"{model1:<20} {best_1['file']:<70} "
|
|
||||||
f"{report_1.accuracy / BEST_ACCURACY_STREE:10.5f}"
|
|
||||||
)
|
|
||||||
print(
|
print(
|
||||||
f"{model2:<20} {best_2['file']:<70} "
|
f"{model2:<20} {best_2['file']:<70} "
|
||||||
f"{report_2.accuracy / BEST_ACCURACY_STREE:10.5f} "
|
f"{report_2.score:10.5f} "
|
||||||
f"{win:3d} {tie:3d} {loose:5d}"
|
f"{win:3d} {tie:3d} {loose:5d}"
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user