Token Classification
Transformers
Safetensors
ONNX
Transformers.js
modernbert
punctuation
punctuation-restoration
asr
speech-recognition
transcription
mmbert
Instructions to use seamon67/Punctuation-Restoration with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use seamon67/Punctuation-Restoration with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="seamon67/Punctuation-Restoration")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForTokenClassification tokenizer = AutoTokenizer.from_pretrained("seamon67/Punctuation-Restoration") model = AutoModelForTokenClassification.from_pretrained("seamon67/Punctuation-Restoration", device_map="auto") - Transformers.js
How to use seamon67/Punctuation-Restoration with Transformers.js:
// npm i @huggingface/transformers import { pipeline } from '@huggingface/transformers'; // Allocate pipeline const pipe = await pipeline('token-classification', 'seamon67/Punctuation-Restoration'); - Notebooks
- Google Colab
- Kaggle
File size: 3,783 Bytes
9456b7b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | """Training windows for punctuation restoration from FineWeb-2 / FineWeb (ODC-BY) snippets (.gated/emb_texts.parquet,
built by emb/build_texts.py: pid, text, lang, url). python punct/build_data.py TEXTS.parquet OUT_DIR [MAX_PER_LANG]
Filter: the snippet ends with a sentence-final mark, >= 6 units, mostly letters, no 60-unit run without any mark, at most
35% of units labelled (lists). Windows: 1-4 snippets of the same language joined (up to 230 words / 400 CJK characters,
the chunk size of deepmultilingualpunctuation); 30% are cut at a random unit, so a window does not always end in ".".
Output OUT_DIR/{train,val}.parquet: text (clean input), ends (unit end offsets), labs (label ids), lang. Val = 1.5% of
snippets (by pid hash). Lowercasing is applied at training time.
"""
import os, random, sys, unicodedata, zlib
import numpy as np, pandas as pd, pyarrow.parquet as pq
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from common import units, L2I, NOSPACE, SKIP
SRC, OUT = sys.argv[1:3]; MAXL = int(sys.argv[3]) if len(sys.argv) > 3 else 0
os.makedirs(OUT, exist_ok=True)
rng = random.Random(0)
END = tuple(".!?。!?।॥۔።။։؟…")
def ok(t, lang):
s = t.rstrip("\"'»”’)] ")
if not s.endswith(END) or len(t) < 30:
return None
letters = sum(c.isalpha() or unicodedata.category(c)[0] == "M" for c in t)
if letters < 0.6 * len(t.replace(" ", "")):
return None
c, e, l = units(t, lang)
if len(e) < 6:
return None
nz = [i for i, x in enumerate(l) if x != "0"]
if len(nz) > 0.35 * len(l) or max(np.diff([-1] + nz + [len(l)])) > 60:
return None
return t
pf = pq.ParquetFile(SRC)
by = {}
for g in range(pf.num_row_groups):
df = pf.read_row_group(g, columns=["pid", "text", "lang"]).to_pandas()
for pid, t, lang in df.itertuples(index=False):
if lang in SKIP:
continue
by.setdefault(lang, []).append((pid, t))
print("languages", len(by), flush=True)
rows = {"train": [], "val": []}
for lang, items in sorted(by.items()):
rng.shuffle(items)
if MAXL:
items = items[:MAXL * 3]
keep = {"train": [], "val": []}
for pid, t in items:
t = ok(t, lang)
if t:
keep["val" if zlib.crc32(str(pid).encode()) % 1000 < 15 else "train"].append(t)
for split, ts in keep.items():
cap = 400 if lang in NOSPACE else 230; sep = "" if lang in NOSPACE else " "; i = 0; n0 = len(rows[split])
while i < len(ts):
k = 1 if rng.random() < 0.4 else rng.randint(2, 4)
c, e, l = units(sep.join(ts[i:i + k]), lang); i += k
for a in range(0, len(e), cap): # split very long joins into chunks
ee, ll = e[a:a + cap], l[a:a + cap]
off = e[a - 1] + (0 if lang in NOSPACE else 1) if a else 0
if rng.random() < 0.3 and len(ee) > 12:
cut = rng.randint(8, len(ee) - 1); ee, ll = ee[:cut], ll[:cut]
if len(ee) < 4:
continue
txt = c[off:ee[-1]]
rows[split].append((txt, [x - off for x in ee], [L2I[x] for x in ll], lang))
if MAXL and len(rows[split]) - n0 >= (MAXL if split == "train" else max(50, MAXL // 50)):
break
print(lang, len(items), "kept", len(keep["train"]), "windows", sum(1 for r in rows["train"] if r[3] == lang), flush=True)
for split, r in rows.items():
df = pd.DataFrame(r, columns=["text", "ends", "labs", "lang"]).sample(frac=1.0, random_state=0)
df.to_parquet(f"{OUT}/{split}.parquet")
lab = np.bincount(np.concatenate(df.labs.map(np.array).values), minlength=6)
print(split, len(df), "units", lab.sum(), "label share", (lab / lab.sum()).round(4).tolist(), flush=True)
|