SentencePiece¶
SentencePiece tokenization utilities for subword segmentation.
Overview¶
SentencePiece is a language-independent subword tokenizer that can handle any language without pre-tokenization. This module provides utilities for training SentencePiece models and using them with TorchLingo.
Why SentencePiece?¶
| Problem | Solution |
|---|---|
| Unknown words | Split into known subwords |
| Large vocabulary | Control vocabulary size |
| Language-agnostic | Works for any language |
| Rare words | Shared subword representations |
Example¶
The ▁ character marks the start of a word.
Quick Start¶
Training a Model¶
from torchlingo.preprocessing import train_sentencepiece
train_sentencepiece(
input_files=["data/train.txt"],
model_prefix="models/sp",
vocab_size=8000,
model_type="bpe",
)
# Creates: models/sp.model, models/sp.vocab
Using a Model¶
from torchlingo.data_processing import SentencePieceVocab
sp = SentencePieceVocab("models/sp.model")
# Tokenize
tokens = sp.tokenize("Hello world")
print(tokens) # ['▁Hello', '▁world']
# Encode to indices
indices = sp.encode("Hello world", add_special_tokens=True)
print(indices) # [2, 145, 892, 3]
# Decode back
text = sp.decode(indices, skip_special_tokens=True)
print(text) # "Hello world"
API Reference¶
train_sentencepiece
¶
train_sentencepiece(input_files: List[Path], model_prefix: str, vocab_size: int = None, columns: Optional[List[str]] = None, src_col: str = None, tgt_col: str = None, model_type: str = None, character_coverage: float = None, normalization_rule_name: str = None, pad_idx: int = None, unk_idx: int = None, sos_idx: int = None, eos_idx: int = None, pad_token: str = None, unk_token: str = None, sos_token: str = None, eos_token: str = None, user_defined_symbols: Optional[List[str]] = None, config: Config = None)
Train a SentencePiece tokenization model on raw text data.
Reads all input files, extracts selected columns (src/tgt by default), concatenates them into a temporary file, and trains a SentencePiece model. Model files are saved with the specified prefix (e.g., 'model.model' and 'model.vocab').
Model training respects configuration for normalization, special tokens, and character coverage.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_files
|
List[Path]
|
Data files to use for training. |
required |
model_prefix
|
str
|
Output prefix for .model and .vocab files. |
required |
vocab_size
|
int
|
Target vocabulary size. Falls back to config.vocab_size. |
None
|
columns
|
List[str]
|
Columns to use for training data. Defaults to [src_col, tgt_col]. |
None
|
src_col
|
str
|
Source column name. Falls back to config.src_col. |
None
|
tgt_col
|
str
|
Target column name. Falls back to config.tgt_col. |
None
|
model_type
|
str
|
SentencePiece model type. Falls back to config.sp_model_type. |
None
|
character_coverage
|
float
|
Character coverage. Falls back to config.sp_character_coverage. |
None
|
normalization_rule_name
|
str
|
Normalization rule. Falls back to config.sp_normalization_rule_name. |
None
|
pad_idx
|
int
|
Padding token index. Falls back to config.pad_idx. |
None
|
unk_idx
|
int
|
Unknown token index. Falls back to config.unk_idx. |
None
|
sos_idx
|
int
|
Start-of-sequence token index. Falls back to config.sos_idx. |
None
|
eos_idx
|
int
|
End-of-sequence token index. Falls back to config.eos_idx. |
None
|
pad_token
|
str
|
Padding token string. Falls back to config.pad_token. |
None
|
unk_token
|
str
|
Unknown token string. Falls back to config.unk_token. |
None
|
sos_token
|
str
|
Start-of-sequence token string. Falls back to config.sos_token. |
None
|
eos_token
|
str
|
End-of-sequence token string. Falls back to config.eos_token. |
None
|
user_defined_symbols
|
List[str]
|
Symbols to register as whole vocabulary pieces that are never split during tokenization. Useful for multilingual language tags (e.g., ['<2es>', '<2fr>']). |
None
|
config
|
Config
|
Configuration object. Falls back to get_default_config(). |
None
|
Side Effects
- Creates temporary file during training (automatically cleaned up).
- Writes {model_prefix}.model and {model_prefix}.vocab to disk.
- Prints confirmation message with output path.
Examples:
>>> train_sentencepiece([Path('train.tsv')], 'models/sp', vocab_size=16000)
SentencePiece model saved to models/sp.model
Source code in src/torchlingo/preprocessing/sentencepiece.py
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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | |
Training Options¶
Model Types¶
| Type | Description | Use Case |
|---|---|---|
bpe |
Byte Pair Encoding | General purpose, most common |
unigram |
Unigram LM | Better for some Asian languages |
char |
Character-level | When subwords aren't needed |
word |
Word-level | Pre-tokenized data |
# BPE (default, recommended)
train_sentencepiece(input_files, model_prefix, model_type="bpe")
# Unigram
train_sentencepiece(input_files, model_prefix, model_type="unigram")
Vocabulary Size¶
# Small vocab (faster, less coverage)
train_sentencepiece(input_files, model_prefix, vocab_size=4000)
# Medium vocab (balanced)
train_sentencepiece(input_files, model_prefix, vocab_size=16000)
# Large vocab (better coverage, more parameters)
train_sentencepiece(input_files, model_prefix, vocab_size=32000)
Rule of thumb:
- Small datasets: 4K-8K
- Medium datasets: 8K-16K
- Large datasets: 16K-32K
Character Coverage¶
# Full coverage (all characters in vocabulary)
train_sentencepiece(input_files, model_prefix, character_coverage=1.0)
# Allow rare characters to be UNK (useful for noisy data)
train_sentencepiece(input_files, model_prefix, character_coverage=0.9995)
For CJK languages (Chinese, Japanese, Korean), use 0.9995 since they have many characters.
Normalization¶
# NMT-NFKC (default, good for translation)
train_sentencepiece(
input_files, model_prefix,
normalization_rule_name="nmt_nfkc"
)
# Other options
train_sentencepiece(input_files, model_prefix, normalization_rule_name="nfc")
train_sentencepiece(input_files, model_prefix, normalization_rule_name="identity")
Examples¶
Complete Training Pipeline¶
from pathlib import Path
from torchlingo.preprocessing import (
load_data,
save_data,
train_sentencepiece,
)
# Prepare training text (combine src and tgt for shared vocab)
df = load_data("data/train.tsv")
train_text = df['src'].tolist() + df['tgt'].tolist()
# Save as text file for SentencePiece
text_path = Path("data/train_combined.txt")
with open(text_path, "w") as f:
f.write("\n".join(train_text))
# Train SentencePiece
train_sentencepiece(
input_files=[str(text_path)],
model_prefix="models/shared_sp",
vocab_size=16000,
model_type="bpe",
)
Separate Source/Target Models¶
# Source language model
with open("data/train_src.txt", "w") as f:
f.write("\n".join(df['src']))
train_sentencepiece(
["data/train_src.txt"],
"models/sp_en",
vocab_size=8000,
)
# Target language model
with open("data/train_tgt.txt", "w") as f:
f.write("\n".join(df['tgt']))
train_sentencepiece(
["data/train_tgt.txt"],
"models/sp_es",
vocab_size=8000,
)
Using with NMTDataset¶
from torchlingo.data_processing import NMTDataset, SentencePieceVocab
# Load trained models
src_sp = SentencePieceVocab("models/sp_en.model")
tgt_sp = SentencePieceVocab("models/sp_es.model")
# Use with dataset
dataset = NMTDataset(
"data/train.tsv",
src_vocab=src_sp,
tgt_vocab=tgt_sp,
)
Configuration via Config¶
from torchlingo.config import Config
config = Config(
use_sentencepiece=True,
sentencepiece_model_prefix="models/sp",
vocab_size=16000,
sp_model_type="bpe",
sp_character_coverage=1.0,
sp_normalization_rule_name="nmt_nfkc",
)
Best Practices¶
1. Train on Training Data Only¶
# ✅ Good: Train on training data
train_sentencepiece(["data/train.txt"], model_prefix)
# ❌ Bad: Including test data
train_sentencepiece(["data/train.txt", "data/test.txt"], model_prefix)
2. Combine Source and Target for Shared Vocab¶
For similar languages (e.g., Spanish-Portuguese), a shared vocabulary works well:
3. Use Appropriate Vocab Size¶
| Dataset Size | Recommended Vocab |
|---|---|
| < 100K sentences | 4K-8K |
| 100K-1M sentences | 8K-16K |
| > 1M sentences | 16K-32K |
4. Inspect the Model¶
import sentencepiece as spm
sp = spm.SentencePieceProcessor()
sp.load("models/sp.model")
# Check vocabulary
print(f"Vocab size: {sp.get_piece_size()}")
# See how text is tokenized
text = "The quick brown fox"
pieces = sp.encode_as_pieces(text)
print(f"Pieces: {pieces}")
ids = sp.encode_as_ids(text)
print(f"IDs: {ids}")
Troubleshooting¶
Model produces too many UNK tokens
Increase character_coverage: