File size: 3,052 Bytes
d5a8846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354a8b7
d5a8846
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d3dd4d6
d5a8846
 
 
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
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
---
language:
- ur
license: mit
tags:
- urdu
- nastaliq
- bert
- character-level
- masked-language-modeling
- neobert
- low-resource
- abjad
datasets:
- statmt/cc100
metrics:
- perplexity
model-index:
- name: NastaliqBERT
  results:
  - task:
      type: fill-mask
    dataset:
      name: CC-100 Urdu
      type: statmt/cc100
    metrics:
    - type: perplexity
      value: 1.67
---

# NastaliqBERT

**Character-level NeoBERT encoder pretrained on unvocalized Urdu Nastaliq text.**

NastaliqBERT is the **first character-level pretrained encoder for Urdu** and the **first NeoBERT-architecture model for any South Asian language**. It achieves a masked language modelling perplexity of **1.67** on CC-100 Urdu.

## Model description

NastaliqBERT uses the NeoBERT architecture with RoPE positional embeddings, SwiGLU activation, and Pre-RMSNorm. It operates on a 116-token character vocabulary covering all Urdu Nastaliq letters (including final forms), ASCII, and special tokens — no subword tokenization.

| | |
|---|---|
| Architecture | NeoBERT (RoPE + SwiGLU + Pre-RMSNorm) |
| Vocabulary | 116 characters |
| Hidden size | 512 |
| Layers | 6 |
| Attention heads | 8 |
| Parameters | ~19.4M |
| Pretraining data | CC-100 Urdu (~8GB) |
| Perplexity | **1.67** |

## Why character-level for Urdu?

Urdu is written in Nastaliq a right-to-left abjad where short vowels are not written. Subword tokenizers fragment Nastaliq ligatures at arbitrary boundaries. Character-level modelling preserves:
- The aspiration digraph ھ (do-chashmi-he) as a distinct unit
- Final letter forms (ے vs ی, ں vs ن)
- Correct morphological boundaries

## Usage

```python
import torch, json, sys
sys.path.insert(0, 'src')
from model import BertCharUr, BertCharUrConfig
from tokenizer import CharTokenizer

tok = CharTokenizer()
with open('config.json') as f:
    cfg = BertCharUrConfig.from_dict(json.load(f))

model = BertCharUr(cfg)
state = torch.load('model.pt', map_location='cpu', weights_only=True)
model.load_state_dict(state['model_state'])
model.eval()

ids = tok.encode("مشاہیر", max_length=64)
input_ids = torch.tensor([ids])
mask = torch.ones_like(input_ids)

with torch.no_grad():
    hidden = model.get_encoder_output(input_ids, mask)
# hidden: (1, seq_len, 512)
```

## Downstream use

NastaliqBERT is used as the encoder in [UrduPhon](https://huggingface.co/mahwizzzz/UrduPhon), a G2P model for Urdu TTS that uses the Phonological Feature Decoder (PFD).

## Training

Pretrained for 100,000 steps on CC-100 Urdu (`statmt/cc100`, `name="ur"`) using:
- MLM with 15% mask rate (no NSP)
- AdamW optimizer, lr=1e-4, cosine decay
- Effective batch size 64 (32 × 2 grad accumulation)
- Mixed precision (bf16)
- FlashAttention-2 (via `F.scaled_dot_product_attention`)

## Citation

```bibtex
@misc{nastaliqbert2025,
  title        = {NastaliqBERT: A Character-Level NeoBERT Encoder for Urdu's Defective Abjad Script},
  author       = {Mahwiz},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/mahwizzzz/NastaliqBERT}},
}
```