-
Notifications
You must be signed in to change notification settings - Fork 0
Metrics multiclassrocoptions
Everything optional about RocAuc.MultiClass, in one ref struct so the spans can travel with
the
rest.
public readonly ref struct MultiClassRocOptionsProperties — Strategy is one-vs-rest or one-vs-one, MultiClassStrategy.OneVsRest by
default.
Average is Averaging.Macro or Averaging.Weighted, and is nullable so that default can mean
macro: default(Averaging) is Averaging.Binary, which multiclass ROC-AUC refuses. Labels
names
the classes the score columns stand for, sorted ascending and unique; empty reads them off
yTrue,
which is wrong when a class is absent from it. SampleWeight weights the samples and is refused
with one-vs-one, as scikit-learn refuses it. MaxDegreeOfParallelism is how many workers run the
per-class or per-pair loop; 0 and 1 are sequential, and there is no sentinel for "all cores" —
write Environment.ProcessorCount.
Example — the same scores under both strategies and both averages.
using Lodestar.Metrics;
int[] yTrue = [0, 1, 2, 2, 2, 1];
double[] yScore =
[
0.6, 0.3, 0.1,
0.3, 0.5, 0.2,
0.2, 0.5, 0.3,
0.1, 0.2, 0.7,
0.4, 0.4, 0.2,
0.2, 0.3, 0.5,
];
MultiClassRocOptions weightedOptions = new() { Average = Averaging.Weighted };
MultiClassRocOptions pairwise = new() { Strategy = MultiClassStrategy.OneVsOne };
double macro = RocAuc.MultiClass(yTrue, yScore, 3); // => 0.7824…
double weighted = RocAuc.MultiClass(yTrue, yScore, 3, weightedOptions); // => 0.7361…
double pairs = RocAuc.MultiClass(yTrue, yScore, 3, pairwise); // => 0.8194…Remarks — default reproduces scikit-learn's own defaults, so the three-argument call is the
one to write until you need something else. Being a ref struct is what lets Labels and
SampleWeight be spans rather than arrays: build it at the call site, and do not try to store it
in
a field.
MaxDegreeOfParallelism is the one setting with no Python counterpart, and it is opt-in rather
than
automatic on purpose — the result is bit-identical at any setting, and above 1 the inputs are
copied, so it is a trade a caller should make knowingly.
Decision 0018 has the
argument.
The trap is Labels. Leaving it empty means the score columns are matched to the sorted
distinct
labels of yTrue, so if your model has five classes and only four of them occur in this
evaluation set, the columns silently shift by one and the number that comes back is meaningless
rather than wrong-looking. Pass Labels whenever the label set is fixed by the model rather than
by
the data.
Applies to — net10.0, netstandard2.0.
See also — RocAuc.MultiClass, MultiClassStrategy, Averaging,
decision 0018,
the Python equivalence table.
| Member | What it does |
|---|
- 0001-target-framework
- 0002-unicode-comparison-unit
- 0003-provenance-and-licensing
- 0004-levenshtein-myers-backlog
- 0005-hamming-jellyfish-divergence
- 0006-ratcliff-autojunk
- 0007-metaphone-scope
- 0008-italian-enza-nltk-divergence
- 0009-sample-consumes-a-local-feed
- 0010-stop-word-list-provenance
- 0011-persistence-format
- 0012-per-package-versioning
- 0013-sentencepiece-parity-scope
- 0014-precompiled-normalizer
- 0015-sonar-rules-in-the-build
- 0016-metrics-package-placement
- 0017-bpe-parity-scope
- 0018-multiclass-roc-auc-parallelism-is-opt-in
- 0019-the-net-analysers-run-in-the-build-too
- 0020-normalize-is-a-projection-not-a-parameter
- 0021-multioutput-is-a-method-not-an-enum
- 0022-added-token-matching-flags
- 0023-byte-level-decode-substitutes
- 0024-weighted-median-averages-within-scikit-learns-epsilon
- 0025-quickselect-replaces-a-full-sort-for-the-median
- 0026-r2-and-explainedvariance-split-their-undefined-cases-differently
- 0027-r2-and-explainedvariance-vectorize-only-a-single-output
- 0028-log1p-is-kahans-identity-not-math-log-1-plus-x
- 0029-balanced-accuracy-adjusted-is-left-to-ieee-754-at-the-edge
- 0030-cohen-kappa-keeps-scikit-learns-expected-matrix-orientation
- 0031-nosamplecorrect-mirrors-numpys-float64-upcast
- 0032-fbeta-substitutes-tp-predicted-and-support-algebraically
- 0033-compensated-sum-is-neumaiers-variant
- 0034-dropout-is-refused-for-want-of-a-user
- 0035-a-null-pre-split-is-removed-with-invert-not-isolated
- 0036-a-member-may-ship-without-an-oracle-if-it-says-so
- 0037-the-guards-run-before-the-commit
- 0038-the-gate-confronts-an-exception-tag-with-the-page-that-documents-it
- 0039-mutual-information-returns-zero-on-an-empty-input
- 0040-a-curve-is-a-sealed-class-per-curve
- 0041-one-sample-file-per-public-class
- 0042-phonetic-encoders-refuse-a-null-word
- 0043-the-equality-table-is-sized-to-the-pattern
- 0044-compression-belongs-to-the-caller
- 0045-a-console-call-carries-its-reason-on-the-line
- 0046-check-adr-immutable-runs-in-ci-only
- 0047-one-gate-per-kernel-not-one-per-alphabet
- 0048-the-gate-depends-on-the-kernel-and-the-alphabet
- 0049-two-gates-per-kernel-tested-where-the-width-is-known
- 0050-the-sentencepiece-bpe-lineage-stays-a-bpe-model
- benchmark_latest
- decisions
- equivalence
- matplotlib
- migration
- nightly_run
- numpy
- pandas
- performance
- pytorch
- seaborn
- sklearn
- statsmodels