Benchmark only with best experiments results

This commit is contained in:
2022-03-02 12:06:03 +01:00
parent a4ddcda5d6
commit 15b46fcc21
3 changed files with 172 additions and 129 deletions

View File

@@ -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"]: def compile_results(self):
dataset = record["dataset"] summary = Summary()
if (model, dataset) in results: summary.acquire(given_score=self._score)
if record["score"] > results[model, dataset][0]: self._models = summary.get_models()
results[model, dataset] = ( for model in self._models:
record["score"], best = summary.best_result(
record["score_std"], criterion="model", value=model, score=self._score
) )
else: file_name = os.path.join(Folders.results, best["file"])
results[model, dataset] = ( with open(file_name) as fi:
record["score"], experiment = json.load(fi)
record["score_std"], 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
result_file_name = self.get_result_file_name()
with open(result_file_name, "w") as f:
f.write(f"classifier, dataset, {self._score}, stdev, file_name\n")
for record in self._results:
f.write(
f"{record['model']}, {record['dataset']}, "
f"{record['score']}, {record['score_std']}, "
f"{record['file_name']}\n"
) )
@staticmethod def exreport(self):
def compile_results(score):
# build Files.exreport
result_file_name = Benchmark.get_result_file_name(score)
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:
f.write(f"classifier, dataset, {score}, stdev\n")
for (model, dataset), (accuracy, stdev) in results.items():
f.write(f"{model}, {dataset}, {accuracy}, {stdev}\n")
@staticmethod
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): print(f"{'Dataset':30s} ", end="")
# Build results data structure lines = "=" * 30 + " "
file_name = Benchmark.get_result_file_name(score) for model in self._models:
results = {} print(f"{model:^13s} ", end="")
with open(file_name) as f: lines += "=" * 13 + " "
data = f.read().splitlines() print(f"\n{lines}")
data = data[1:] for dataset in self._datasets:
for line in data: print(f"{dataset:30s} ", end="")
model, dataset, accuracy, stdev = line.split(", ") for model in self._models:
if model not in results: result = self._report[model][dataset]
results[model] = {} print(f"{float(result['score']):.5f}±", end="")
results[model][dataset] = (accuracy, stdev) print(f"{float(result['score_std']):.3f} ", end="")
return results 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}")
@staticmethod def get_excel_file_name(self):
def report(score): return os.path.join(
def show(results): Folders.exreport, Files.exreport_excel(self._score)
datasets = results[list(results)[0]] )
print(f"{'Dataset':30s} ", end="")
lines = "=" * 30 + " "
for model in results:
print(f"{model:^13s} ", end="")
lines += "=" * 13 + " "
print(f"\n{lines}")
for dataset, _ in datasets.items():
print(f"{dataset:30s} ", end="")
for model in results:
print(f"{float(results[model][dataset][0]):.5f}±", end="")
print(f"{float(results[model][dataset][1]):.3f} ", end="")
print("")
print(f"* Score is: {score}") def excel(self):
show(Benchmark.build_results(score)) book = xlsxwriter.Workbook(self.get_excel_file_name())
@staticmethod
def get_excel_file_name(score):
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,22 +729,24 @@ class Summary:
time, time,
stratified, stratified,
) = Files().split_file_name(result) ) = Files().split_file_name(result)
report = StubReport(os.path.join(Folders.results, result)) if given_score in ("any", score):
report.report() self.models.add(model)
entry = dict( report = StubReport(os.path.join(Folders.results, result))
score=score, report.report()
model=model, entry = dict(
title=report.title, score=score,
platform=platform, model=model,
date=date, title=report.title,
time=time, platform=platform,
stratified=stratified, date=date,
file=result, time=time,
metric=report.accuracy / BEST_ACCURACY_STREE, stratified=stratified,
duration=report.duration, file=result,
) metric=report.score,
self.datasets[result] = report.lines duration=report.duration,
self.data.append(entry) )
self.datasets[result] = report.lines
self.data.append(entry)
def list_results( def list_results(
self, self,

View File

@@ -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())

View File

@@ -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}"
) )