-
Notifications
You must be signed in to change notification settings - Fork 0
0013 sentencepiece parity scope
Status: accepted, superseded in part by 0014 · Date: 2026-08-06
Section 1 below no longer holds:
0014implemented the precompiled normalizer, the fixture keeps its stocknmt_nfkcmap, and the oracle covers the stock XLM-R pipeline rather than its vocabulary alone. That is the revision this decision asked for in its last consequence. Section 2, the unknown-piece penalty floor, stands.
SentencePieceTokenizer names ALBERT, T5, camemBERT and XLM-R in its
documentation. #63 asked for
that claim to be earned: a control-piece filter that guessed by id worked only
for vocabularies laying <unk>, <s> and </s> out at 0, 1 and 2, and the
oracle — a 984-byte self-trained model doing exactly that — could not see the
failure. The filter now reads SentencePieceVocabulary.Types, and the oracle
now includes XLM-R's own vocabulary.
Building that oracle surfaced two things the parity claim has to state rather than imply.
xlm-roberta-base ships two things this library treats differently:
| Stock file | What DataNet does | |
|---|---|---|
| Vocabulary — 250 000 pieces, their scores, their types | sentencepiece.bpe.model |
reproduced exactly |
Normalizer — nmt_nfkc plus a 237 KB precompiled character map |
same file |
refused by SentencePieceModelLoader
|
Two further facts make a straight copy of the stock file useless as a fixture:
- its own layout is the raw one (
<unk>=0,<s>=1,</s>=2, no<pad>, no<mask>) — the fairseq numbering lives in HuggingFace's tokenizer wrapper, not in the file, so the stock file exercises precisely the case the old guess got right; - it cannot be loaded at all, because of the normalizer.
tools/fetch_xlmr_vocab.py therefore re-emits the vocabulary:
tests/oracles/xlmr_fairseq.model carries the same pieces, scores and types at
the ids HuggingFace gives them (<s>=0, <pad>=1, </s>=2, <unk>=3,
<mask>=250001), with the normalizer set to identity. The reference values in
xlmr_fairseq.json come from sentencepiece reading that same file, so both
sides normalize identically and the comparison stays honest.
What this proves: over a real 250 002-piece multilingual vocabulary in the
layout the issue is about, DataNet's Viterbi segmentation is identical to
sentencepiece's, and no control or unknown piece is ever matched as text — not
even for input that names all five markers literally.
What it does not prove: that DataNet reproduces stock XLM-R end to end. It does
not, and says so — nmt_nfkc is refused rather than approximated, because a
tokenizer that normalizes differently produces different embeddings while
looking like it works. Implementing the precompiled character map is a separate
piece of work.
sentencepiece scores an uncovered character at min_score - 10, where
min_score is the lowest piece score in the vocabulary. DataNet computes
min(0, min_score) - 10.
The two agree for every real model — SentencePiece scores are log-probabilities,
so min_score is negative and the floor never binds. They differ only for a
hand-built vocabulary whose scores are all positive, where DataNet penalises the
unknown piece more than sentencepiece would (-10 against, say, +5 - 10).
Keep the floor. It is the safe direction — a heavier penalty can only make
the unknown piece lose a comparison it would otherwise have won — and it keeps
the constructor total: initialising to double.MaxValue instead would give a
vocabulary with no matchable piece an unknown score of double.MaxValue - 10,
which is a positive reward, not a penalty.
-
docs/equivalence.mdstates which models the tokenizer row is verified against, instead of an unqualified "exact parity". - The 5.3 MB fixture is a redistributed third-party resource. It is the
vocabulary only — never weights, per
0003— and is attributed inTHIRD-PARTY-NOTICES.md.xlm-roberta-baseis MIT-licensed. - The fixture is an input to
tools/generate_oracles.py, liketiny_sp.modelbefore it: theOracles are reproduciblejob regenerates the JSON from it and needs no network. Rebuilding the fixture itself is a deliberate act (tools/fetch_xlmr_vocab.py), pinned to a SHA-256 of the upstream download. - If the precompiled normalizer is ever implemented, this decision should be revisited: the stock file would then load, and the oracle could replay stock XLM-R rather than its vocabulary.
- 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