WtP usage in wtpsplit (Legacy)

June 24, 2024 · View on GitHub

This doc details how to use the old WtP models. You should probably use SaT instead.

Usage

from wtpsplit import WtP

wtp = WtP("wtp-bert-mini")
# optionally run on GPU for better performance
# also supports TPUs via e.g. wtp.to("xla:0"), in that case pass `pad_last_batch=True` to wtp.split
wtp.half().to("cuda")

# returns ["Hello ", "This is a test."]
wtp.split("Hello This is a test.")

# returns an iterator yielding a lists of sentences for every text
# do this instead of calling wtp.split on every text individually for much better performance
wtp.split(["Hello This is a test.", "And some more texts..."])

# if you're using a model with language adapters, also pass a `lang_code`
wtp.split("Hello This is a test.", lang_code="en")

# depending on your usecase, adaptation to e.g. the Universal Dependencies style may give better results
# this always requires a language code
wtp.split("Hello This is a test.", lang_code="en", style="ud")

ONNX support

You can enable ONNX inference for the wtp-bert-* models:

wtp = WtP("wtp-bert-mini", onnx_providers=["CUDAExecutionProvider"])

This requires onnxruntime and onnxruntime-gpu. It should give a good speedup on GPU!

>>> from wtpsplit import WtP
>>> texts = ["This is a sentence. This is another sentence."] * 1000

# PyTorch GPU
>>> model = WtP("wtp-bert-mini")
>>> model.half().to("cuda")
>>> %timeit list(model.split(texts))
272 ms ± 16.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# onnxruntime GPU
>>> model = WtP("wtp-bert-mini", ort_providers=["CUDAExecutionProvider"])
>>> %timeit list(model.split(texts))
198 ms ± 1.36 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Notes:

  • The wtp-canine-* models are currently not supported with ONNX because the pooling done by CANINE is not trivial to export. Ideas to solve this are very welcome!
  • This does not work with Python 3.7 because onnxruntime does not support the opset we need for py37.

Available Models

Pro tips: I recommend wtp-bert-mini for speed-sensitive applications, otherwise wtp-canine-s-12l. The *-no-adapters models provide a good tradeoff between speed and performance. You should probably not use wtp-bert-tiny.

ModelEnglish ScoreEnglish Score
(adapted)
Multilingual ScoreMultilingual Score
(adapted)
wtp-bert-tiny83.891.979.588.6
wtp-bert-mini91.895.984.391.3
wtp-canine-s-1l94.596.586.792.8
wtp-canine-s-1l-no-adapters93.196.485.191.8
wtp-canine-s-3l94.496.886.793.4
wtp-canine-s-3l-no-adapters93.896.48692.3
wtp-canine-s-6l94.597.18793.6
wtp-canine-s-6l-no-adapters94.496.886.492.8
wtp-canine-s-9l94.89787.793.8
wtp-canine-s-9l-no-adapters94.396.986.693
wtp-canine-s-12l94.797.187.994
wtp-canine-s-12l-no-adapters94.59787.193.2

The scores are macro-average F1 score across all available datasets for "English", and macro-average F1 score across all datasets and languages for "Multilingual". "adapted" means adapation via WtP Punct; check out the paper for details.

For comparison, here's the English scores of some other tools:

ModelEnglish Score
SpaCy (sentencizer)86.8
PySBD69.8
SpaCy (dependency parser)93.1
Ersatz91.6
Punkt (nltk.sent_tokenize)92.5

Paragraph Segmentation

Since WtP models are trained to predict newline probablity, they can segment text into paragraphs in addition to sentences.

# returns a list of paragraphs, each containing a list of sentences
# adjust the paragraph threshold via the `paragraph_threshold` argument.
wtp.split(text, do_paragraph_segmentation=True)

Adaptation

WtP can adapt to the Universal Dependencies, OPUS100 or Ersatz corpus segmentation style in many languages by punctuation adaptation (preferred) or threshold adaptation.

Punctuation Adaptation

# this requires a `lang_code`
# check the paper or `wtp.mixtures` for supported styles
wtp.split(text, lang_code="en", style="ud")

This also allows changing the threshold, but inherently has higher thresholds values since it is not newline probablity anymore being thresholded:

wtp.split(text, lang_code="en", style="ud", threshold=0.7)

To get the default threshold for a style:

wtp.get_threshold("en", "ud", return_punctuation_threshold=True)

Threshold Adaptation

threshold = wtp.get_threshold("en", "ud")

