evalsuite-python 0.3.0__py3-none-any.whl → 0.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- evalsuite/benchmarks.py +95 -4
- evalsuite/core/validation.py +21 -0
- evalsuite/regression/metrics.py +9 -1
- evalsuite/stats/_resolve.py +6 -1
- evalsuite/version.py +1 -1
- evalsuite/vision/segmentation.py +9 -1
- {evalsuite_python-0.3.0.dist-info → evalsuite_python-0.3.1.dist-info}/METADATA +25 -21
- {evalsuite_python-0.3.0.dist-info → evalsuite_python-0.3.1.dist-info}/RECORD +11 -11
- {evalsuite_python-0.3.0.dist-info → evalsuite_python-0.3.1.dist-info}/WHEEL +0 -0
- {evalsuite_python-0.3.0.dist-info → evalsuite_python-0.3.1.dist-info}/entry_points.txt +0 -0
- {evalsuite_python-0.3.0.dist-info → evalsuite_python-0.3.1.dist-info}/licenses/LICENSE +0 -0
evalsuite/benchmarks.py
CHANGED
|
@@ -17,8 +17,10 @@ whose reference library is not installed is timed for EvalSuite only.
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import contextlib
|
|
20
|
+
import importlib
|
|
20
21
|
import json
|
|
21
22
|
import platform
|
|
23
|
+
import re
|
|
22
24
|
import time
|
|
23
25
|
import tracemalloc
|
|
24
26
|
import warnings
|
|
@@ -371,6 +373,28 @@ def _clinical_cases(n: int, rng: np.random.Generator) -> list[Case]:
|
|
|
371
373
|
return [(name, ref, es_fn, own if own is not None else refs.get(name)) for name, ref, es_fn, own in cases]
|
|
372
374
|
|
|
373
375
|
|
|
376
|
+
_GROUPS = (
|
|
377
|
+
("Classification and regression", ("binary", "10 classes", "regression")),
|
|
378
|
+
("Clinical, calibration and statistics", ("clinical", "calibration", "decision", "statistics", "multiple")),
|
|
379
|
+
("Segmentation and object detection", ("segmentation", "detection")),
|
|
380
|
+
)
|
|
381
|
+
MATCH_TOLERANCE = 1e-9
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
def benchmark_group(case: str) -> str:
|
|
385
|
+
"""The suite a benchmark case belongs to, by its name."""
|
|
386
|
+
lowered = case.lower()
|
|
387
|
+
for title, prefixes in _GROUPS:
|
|
388
|
+
if lowered.startswith(prefixes):
|
|
389
|
+
return title
|
|
390
|
+
return "Other"
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def _geomean(values: Sequence[float]) -> Optional[float]:
|
|
394
|
+
vals = [v for v in values if v is not None and v > 0]
|
|
395
|
+
return float(np.exp(np.mean(np.log(vals)))) if vals else None
|
|
396
|
+
|
|
397
|
+
|
|
374
398
|
@dataclass(frozen=True, eq=False)
|
|
375
399
|
class BenchmarkResult:
|
|
376
400
|
"""Rows of timings (milliseconds), peak memory (MiB) and agreement, plus the environment they ran in."""
|
|
@@ -382,6 +406,60 @@ class BenchmarkResult:
|
|
|
382
406
|
object.__setattr__(self, "rows", tuple(MappingProxyType(dict(r)) for r in self.rows))
|
|
383
407
|
object.__setattr__(self, "environment", MappingProxyType(dict(self.environment)))
|
|
384
408
|
|
|
409
|
+
def sorted_rows(self) -> list[Any]:
|
|
410
|
+
"""Rows in alphabetical order of case, then by size."""
|
|
411
|
+
return sorted(self.rows, key=lambda r: (r["case"].lower(), r["n"]))
|
|
412
|
+
|
|
413
|
+
def overall(self) -> list[dict[str, Any]]:
|
|
414
|
+
"""One summary row per suite and one for everything: cases, how many agree with the reference
|
|
415
|
+
(max |difference| <= 1e-9), and the geometric-mean, smallest and largest speed-up."""
|
|
416
|
+
|
|
417
|
+
def summarise(name: str, rows: Sequence[Any]) -> dict[str, Any]:
|
|
418
|
+
compared = [r for r in rows if r["speedup"] is not None]
|
|
419
|
+
speedups = [r["speedup"] for r in compared]
|
|
420
|
+
return {
|
|
421
|
+
"group": name,
|
|
422
|
+
"cases": len({re.sub(r"\s*\(\d+ images?\)", "", r["case"]) for r in rows}),
|
|
423
|
+
"rows": len(rows),
|
|
424
|
+
"compared": len(compared),
|
|
425
|
+
"matching": sum(
|
|
426
|
+
r["max_abs_diff"] is not None and r["max_abs_diff"] <= MATCH_TOLERANCE for r in rows
|
|
427
|
+
),
|
|
428
|
+
"faster": sum(sp > 1 for sp in speedups),
|
|
429
|
+
"geomean_speedup": _geomean(speedups),
|
|
430
|
+
"min_speedup": min(speedups) if speedups else None,
|
|
431
|
+
"max_speedup": max(speedups) if speedups else None,
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
groups = sorted({benchmark_group(r["case"]) for r in self.rows})
|
|
435
|
+
out = [summarise(g, [r for r in self.rows if benchmark_group(r["case"]) == g]) for g in groups]
|
|
436
|
+
out.append(summarise("Overall", self.rows))
|
|
437
|
+
return out
|
|
438
|
+
|
|
439
|
+
_OVERALL_TITLES = ("Suite", "Cases", "Rows", "Match reference", "Faster", "Geo-mean speed-up", "Range")
|
|
440
|
+
|
|
441
|
+
def _overall_cells(self) -> list[list[str]]:
|
|
442
|
+
def x(v: Optional[float]) -> str:
|
|
443
|
+
return "–" if v is None else f"{v:.2f}×"
|
|
444
|
+
|
|
445
|
+
return [
|
|
446
|
+
[
|
|
447
|
+
o["group"],
|
|
448
|
+
str(o["cases"]),
|
|
449
|
+
str(o["rows"]),
|
|
450
|
+
f"{o['matching']}/{o['compared']}",
|
|
451
|
+
f"{o['faster']}/{o['compared']}",
|
|
452
|
+
x(o["geomean_speedup"]),
|
|
453
|
+
"–" if o["min_speedup"] is None else f"{x(o['min_speedup'])}–{x(o['max_speedup'])}",
|
|
454
|
+
]
|
|
455
|
+
for o in self.overall()
|
|
456
|
+
]
|
|
457
|
+
|
|
458
|
+
def overall_markdown(self) -> str:
|
|
459
|
+
"""The overall summary as a Markdown table."""
|
|
460
|
+
lines = ["| " + " | ".join(self._OVERALL_TITLES) + " |", "| --- |" + " ---: |" * 6]
|
|
461
|
+
return "\n".join(lines + ["| " + " | ".join(c) + " |" for c in self._overall_cells()])
|
|
462
|
+
|
|
385
463
|
def _cells(self, digits: int) -> list[list[str]]:
|
|
386
464
|
def f(v: Any, d: int = digits) -> str:
|
|
387
465
|
return "–" if v is None else f"{v:.{d}f}"
|
|
@@ -398,7 +476,7 @@ class BenchmarkResult:
|
|
|
398
476
|
f(r.get("reference_peak_mb"), 2),
|
|
399
477
|
"–" if r["max_abs_diff"] is None else f"{r['max_abs_diff']:.1e}",
|
|
400
478
|
]
|
|
401
|
-
for r in self.
|
|
479
|
+
for r in self.sorted_rows()
|
|
402
480
|
]
|
|
403
481
|
|
|
404
482
|
_TITLES = (
|
|
@@ -430,7 +508,14 @@ class BenchmarkResult:
|
|
|
430
508
|
+ f" | {env['machine']} | fastest of {env['repeat']} runs"
|
|
431
509
|
)
|
|
432
510
|
note = "Speed-up > 1 means EvalSuite is faster. Max |difference| compares EvalSuite with the reference."
|
|
433
|
-
|
|
511
|
+
ocells = self._overall_cells()
|
|
512
|
+
owidths = [max(len(t), *(len(c[i]) for c in ocells)) for i, t in enumerate(self._OVERALL_TITLES)]
|
|
513
|
+
|
|
514
|
+
def oline(c: Sequence[str]) -> str:
|
|
515
|
+
return " ".join(x.ljust(owidths[i]) if i == 0 else x.rjust(owidths[i]) for i, x in enumerate(c))
|
|
516
|
+
|
|
517
|
+
overall = ["Overall", oline(self._OVERALL_TITLES), *(oline(c) for c in ocells), ""]
|
|
518
|
+
return "\n".join([head, "", *overall, line(self._TITLES), *(line(c) for c in cells), "", note])
|
|
434
519
|
|
|
435
520
|
def __repr__(self) -> str:
|
|
436
521
|
return self.summary()
|
|
@@ -438,7 +523,13 @@ class BenchmarkResult:
|
|
|
438
523
|
def to_dict(self) -> dict[str, Any]:
|
|
439
524
|
return cast(
|
|
440
525
|
"dict[str, Any]",
|
|
441
|
-
_json_safe(
|
|
526
|
+
_json_safe(
|
|
527
|
+
{
|
|
528
|
+
"environment": dict(self.environment),
|
|
529
|
+
"overall": self.overall(),
|
|
530
|
+
"rows": [dict(r) for r in self.rows],
|
|
531
|
+
}
|
|
532
|
+
),
|
|
442
533
|
)
|
|
443
534
|
|
|
444
535
|
def to_json(self, *, indent: Optional[int] = 2) -> str:
|
|
@@ -514,7 +605,7 @@ def run_benchmarks(
|
|
|
514
605
|
if compare_sklearn:
|
|
515
606
|
for mod in versions:
|
|
516
607
|
with contextlib.suppress(ImportError):
|
|
517
|
-
|
|
608
|
+
importlib.import_module(mod) # fixed names only: sklearn, statsmodels, pycocotools
|
|
518
609
|
from importlib.metadata import version as _dist_version
|
|
519
610
|
|
|
520
611
|
versions[mod] = _dist_version("scikit-learn" if mod == "sklearn" else mod)
|
evalsuite/core/validation.py
CHANGED
|
@@ -45,9 +45,25 @@ def to_numpy(x: ArrayLike, name: str, *, allow_2d: bool = False) -> NDArray[Any]
|
|
|
45
45
|
raise InputValidationError(f"{name} must be {expected}; received an array with shape {arr.shape}.")
|
|
46
46
|
if arr.shape[0] == 0:
|
|
47
47
|
raise InputValidationError(f"{name} is empty. Provide at least one observation.")
|
|
48
|
+
if (
|
|
49
|
+
arr.ndim == 1
|
|
50
|
+
and arr.dtype.kind in "US"
|
|
51
|
+
and isinstance(x, (list, tuple))
|
|
52
|
+
and not all(isinstance(v, (str, bytes)) for v in x)
|
|
53
|
+
):
|
|
54
|
+
# NumPy silently turns [0, "a"] into ["0", "a"]; a mix of numbers and strings is almost always a bug.
|
|
55
|
+
raise InputValidationError(f"{name} mixes numbers and strings; use one label type throughout.")
|
|
48
56
|
return arr
|
|
49
57
|
|
|
50
58
|
|
|
59
|
+
def _label_kind(arr: NDArray[Any]) -> str:
|
|
60
|
+
if arr.dtype.kind in "US":
|
|
61
|
+
return "string"
|
|
62
|
+
if arr.dtype.kind in "biuf":
|
|
63
|
+
return "number"
|
|
64
|
+
return "other"
|
|
65
|
+
|
|
66
|
+
|
|
51
67
|
def check_finite(arr: NDArray[Any], name: str) -> None:
|
|
52
68
|
if np.issubdtype(arr.dtype, np.number) and not np.all(np.isfinite(arr)):
|
|
53
69
|
n_nan = int(np.isnan(arr).sum())
|
|
@@ -126,6 +142,11 @@ def resolve_labels(
|
|
|
126
142
|
if np.unique(lab).shape[0] != lab.shape[0]:
|
|
127
143
|
raise InputValidationError("labels contains duplicates.")
|
|
128
144
|
return lab
|
|
145
|
+
if y_pred is not None and {_label_kind(y_true), _label_kind(y_pred)} == {"string", "number"}:
|
|
146
|
+
raise InputValidationError(
|
|
147
|
+
f"y_true has {_label_kind(y_true)} labels but y_pred has {_label_kind(y_pred)} labels; "
|
|
148
|
+
"use the same label type in both (for example map class names to integers first)."
|
|
149
|
+
)
|
|
129
150
|
present = y_true if y_pred is None else np.concatenate([y_true, y_pred])
|
|
130
151
|
try:
|
|
131
152
|
return unique_labels(present)
|
evalsuite/regression/metrics.py
CHANGED
|
@@ -202,7 +202,15 @@ def rmse(
|
|
|
202
202
|
) -> MetricResult:
|
|
203
203
|
"""Root mean squared error (square root taken per output, then averaged)."""
|
|
204
204
|
inp = _inputs(y_true, y_pred, sample_weight)
|
|
205
|
-
|
|
205
|
+
with np.errstate(over="ignore"):
|
|
206
|
+
per_output = np.sqrt(inp.mean(inp.error**2))
|
|
207
|
+
if not np.all(np.isfinite(per_output)):
|
|
208
|
+
# Errors above ~1e154 overflow when squared although the RMSE itself is representable:
|
|
209
|
+
# rescale by the largest error and square again.
|
|
210
|
+
scale = np.abs(inp.error).max(axis=0)
|
|
211
|
+
scale = np.where(np.isfinite(scale) & (scale > 0), scale, 1.0)
|
|
212
|
+
per_output = scale * np.sqrt(inp.mean((inp.error / scale) ** 2))
|
|
213
|
+
return _finish(per_output, inp, multioutput, "rmse", "RMSE")
|
|
206
214
|
|
|
207
215
|
|
|
208
216
|
def _r2_per_output(inp: _Inputs) -> FloatArray:
|
evalsuite/stats/_resolve.py
CHANGED
|
@@ -10,7 +10,7 @@ from typing import Any, Optional
|
|
|
10
10
|
import numpy as np
|
|
11
11
|
from numpy.typing import NDArray
|
|
12
12
|
|
|
13
|
-
from ..core.exceptions import InputValidationError
|
|
13
|
+
from ..core.exceptions import InputValidationError, StatisticalTestError
|
|
14
14
|
from ..core.validation import target_type, to_numpy
|
|
15
15
|
|
|
16
16
|
MetricFn = Callable[..., Any]
|
|
@@ -89,6 +89,11 @@ class MetricCall:
|
|
|
89
89
|
f"observations. Received {self.y_true.shape[0]} and {self.second.shape[0]}."
|
|
90
90
|
)
|
|
91
91
|
self.n = self.y_true.shape[0]
|
|
92
|
+
if self.n < 2:
|
|
93
|
+
raise StatisticalTestError(
|
|
94
|
+
f"Resampling needs at least 2 observations; got {self.n}. An interval or test from a single "
|
|
95
|
+
"observation would have zero width and no meaning."
|
|
96
|
+
)
|
|
92
97
|
self.weight = None if sample_weight is None else to_numpy(sample_weight, "sample_weight")
|
|
93
98
|
self.kwargs = dict(kwargs or {})
|
|
94
99
|
params = inspect.signature(fn).parameters
|
evalsuite/version.py
CHANGED
evalsuite/vision/segmentation.py
CHANGED
|
@@ -84,9 +84,17 @@ _REF_HD = (
|
|
|
84
84
|
|
|
85
85
|
# ---- input handling ------------------------------------------------------------------------------
|
|
86
86
|
def _as_images(masks: Masks, name: str) -> list[NDArray[Any]]:
|
|
87
|
+
images = None
|
|
87
88
|
if isinstance(masks, (list, tuple)) or (isinstance(masks, np.ndarray) and masks.dtype == object):
|
|
88
89
|
images = [np.asarray(m) for m in masks]
|
|
89
|
-
|
|
90
|
+
if (
|
|
91
|
+
images
|
|
92
|
+
and isinstance(masks, (list, tuple))
|
|
93
|
+
and all(m.ndim == 1 for m in images)
|
|
94
|
+
and not any(isinstance(m, np.ndarray) for m in masks)
|
|
95
|
+
):
|
|
96
|
+
images = None # a nested Python list of rows, e.g. [[1, 1], [0, 0]], is one 2-D mask
|
|
97
|
+
if images is None:
|
|
90
98
|
arr = np.asarray(masks)
|
|
91
99
|
if arr.ndim < 2:
|
|
92
100
|
raise InputValidationError(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: evalsuite-python
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: A unified Python framework for machine-learning, clinical, statistical, segmentation, object-detection, uncertainty, and model evaluation.
|
|
5
5
|
Project-URL: Homepage, https://evalsuite-nine.vercel.app
|
|
6
6
|
Project-URL: Documentation, https://evalsuite-nine.vercel.app/docs
|
|
@@ -49,7 +49,7 @@ Requires-Dist: pycocotools>=2.0.7; extra == 'dev'
|
|
|
49
49
|
Requires-Dist: pytest-cov>=4; extra == 'dev'
|
|
50
50
|
Requires-Dist: pytest>=7; extra == 'dev'
|
|
51
51
|
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
52
|
-
Requires-Dist: scikit-learn>=1.
|
|
52
|
+
Requires-Dist: scikit-learn>=1.4; extra == 'dev'
|
|
53
53
|
Requires-Dist: statsmodels>=0.13; extra == 'dev'
|
|
54
54
|
Requires-Dist: twine; extra == 'dev'
|
|
55
55
|
Provides-Extra: plot
|
|
@@ -70,7 +70,7 @@ Description-Content-Type: text/markdown
|
|
|
70
70
|
EvalSuite brings classification, regression, clinical, statistical, segmentation and object-detection
|
|
71
71
|
evaluation into one consistent, validated, documented framework.
|
|
72
72
|
|
|
73
|
-
> **Status: stable (0.3.
|
|
73
|
+
> **Status: stable (0.3.1).** Every item on the 0.1.0, 0.2.0 and 0.3.0 roadmaps is implemented and verified.
|
|
74
74
|
|
|
75
75
|
## Installation
|
|
76
76
|
|
|
@@ -283,24 +283,28 @@ Input files can be CSV, TSV, Parquet or JSON. Output format follows `--format` o
|
|
|
283
283
|
## Performance
|
|
284
284
|
|
|
285
285
|
Benchmarked against reference implementations on the same data (fastest of 5 runs; Python 3.12, NumPy 2.5,
|
|
286
|
-
Linux x86_64).
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
|
292
|
-
|
|
|
293
|
-
|
|
|
294
|
-
|
|
|
295
|
-
|
|
|
296
|
-
| calibration slope and intercept |
|
|
297
|
-
|
|
|
298
|
-
|
|
|
299
|
-
|
|
|
300
|
-
|
|
|
301
|
-
|
|
|
302
|
-
|
|
|
303
|
-
|
|
|
286
|
+
Linux x86_64). **Overall: 45 of 45 rows agree with the reference** (largest
|
|
287
|
+
difference 2.8e-14), 32 are faster, and the geometric-mean speed-up across all
|
|
288
|
+
15 cases and three sizes is **2.22×**. At 1,000,000 samples (pixels for
|
|
289
|
+
segmentation; 1,000 images for detection and 50 for Hausdorff), in alphabetical order:
|
|
290
|
+
|
|
291
|
+
| Case | Reference | EvalSuite (ms) | Reference (ms) | Speed-up |
|
|
292
|
+
| --- | --- | ---: | ---: | ---: |
|
|
293
|
+
| 10 classes: macro F1 | scikit-learn | 29.3 | 130.8 | **4.5×** |
|
|
294
|
+
| binary: 8 label metrics via evaluate() | scikit-learn | 39.5 | 1084.1 | **27.4×** |
|
|
295
|
+
| binary: ROC AUC | scikit-learn | 195.0 | 348.3 | **1.8×** |
|
|
296
|
+
| calibration: slope and intercept | statsmodels | 193.0 | 1068.0 | **5.5×** |
|
|
297
|
+
| clinical: diagnostic report (7 CIs) | statsmodels | 23.5 | 4.7 | 0.20× |
|
|
298
|
+
| clinical: sensitivity, specificity, LR+, LR− | scikit-learn | 69.1 | 414.0 | **6.0×** |
|
|
299
|
+
| decision curve: 99 thresholds | NumPy loop | 156.3 | 181.6 | **1.2×** |
|
|
300
|
+
| detection: COCO evaluation (1000 images) | pycocotools | 817.3 | 983.7 | **1.2×** |
|
|
301
|
+
| multiple testing: Hochberg (n p-values) | statsmodels | 82.0 | 108.0 | **1.3×** |
|
|
302
|
+
| regression: MAE, MSE, RMSE, R² via evaluate() | scikit-learn | 23.1 | 10.8 | 0.47× |
|
|
303
|
+
| segmentation: Dice and IoU per class (n = pixels) | scikit-learn | 43.0 | 290.0 | **6.8×** |
|
|
304
|
+
| segmentation: Hausdorff distance (50 images) | SciPy | 27.0 | 20.2 | 0.75× |
|
|
305
|
+
| statistics: Cramér's V (5×5 table) | SciPy | 0.5 | 0.4 | 0.88× |
|
|
306
|
+
| statistics: Mann–Whitney U | SciPy | 349.7 | 350.2 | **1.0×** |
|
|
307
|
+
| statistics: Welch t-test | SciPy | 14.5 | 7.2 | 0.49× |
|
|
304
308
|
|
|
305
309
|
`evaluate()` validates inputs once and builds the confusion matrix once for all metrics, which is where most
|
|
306
310
|
of the speed-up comes from. Hypothesis tests use SciPy underneath, so they match its speed at best; rows
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
evalsuite/__init__.py,sha256=5QLHlf6OX5UMBiPPpo9TrIhJYgCmqLXlzOgUkhPxxKw,5267
|
|
2
2
|
evalsuite/__main__.py,sha256=Nq90_8VlUN1mif-AVgX-kZRL63bd94F5-F7F9UkVZD4,117
|
|
3
3
|
evalsuite/api.py,sha256=TU49b4DolAm6dwU3ypJprOEzv5hJOsnRiXLwccyaGew,10170
|
|
4
|
-
evalsuite/benchmarks.py,sha256=
|
|
4
|
+
evalsuite/benchmarks.py,sha256=GzC6yNdxkih6Coe8hNqUSxTc6NLVfOP5MOK1K1TDuUo,26992
|
|
5
5
|
evalsuite/calibration.py,sha256=sP7XO29Lk6wNp7qS5INNDtpz6SuVGGZhYUxSrTUxj94,14979
|
|
6
6
|
evalsuite/plot.py,sha256=tfyuIF_8m-lrn87Eqq7GkQG5OWfD9yQNBRGKHCtYVLk,20016
|
|
7
7
|
evalsuite/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
8
|
evalsuite/reporting.py,sha256=-LISv9vvEnltT26GtzLjVlxOCcAwmjv4-HyB8_1UF5o,9615
|
|
9
|
-
evalsuite/version.py,sha256=
|
|
9
|
+
evalsuite/version.py,sha256=FZk8M-bQVGqb0YvmxRi1eu5Z11BEwSB4mexHdE1qj48,98
|
|
10
10
|
evalsuite/classification/__init__.py,sha256=ErBIXbBGnhfW6v-1Cn5SegiERoyxNlmO1tEKcLM15mA,833
|
|
11
11
|
evalsuite/classification/_common.py,sha256=3ANV33ix_mnOzvOAG8glyJO-iYVhhTGO0S3YG0ZddB8,4543
|
|
12
12
|
evalsuite/classification/metrics.py,sha256=8-RPjzuFUKJYlXndrDv6kXlzRdx6aR2lHp7mzKsas2g,36969
|
|
@@ -22,11 +22,11 @@ evalsuite/core/export.py,sha256=6M_ktQzW3E7usOrwqv5f5zOEdoi48JD6CvgyRpDkGvM,4303
|
|
|
22
22
|
evalsuite/core/registry.py,sha256=3l2_o2PlckuKY89HxfnxPLf-sDaCe_-McUcAcUmXusk,2884
|
|
23
23
|
evalsuite/core/result.py,sha256=L_fQZRGRgVgzII2jZb_jpRBK2jy-CdO5u9s-6pUk9fE,14927
|
|
24
24
|
evalsuite/core/types.py,sha256=r6bhUk7CYAcrlQzjmf-6xWQsNqO3EOipZD-e-2yAJTI,720
|
|
25
|
-
evalsuite/core/validation.py,sha256=
|
|
25
|
+
evalsuite/core/validation.py,sha256=nWWyISLdW2TtzxUs3gT-Qx2uh6euDOlYMvbnCrFRYME,9975
|
|
26
26
|
evalsuite/regression/__init__.py,sha256=t2XEHUw6e5tyWBHcEeiog2WWd-wwaxf4m5AIX8dJyng,571
|
|
27
|
-
evalsuite/regression/metrics.py,sha256=
|
|
27
|
+
evalsuite/regression/metrics.py,sha256=5i3hmiFfZGfmqtFDaDOxGHRYCXzdt48-GNfgvVOX7CM,22914
|
|
28
28
|
evalsuite/stats/__init__.py,sha256=mtnEqpvlvscQ3C6ceRr8xLKoSHPQWsWB24pEVlvp6fs,1187
|
|
29
|
-
evalsuite/stats/_resolve.py,sha256=
|
|
29
|
+
evalsuite/stats/_resolve.py,sha256=QhvI6A2Ui2gbS1qY5AAofz47hYO_DSoyQtKlRA2wZ7M,5036
|
|
30
30
|
evalsuite/stats/compare.py,sha256=2c66hQNgsxl2DBEOeebl-SRxQ83ZkO_71lAfvf9jZEU,17998
|
|
31
31
|
evalsuite/stats/effect.py,sha256=Esw1Di0BSabiErcsxoUinB9V0-ByEQ5fTLzAptf-dBo,6943
|
|
32
32
|
evalsuite/stats/hypothesis.py,sha256=Sd3vcPUYVs_QwZ0IKKgQEFqtFcFan_CTy0EHjHEgIF4,12773
|
|
@@ -35,9 +35,9 @@ evalsuite/stats/paired.py,sha256=YK3AFndChKeCEpK512u56VtRlKvhlGdkFLHHYe77zmc,824
|
|
|
35
35
|
evalsuite/stats/results.py,sha256=nqXHUiW8l0fQJkbMiunU6Gz-2be1NApZ6Fif2B1K_Yw,4407
|
|
36
36
|
evalsuite/vision/__init__.py,sha256=9gpOBTPveM_srE6BM-SgCssdQurya2LPHhoMLGOh2A0,991
|
|
37
37
|
evalsuite/vision/detection.py,sha256=eUnt5iFUVLEoUl1RB51q-vfr5juDCD3YH8ttLFrqxFg,27781
|
|
38
|
-
evalsuite/vision/segmentation.py,sha256=
|
|
39
|
-
evalsuite_python-0.3.
|
|
40
|
-
evalsuite_python-0.3.
|
|
41
|
-
evalsuite_python-0.3.
|
|
42
|
-
evalsuite_python-0.3.
|
|
43
|
-
evalsuite_python-0.3.
|
|
38
|
+
evalsuite/vision/segmentation.py,sha256=7h0AirBU0G6XMWzdA7MQNO52hXz8oboNAX9s55y6SVQ,38647
|
|
39
|
+
evalsuite_python-0.3.1.dist-info/METADATA,sha256=75uFR4hsGdPZy40k1PwTyyubHsmSBSDOSAJK1Kyho1g,17640
|
|
40
|
+
evalsuite_python-0.3.1.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
41
|
+
evalsuite_python-0.3.1.dist-info/entry_points.txt,sha256=YYIwisn4L4sQt3ntzbM0_Z4yZE2KCu3GJ6KfWL1kIwc,54
|
|
42
|
+
evalsuite_python-0.3.1.dist-info/licenses/LICENSE,sha256=cRRQ6Kk8w2qCqtDSSUJQGy-0rqjmjJG09cZ6iIiMvdc,1095
|
|
43
|
+
evalsuite_python-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|