ALBERT Persian POS Tagger
Part-of-speech tagger for Persian using the 17-tag
Universal Dependencies scheme. Fine-tuned from
shekar-ai/albert-base-v2-persian-zwnj-naab-mlm
on the Persian Universal Dependency Treebank (PerDT).
| |
|---|
| Task | Token classification (17 UD tags) |
| Parameters | 11.4 M |
| Base model | shekar-ai/albert-base-v2-persian-zwnj-naab-mlm |
| Training data | PerDT (UD_Persian-PerDT) |
| License | MIT |
Tags: ADJ, ADP, ADV, AUX, CCONJ, DET, INTJ, NOUN, NUM, PART, PRON, PROPN,
PUNCT, SCONJ, VERB, X, _.
Usage
Shekar
1from shekar import POSTagger
2
3tagger = POSTagger()
4
5for word, tag in tagger("کتابها دریچهای به جهان دانش هستند."):
6 print(f"{word}\t{tag}")
1کتابها NOUN
2دریچهای NOUN
3به ADP
4جهان NOUN
5دانش NOUN
6هستند VERB
7. PUNCT
Transformers
The model was trained on word-level input with labels on the first subtoken of each word and no
special tokens. Feeding raw text to the generic token-classification pipeline therefore produces
subword-level noise — tokenize word by word and read the prediction of each word's first subtoken:
1import torch
2from transformers import AutoModelForTokenClassification, AutoTokenizer
3
4repo = "shekar-ai/albert-base-v2-persian-pos-tagger"
5tokenizer = AutoTokenizer.from_pretrained(repo)
6model = AutoModelForTokenClassification.from_pretrained(repo).eval()
7
8def tag(words):
9 input_ids, word_ids = [], []
10 for index, word in enumerate(words):
11 subtokens = tokenizer.encode(word, add_special_tokens=False) or [tokenizer.unk_token_id]
12 input_ids.extend(subtokens)
13 word_ids.extend([index] * len(subtokens))
14
15 with torch.no_grad():
16 logits = model(input_ids=torch.tensor([input_ids])).logits[0]
17 predictions = logits.argmax(-1).tolist()
18
19 tags, previous = [], None
20 for word_index, prediction in zip(word_ids, predictions):
21 if word_index != previous:
22 tags.append((words[word_index], model.config.id2label[prediction]))
23 previous = word_index
24 return tags
25
26from shekar import WordTokenizer
27
28for word, pos in tag(list(WordTokenizer()("شاهنامه اثر فردوسی در توس سروده شد."))):
29 print(f"{word}\t{pos}")
1شاهنامه PROPN
2اثر NOUN
3فردوسی PROPN
4در ADP
5توس PROPN
6سروده VERB
7شد VERB
8. PUNCT
Training
Fine-tuned on the PerDT treebank: 26,196 training, 1,456 development, and 1,455 test sentences.
Each word is tokenized independently; the gold tag is assigned to its first subtoken and remaining
subtokens are masked out of the loss with -100. The checkpoint with the best macro-F1 was kept.
| Hyperparameter | Value |
|---|
| Epochs | 10 |
| Batch size | 8 |
| Learning rate | 2e-5 |
| LR scheduler | Linear |
| Weight decay | 0.01 |
| Optimizer | AdamW |
| Max sequence length | 512 |
Evaluation
Measured on the PerDT test split (1,455 sentences, 24,429 tokens):
| Metric | Value |
|---|
| Accuracy | 97.66 |
| Macro F1 | 90.82 |
Per-tag scores:
| Tag | Precision | Recall | F1 | Support |
|---|
| ADJ | 0.943 | 0.935 | 0.939 | 1,652 |
| ADP | 0.994 | 0.992 | 0.993 | 3,407 |
| ADV | 0.915 | 0.924 | 0.920 | 384 |
| AUX | 0.998 | 0.991 | 0.994 | 899 |
| CCONJ | 0.996 | 0.997 | 0.997 | 1,026 |
| DET | 0.972 | 0.982 | 0.977 | 491 |
| INTJ | 0.852 | 0.852 | 0.852 | 27 |
| NOUN | 0.974 | 0.971 | 0.972 | 8,219 |
| NUM | 0.970 | 0.980 | 0.975 | 293 |
| PART | 1.000 | 0.929 | 0.963 | 28 |
| PRON | 0.992 | 0.991 | 0.992 | 1,126 |
| PROPN | 0.873 | 0.907 | 0.890 | 1,111 |
| PUNCT | 0.999 | 0.999 | 0.999 | 2,141 |
| SCONJ | 0.990 | 0.979 | 0.985 | 632 |
| VERB | 0.996 | 0.998 | 0.997 | 2,696 |
| X | 0.000 | 0.000 | 0.000 | 1 |
_ | 1.000 | 0.993 | 0.997 | 296 |
Macro F1 is held down by the rare tags: INTJ (27 tokens) and X (1 token) contribute as much to
the average as NOUN (8,219 tokens). The main substantive weakness is the NOUN/PROPN boundary,
where Persian offers no capitalization cue.
Per-epoch validation during training
| Epoch | Training loss | Validation loss | Accuracy | Macro F1 |
|---|
| 1 | 0.1121 | 0.1027 | 0.9699 | 0.8784 |
| 2 | 0.0726 | 0.0817 | 0.9753 | 0.9025 |
| 3 | 0.0563 | 0.0806 | 0.9763 | 0.9026 |
| 4 | 0.0396 | 0.0888 | 0.9761 | 0.9067 |
| 5 | 0.0280 | 0.1055 | 0.9765 | 0.9060 |
| 6 | 0.0124 | 0.1230 | 0.9766 | 0.9082 |
| 7 | 0.0078 | 0.1385 | 0.9763 | 0.9069 |
| 8 | 0.0042 | 0.1544 | 0.9758 | 0.9040 |
| 9 | 0.0017 | 0.1630 | 0.9763 | 0.9027 |
| 10 | 0.0012 | 0.1687 | 0.9763 | 0.9059 |
Citation
1@article{Amirivojdan2025Shekar,
2 author = {Amirivojdan, Ahmad},
3 title = {{Shekar: A Python Toolkit for Persian Natural Language Processing}},
4 journal = {Journal of Open Source Software},
5 volume = {10},
6 number = {114},
7 pages = {9128},
8 year = {2025},
9 doi = {10.21105/joss.09128},
10 url = {https://joss.theoj.org/papers/10.21105/joss.09128}
11}