wtp.split(text, threshold=threshold)

Advanced Usage

Get the newline or sentence boundary probabilities for a text:

# returns newline probabilities (supports batching!)
wtp.predict_proba(text)

# returns sentence boundary probabilities for the given style
wtp.predict_proba(text, lang_code="en", style="ud")

Load a WtP model in HuggingFace transformers:

# import wtpsplit.models to register the custom models 
# (character-level BERT w/ hash embeddings and canine with language adapters)
import wtpsplit.models
from transformers import AutoModelForTokenClassification

model = AutoModelForTokenClassification.from_pretrained("benjamin/wtp-bert-mini") # or some other model name

** NEW ** Adapt to your own corpus using WtP_Punct:

Clone the repository:

git clone https://github.com/bminixhofer/wtpsplit
cd wtpsplit

Create your data:

import torch

torch.save(
    {
        "en": {
            "sentence": {
                "dummy-dataset": {
                    "meta": {
                        "train_data": ["train sentence 1", "train sentence 2"],
                    },
                    "data": [
                        "test sentence 1",
                        "test sentence 2",
                    ]
                }
            }
        }
    },
    "dummy-dataset.pth"
)

Run adaptation:

python3 wtpsplit/evaluation/adapt.py --model_path=benjamin/wtp-bert-mini --eval_data_path dummy-dataset.pth --include_langs=en

This should print something like

en dummy-dataset U=0.500 T=0.667 PUNCT=0.667
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 30.52it/s]
Wrote mixture to /Users/bminixhofer/Documents/wtpsplit/wtpsplit/.cache/wtp-bert-mini.skops
Wrote results to /Users/bminixhofer/Documents/wtpsplit/wtpsplit/.cache/wtp-bert-mini_intrinsic_results.json

i.e. run adaptation on your data and save the mixtures and evaluation results. You can then load and use the mixture like this:

from wtpsplit import WtP
import skops.io as sio

wtp = WtP(
    "wtp-bert-mini",
    mixtures=sio.load(
        "wtpsplit/.cache/wtp-bert-mini.skops",
        ["numpy.float32", "numpy.float64", "sklearn.linear_model._logistic.LogisticRegression"],
    ),
)

wtp.split("your text here", lang_code="en", style="dummy-dataset")

... and adjust the dataset name, language and model in the above to your needs.

Reproducing the paper

configs/ contains the configs for the runs from the paper. We trained on a TPUv3-8. Launch training like this:

python wtpsplit/train/train.py configs/<config_name>.json

In addition:

  • wtpsplit/data_acquisition contains the code for obtaining evaluation data and raw text from the mC4 corpus.
  • wtpsplit/evaluation contains the code for:
    • intrinsic evaluation (i.e. sentence segmentation results) via adapt.py. The raw intrinsic results in JSON format are also at evaluation_results/
    • extrinsic evaluation on Machine Translation in extrinsic.py
    • baseline (PySBD, nltk, etc.) intrinsic evaluation in intrinsic_baselines.py
    • punctuation annotation experiments in punct_annotation.py and punct_annotation_wtp.py

Supported Languages

isoName
afAfrikaans
amAmharic
arArabic
azAzerbaijani
beBelarusian
bgBulgarian
bnBengali
caCatalan
cebCebuano
csCzech
cyWelsh
daDanish
deGerman
elGreek
enEnglish
eoEsperanto
esSpanish
etEstonian
euBasque
faPersian
fiFinnish
frFrench
fyWestern Frisian
gaIrish
gdScottish Gaelic
glGalician
guGujarati
haHausa
heHebrew
hiHindi
huHungarian
hyArmenian
idIndonesian
igIgbo
isIcelandic
itItalian
jaJapanese
jvJavanese
kaGeorgian
kkKazakh
kmCentral Khmer
knKannada
koKorean
kuKurdish
kyKirghiz
laLatin
ltLithuanian
lvLatvian
mgMalagasy
mkMacedonian
mlMalayalam
mnMongolian
mrMarathi
msMalay
mtMaltese
myBurmese
neNepali
nlDutch
noNorwegian
paPanjabi
plPolish
psPushto
ptPortuguese
roRomanian
ruRussian
siSinhala
skSlovak
slSlovenian
sqAlbanian
srSerbian
svSwedish
taTamil
teTelugu
tgTajik
thThai
trTurkish
ukUkrainian
urUrdu
uzUzbek
viVietnamese
xhXhosa
yiYiddish
yoYoruba
zhChinese
zuZulu