This repository compares Morphologically-aware Turkish tokenization (MFT) with standard BPE tokenization for sentence embedding models.
Investigate whether morphologically-aware tokenization improves Turkish sentence embeddings compared to standard BPE tokenization. We evaluate this by:
| Tokenizer | Type | Vocab Size | Description |
|---|---|---|---|
| MFT | Morphological | 32K | Root + suffix decomposition with vowel harmony |
| TabiBERT | BPE | 32K | Standard BPE trained on Turkish (pruned from 52K) |
All models use the same architecture with 131M parameters (131,420,928 params with 32K vocab).
| # | Model | HuggingFace ID | Tokenizer | Initialization | Parameters |
|---|---|---|---|---|---|
| 5 | mft-random-init | alibayram/mft-random-init | MFT | Random Xavier init | 131M |
| 6 | tabi-random-init | alibayram/tabi-random-init | TabiBERT | Random Xavier init | 131M |
Note: EmbeddingGemma (originally 262K vocab → 300M params) is resized to 32K vocab, resulting in identical parameter counts. The extra ~5M params come from Dense projection layers in the SentenceTransformer.
This experiment uses alibayram/cosmos-corpus-encoded, a pre-processed dataset optimized for distillation.
text: Original raw text.mft_input_ids: Pre-computed MFT tokenizer sequences.tabi_input_ids: Pre-computed TabiBERT tokenizer sequences.teacher_embedding_final: Knowledge distillation targets (Teacher embeddings).All samples are pre-filtered to ensure length compliance for both tokenizers, eliminating runtime tokenization overhead.
Traditional BPE tokenizers split Turkish words arbitrarily, losing morphological information:
BPE (Theoretical): "evlerinden" → ["evl", "er", "ind", "en"]
BPE (TabiBERT): "evlerinden" → ["ev", "lerinden"]
MFT Tokenizer: "evlerinden" → ["ev", "ler", "in", "den"]
(root) (plural) (poss.) (ablative)
# another example: "Yapay zeka ve makine öğrenmesi"
BPE (Theoretical) → ["yapay", "zeka", "ve", "makine", "öğrenmesi"]
BPE (TabiBERT) → ['Yap', 'ay', ' zek', 'a ve ', 'makine ', 'öğren', 'mesi']
MFT Tokenizer → ['<uppercase>', ' yapay', ' zeka', ' ve', ' makine', ' öğren', 'me', 'si']
MFT preserves morphological structure:
Evaluation uses the Turkish STS benchmark (figenfikri/stsb_tr):
# Evaluate a single model
python evaluate_sts_tr.py --model "alibayram/mft-downstream-task-embeddinggemma"
# Compare multiple models
python evaluate_sts_tr.py --model "model1" "model2" "model3"
Results are saved to sts_benchmark_results.json.
To generate a detailed Markdown report and visualizations from the results JSON:
python generate_sts_tables.py
This script will:
sts_benchmark_results.jsonsts_benchmark_chart_*.png) visualizing performance over checkpointsSTS_BENCHMARK_RESULTS.mdModels with MFT tokenizer do not include tokenizer.json because the tokenizer is morphology-based (not BPE). You must use the modified sentence_transformers library included in this repo:
from sentence_transformers import SentenceTransformer
import turkish_tokenizer as tt
# Initialize custom tokenizer
tokenizer = tt.TurkishTokenizer()
# Load model with custom tokenizer
model = SentenceTransformer(
"alibayram/mft-downstream-task-embeddinggemma",
custom_tokenizer=tokenizer
)
# Encode sentences
embeddings = model.encode(["Merhaba dünya", "Türkiye güzel bir ülke"])
tr-tokenizer-train/
├── turkish_tokenizer.py # MFT tokenizer implementation
├── turkish_decoder.py # Vowel harmony aware decoder
├── kokler.json # Turkish roots (~20K)
├── ekler.json # Turkish suffixes (72 groups)
├── bpe_tokenler.json # BPE fallback tokens
├── evaluate_sts_tr.py # STS benchmark evaluation
│
├── random_init.py # Random init (both tokenizers, seed=42)
│
└── sentence_transformers/ # Modified library with custom_tokenizer support
git clone <repository-url>
cd tr-tokenizer-train
pip install torch transformers sentence-transformers python-dotenv datasets scipy
# Create .env with HuggingFace token
echo "HF_TOKEN=your_token_here" > .env
python random_init.py
python evaluate_sts_tr.py -m "alibayram/mft-random-init" "alibayram/tabi-random-init" "alibayram/cosmosGPT2-random-init" "alibayram/newmindaiMursit-random-init"
💡 Insight: The morphologically-aware vocabulary design of MFT provides a strong inductive bias that improves semantic similarity even before any fine-tuning.
Results will be tracked after training in sts_benchmark_results.json. We compare:
random_init.py script creates the model once and pushes to both repos-only the tokenizer files differ:
alibayram/mft-random-init: No tokenizer files (uses custom TurkishTokenizer at inference)alibayram/tabi-random-init: Includes TabiBERT tokenizer filesalibayram/cosmosGPT2-random-init: Includes cosmosGPT2 tokenizer filesalibayram/newmindaiMursit-random-init: Includes newmindaiMursit tokenizer filesTabiBERT originally has ~52K tokens. We pruned to 32K to match MFT vocabulary size, ensuring fair comparison (same embedding matrix capacity).
The standard library doesn't support custom tokenizers. Our modifications:
custom_tokenizer parameter to SentenceTransformer.__init__Transformer.tokenize() to handle non-HuggingFace tokenizers37 commits
1 commits
Jupyter Notebook
51.8%
Python
46.4%
TeX
1.2%
This repository compares Morphologically-aware Turkish tokenization (MFT) with standard BPE tokenization for sentence embedding models.
Investigate whether morphologically-aware tokenization improves Turkish sentence embeddings compared to standard BPE tokenization. We evaluate this by:
| Tokenizer | Type | Vocab Size | Description |
|---|---|---|---|
| MFT | Morphological | 32K | Root + suffix decomposition with vowel harmony |
| TabiBERT | BPE | 32K | Standard BPE trained on Turkish (pruned from 52K) |
All models use the same architecture with 131M parameters (131,420,928 params with 32K vocab).
| # | Model | HuggingFace ID | Tokenizer | Initialization | Parameters |
|---|---|---|---|---|---|
| 5 | mft-random-init | alibayram/mft-random-init | MFT | Random Xavier init | 131M |
| 6 | tabi-random-init | alibayram/tabi-random-init | TabiBERT | Random Xavier init | 131M |
Note: EmbeddingGemma (originally 262K vocab → 300M params) is resized to 32K vocab, resulting in identical parameter counts. The extra ~5M params come from Dense projection layers in the SentenceTransformer.
This experiment uses alibayram/cosmos-corpus-encoded, a pre-processed dataset optimized for distillation.
text: Original raw text.mft_input_ids: Pre-computed MFT tokenizer sequences.tabi_input_ids: Pre-computed TabiBERT tokenizer sequences.teacher_embedding_final: Knowledge distillation targets (Teacher embeddings).All samples are pre-filtered to ensure length compliance for both tokenizers, eliminating runtime tokenization overhead.
Traditional BPE tokenizers split Turkish words arbitrarily, losing morphological information:
BPE (Theoretical): "evlerinden" → ["evl", "er", "ind", "en"]
BPE (TabiBERT): "evlerinden" → ["ev", "lerinden"]
MFT Tokenizer: "evlerinden" → ["ev", "ler", "in", "den"]
(root) (plural) (poss.) (ablative)
# another example: "Yapay zeka ve makine öğrenmesi"
BPE (Theoretical) → ["yapay", "zeka", "ve", "makine", "öğrenmesi"]
BPE (TabiBERT) → ['Yap', 'ay', ' zek', 'a ve ', 'makine ', 'öğren', 'mesi']
MFT Tokenizer → ['<uppercase>', ' yapay', ' zeka', ' ve', ' makine', ' öğren', 'me', 'si']
MFT preserves morphological structure:
Evaluation uses the Turkish STS benchmark (figenfikri/stsb_tr):
# Evaluate a single model
python evaluate_sts_tr.py --model "alibayram/mft-downstream-task-embeddinggemma"
# Compare multiple models
python evaluate_sts_tr.py --model "model1" "model2" "model3"
Results are saved to sts_benchmark_results.json.
To generate a detailed Markdown report and visualizations from the results JSON:
python generate_sts_tables.py
This script will:
sts_benchmark_results.jsonsts_benchmark_chart_*.png) visualizing performance over checkpointsSTS_BENCHMARK_RESULTS.mdModels with MFT tokenizer do not include tokenizer.json because the tokenizer is morphology-based (not BPE). You must use the modified sentence_transformers library included in this repo:
from sentence_transformers import SentenceTransformer
import turkish_tokenizer as tt
# Initialize custom tokenizer
tokenizer = tt.TurkishTokenizer()
# Load model with custom tokenizer
model = SentenceTransformer(
"alibayram/mft-downstream-task-embeddinggemma",
custom_tokenizer=tokenizer
)
# Encode sentences
embeddings = model.encode(["Merhaba dünya", "Türkiye güzel bir ülke"])
tr-tokenizer-train/
├── turkish_tokenizer.py # MFT tokenizer implementation
├── turkish_decoder.py # Vowel harmony aware decoder
├── kokler.json # Turkish roots (~20K)
├── ekler.json # Turkish suffixes (72 groups)
├── bpe_tokenler.json # BPE fallback tokens
├── evaluate_sts_tr.py # STS benchmark evaluation
│
├── random_init.py # Random init (both tokenizers, seed=42)
│
└── sentence_transformers/ # Modified library with custom_tokenizer support
git clone <repository-url>
cd tr-tokenizer-train
pip install torch transformers sentence-transformers python-dotenv datasets scipy
# Create .env with HuggingFace token
echo "HF_TOKEN=your_token_here" > .env
python random_init.py
python evaluate_sts_tr.py -m "alibayram/mft-random-init" "alibayram/tabi-random-init" "alibayram/cosmosGPT2-random-init" "alibayram/newmindaiMursit-random-init"
💡 Insight: The morphologically-aware vocabulary design of MFT provides a strong inductive bias that improves semantic similarity even before any fine-tuning.
Results will be tracked after training in sts_benchmark_results.json. We compare:
random_init.py script creates the model once and pushes to both repos-only the tokenizer files differ:
alibayram/mft-random-init: No tokenizer files (uses custom TurkishTokenizer at inference)alibayram/tabi-random-init: Includes TabiBERT tokenizer filesalibayram/cosmosGPT2-random-init: Includes cosmosGPT2 tokenizer filesalibayram/newmindaiMursit-random-init: Includes newmindaiMursit tokenizer filesTabiBERT originally has ~52K tokens. We pruned to 32K to match MFT vocabulary size, ensuring fair comparison (same embedding matrix capacity).
The standard library doesn't support custom tokenizers. Our modifications:
custom_tokenizer parameter to SentenceTransformer.__init__Transformer.tokenize() to handle non-HuggingFace tokenizers37 commits
1 commits
Jupyter Notebook
51.8%
Python
46.4%
TeX
1.2%