ek.harness#
The offline evaluation harness: run a predictor over gold, gate regressions.
Reference-based benchmarking (Need #1) is only useful if it is repeatable and
regression-safe: a “better” system must not silently get worse on some slice. The
harness adds that discipline on top of ek.score()/ek.evaluate():
evaluate_store()– run anyinput -> predictionpredictor over a gold store (a dict or aekgold store), scored per slice (grouped by each record’s slice label), with results persisted. (The OCR benchmark inek.ocris the OCR-specific specialization of this.)save_baseline()/regression_gate()– freeze a baseline and fail when a later run regresses beyond a tolerance, per slice, not just on the aggregate. This is the golden-set CI gate.cohen_kappa()/percent_agreement()/krippendorff_alpha()– inter-annotator agreement (IAA), to know the ceiling of your gold standard before trusting any model score (all pure-Python, no optional dependency).
See misc/docs/ek_02 for the harness design (canonicalizer versioning, slicing,
IAA conventions, golden-set CI).
Functions
|
Cohen's kappa for two raters on nominal labels (chance-corrected agreement). |
|
Run |
|
Krippendorff's alpha -- the general inter-annotator agreement coefficient. |
|
Load a named baseline (or |
|
Raw fraction of items two raters labelled identically. |
|
Fail if |
|
Freeze a report's aggregate + per-slice scores as a named baseline. |
Classes
|
Outcome of a |
- class ek.harness.GateResult(passed, metric, higher_is_better, tolerance, aggregate_current=None, aggregate_baseline=None, regressions=<factory>)[source]#
Bases:
objectOutcome of a
regression_gate()check.
- ek.harness.cohen_kappa(rater_a, rater_b)[source]#
Cohen’s kappa for two raters on nominal labels (chance-corrected agreement).
Use only for exactly two raters, nominal labels, complete data; prefer
krippendorff_alpha()for the general case (missing data, any measurement level).- Return type:
- ek.harness.evaluate_store(predict, gold, *, metric=None, grammar=None, normalize=None, weights=None, input_key='input', reference_key='reference', slice_key='slice', persist=False, run_id=None, rootdir=None)[source]#
Run
predictover a gold store and score it per slice.- Parameters:
predict (
Callable[[Any],Any]) –input -> predictioncallable (the system under test).gold (
Mapping) – Mappingkey -> {input, reference, [slice], ...}(a dict or aekgold store).metric (
Optional[str]) – Metric name/callable (defaults to type-dispatch on the first case).grammar/normalize/weights – forwarded to scoring.
input_key/reference_key/slice_key – field names within each gold record.
persist/run_id/rootdir – persist the run to the
results/runsstores.
- Returns:
A
Report;detail['per_item']maps each key to its prediction, reference, slice, and score.
- ek.harness.krippendorff_alpha(reliability_data, *, level='nominal')[source]#
Krippendorff’s alpha – the general inter-annotator agreement coefficient.
Pure-Python (no dependency, permissive core): any number of raters, any measurement
level("nominal","ordinal","interval","ratio"), and missing data (useNoneorfloat('nan')for an unlabelled cell).reliability_datais one row per rater, one column per item. Alpha is1.0for perfect agreement,0.0at chance, and goes negative for systematic disagreement. Computed via the coincidence-matrix method (Krippendorff 2011): observed vs expected disagreement under the level-specific difference metric.- Return type:
Example
>>> data = [[1, 1, 1, 1], [1, 1, 1, 1]] # two raters, perfect agreement >>> krippendorff_alpha(data) 1.0
- ek.harness.load_baseline(name, *, rootdir=None)[source]#
Load a named baseline (or
Noneif it does not exist).
- ek.harness.percent_agreement(rater_a, rater_b)[source]#
Raw fraction of items two raters labelled identically.
- Return type:
- ek.harness.regression_gate(report, baseline, *, tolerance=0.0, higher_is_better=None, rootdir=None)[source]#
Fail if
reportregresses beyondtolerancevs a baseline, per slice.- Parameters:
report – The current
Report.baseline (
Any) – A baseline name (loaded from thebaselinesstore) or a baseline dict fromsave_baseline().tolerance (
float) – Allowed drift before a change counts as a regression.higher_is_better (
Optional[bool]) – Override metric-direction inference (CER/WER/graph are lower-is-better; F1/similarity are higher-is-better).rootdir (
Optional[str]) – data root (whenbaselineis a name).
- Return type:
- Returns:
A
GateResult(falsy if any regression was found).