-
Notifications
You must be signed in to change notification settings - Fork 0
Text tversky similarity
Development build. This page describes
main, not a released package. The latest published Lodestar.Text is 0.4.0 — read its documentation.
Computes the Tversky index of two inputs: shared q-grams against each side's surplus, weighted separately.
public static double Similarity(ReadOnlySpan<char> a, ReadOnlySpan<char> b, double alpha = 1, double beta = 1, int qval = 1, TextElement element = TextElement.Utf16Unit)Parameters — a and b are the two inputs to compare; a string converts implicitly. Unlike
the rest of this namespace, their order matters unless alpha and beta are equal. alpha
weights the grams a holds and b does not, beta those b holds and a does not; both are
1 by default, which is Jaccard.Similarity. qval is how many
characters make one gram, 1 by default; it must be at least 1. element says what counts as
one character: TextElement.Utf16Unit by default, or TextElement.CodePoint to match Python
outside the Basic Multilingual Plane.
Returns — double, in [0, 1] for non-negative alpha and beta. 1 when the weighted
surpluses vanish, 0 when the two share no gram.
Exceptions — ArgumentOutOfRangeException when qval is below 1.
Example — the same pair read symmetrically, as containment, and on SorensenDice's scale.
using Lodestar.Text.Similarity;
double symmetric = Tversky.Similarity("apple", "pineapple"); // => 0.5555…
double contained = Tversky.Similarity("apple", "pineapple", alpha: 1, beta: 0); // => 1
double dice = Tversky.Similarity("apple", "pineapple", alpha: 0.5, beta: 0.5); // => 0.7142…Remarks — the weights are what make this the only asymmetric measure in the namespace.
alpha: 1, beta: 0 charges nothing for what b holds alone, so it answers "is a contained in
b" — 1 above, because every gram of "apple" is in "pineapple". Reversing the weights to
alpha: 0, beta: 1 reads 0.5555… for this pair, the same as the symmetric default, since
"apple" has no surplus of its own for alpha to charge in the first place.
Two settings reproduce neighbours exactly: alpha: 1, beta: 1 is
Jaccard.Similarity, and alpha: 0.5, beta: 0.5 is
SorensenDice.Similarity — 0.7142… above, the number that page
prints for the same pair.
Two edges belong to the caller rather than to the measure, because the weights are theirs.
A zero weight makes an empty input score 1. With beta: 0 nothing is charged for what b
holds alone, so an empty a has no surplus, no intersection and no denominator at all — and the
degenerate case answers 1, the same value two empty inputs get. An empty query is vacuously
contained in everything, which is arithmetically right and rarely what a caller wanted:
using Lodestar.Text.Similarity;
double vacuous = Tversky.Similarity("", "abc", alpha: 1, beta: 0); // => 1Negative weights leave [0, 1]. They are accepted rather than rejected, and a negative
denominator yields a legitimate quotient, so the bound in Returns holds only for non-negative
alpha and beta.
Two empty inputs give 1 whatever the weights.
Applies to — net10.0, netstandard2.0.
See also — Jaccard.Similarity,
Overlap.Similarity,
the Python equivalence table.
- 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