Darayut commited on
Commit
7c65031
·
verified ·
1 Parent(s): 8376691

Netra NMT release: ONNX model folder + PyTorch weights

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/metrics_benchmark.png filter=lfs diff=lfs merge=lfs -text
37
+ assets/speed_benchmark.png filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - en
5
+ - km
6
+ library_name: onnx
7
+ pipeline_tag: translation
8
+ tags:
9
+ - translation
10
+ - khmer
11
+ - english
12
+ - onnx
13
+ - netra-lab
14
+ datasets:
15
+ - Netra-Lab/bilingual-en-km
16
+ ---
17
+
18
+ # Netra NMT
19
+
20
+ A **77M-parameter** English↔Khmer translation model: one encoder-decoder transformer for both directions, trained from scratch on 220 million tokens of parallel text. It runs on ONNX Runtime with the `netra-nmt` package, on a CPU, without PyTorch.
21
+
22
+ **Code:** [github.com/netra-ai-lab/Netra-NMT](https://github.com/netra-ai-lab/Netra-NMT), with the inference package and the full training recipe.
23
+
24
+ ## Results
25
+
26
+ ALT test split (`mutiyama/alt`, 1,018 pairs), greedy decoding; spBLEU with the FLORES-200 tokenizer, higher is better.
27
+
28
+ | Model | Params | EN → KM | KM → EN |
29
+ |---|---:|---:|---:|
30
+ | NLLB-350M (EN-KM) | 350M | 18.89 | 0.26 |
31
+ | NLLB-200 distilled 600M | 600M | 9.24 | 31.28 |
32
+ | NLLB-200 distilled 1.3B | 1.3B | 16.62 | 35.15 |
33
+ | MADLAD-400 | 3B | 16.19 | 36.13 |
34
+ | Google Translate | — | 28.93 | 34.86 |
35
+ | **Netra NMT** | **77M** | **25.83** | **19.47** |
36
+
37
+ - **Where it wins:** English→Khmer, the best spBLEU after Google Translate and the best TER of all systems (60.47), and on CPU 65.6 ms per sentence greedy against 550.8 for NLLB-350M.
38
+ - **Where it loses:** Khmer→English, 15.7 spBLEU behind NLLB-200 1.3B.
39
+
40
+ <p align="center"><img src="https://huggingface.co/Netra-Lab/Netra-NMT/resolve/main/assets/metrics_benchmark.png" width="100%" alt="spBLEU, chrF++, TER, COMET and BERTScore on ALT"></p>
41
+
42
+ *spBLEU, chrF++, TER, COMET (wmt22-comet-da) and BERTScore F1 (xlm-roberta-base) on ALT, both directions.*
43
+
44
+ <p align="center"><img src="https://huggingface.co/Netra-Lab/Netra-NMT/resolve/main/assets/speed_benchmark.png" width="100%" alt="Speed against NLLB on CPU and GPU"></p>
45
+
46
+ *English→Khmer, median ms per sentence over 20 sentences, Intel i7-13700KF (16 threads) and RTX 3060, PyTorch.*
47
+
48
+ ## Architecture
49
+
50
+ <p align="center"><img src="https://huggingface.co/Netra-Lab/Netra-NMT/resolve/main/assets/model_architecture.png" width="70%" alt="Encoder-decoder architecture"></p>
51
+
52
+ - **Shape:** 12 encoder layers, 2 decoder layers (deep encoder, shallow decoder), d_model 512, 8 heads, FFN 2048, vocabulary 32K.
53
+ - **Components:** rotary position embeddings, RMSNorm (pre-norm), SwiGLU, one embedding table shared by the encoder, the decoder and the tied output head, a KV cache.
54
+ - **Input:** a target-language marker (`<2km>` or `<2en>`) then the source. English sources are NFC-normalised and lowercased; Khmer is word-segmented with khmercut. The package does this for you.
55
+
56
+ ## How it was made
57
+
58
+ 1. **Data.** About 2.4M unique pairs from four sources (synthetic and ParaCrawl), deduplicated, length-filtered, then used in both directions: 4.2M examples.
59
+ 2. **Tokenizer.** A 32K SentencePiece unigram model shared by both languages, trained on Khmer segmented with khmercut.
60
+ 3. **Training.** From scratch, with label smoothing and a warm-up + cosine learning-rate schedule (settings in `training/netra_nmt_train/scripts/recipe/09_train_student.py`); the checkpoint with the best validation chrF is released.
61
+ 4. **Export.** The encoder and a one-step decoder with a KV cache as ONNX graphs, weights stored as fp16. The exported folder generates the same tokens as the PyTorch model on the ALT test set (greedy and beam-5, both directions).
62
+
63
+ ## Usage
64
+
65
+ ```bash
66
+ pip install "netra-nmt[cpu]" # or [gpu]
67
+ ```
68
+
69
+ ```python
70
+ from netra_nmt import translate
71
+
72
+ translate("Hello, how are you?") # English -> Khmer
73
+ translate("ខ្ញុំស្រលាញ់ប្រទេសកម្ពុជា។", direction="km2en") # -> "I love Cambodia."
74
+ ```
75
+
76
+ ```bash
77
+ netra-nmt --text "Hello, how are you?" --mode beam
78
+ netra-nmt serve # web app + REST API (extra: server)
79
+ ```
80
+
81
+ The package downloads `model/` from this repo once, at the commit it was tested with.
82
+
83
+ ## Files
84
+
85
+ | File | Contents |
86
+ |---|---|
87
+ | `model/netra-model.json` | settings: graphs, decoder shape, special ids, language markers, sha256 of every file |
88
+ | `model/encoder.onnx` | tokens → cross-attention keys/values for every decoder layer (136 MB) |
89
+ | `model/decoder_step.onnx` | one decoding step with the self-attention KV cache (52 MB) |
90
+ | `model/spm_32k.model` | the SentencePiece tokenizer |
91
+ | `pytorch/model.safetensors` | fp16 weights for fine-tuning (`lm_head` tied to the embeddings, not stored) |
92
+ | `pytorch/config.json`, `pytorch/spm_32k.model` | architecture and tokenizer for the PyTorch model |
93
+ | `assets/` | the figures on this card |
94
+
95
+ To fine-tune from `pytorch/`: `bash training/finetune.sh my_pairs.tsv` in the GitHub repo.
96
+
97
+ ## License and attribution
98
+
99
+ - **Weights:** MIT, trained from scratch (no pretrained weights).
100
+ - **Training data:** see the [dataset card](https://huggingface.co/datasets/Netra-Lab/bilingual-en-km) and its sources; check their terms before commercial use.
101
+ - **Evaluation data:** ALT (NICT), CC BY 4.0.
assets/metrics_benchmark.png ADDED

Git LFS Details

  • SHA256: 0993cdbc31ec3c591bdc9b3e83ce08b17af65d5d9c1cfa14499586f31a5450d3
  • Pointer size: 131 Bytes
  • Size of remote file: 441 kB
assets/model_architecture.png ADDED
assets/speed_benchmark.png ADDED

Git LFS Details

  • SHA256: 3edae17cc16db983a5081ab29cedb19a4bdf2a83a053f56612e0179d266ea071
  • Pointer size: 131 Bytes
  • Size of remote file: 107 kB
model/decoder_step.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:23ca5422992f1cc388a1b58109bf1b68cc6352b35ef2e2f7c60c5c9cd5538a2d
3
+ size 51848792
model/encoder.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7e04885e0c170a2f945de8482c3b83da67fe44716a698875c151caf339b37eae
3
+ size 136209085
model/netra-model.json ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "format": "netra-bundle",
3
+ "format_version": 1,
4
+ "name": "netra-nmt",
5
+ "version": "1.0.0",
6
+ "task": "translation",
7
+ "languages": [
8
+ "en",
9
+ "km"
10
+ ],
11
+ "graphs": {
12
+ "encoder": "encoder.onnx",
13
+ "decoder_step": "decoder_step.onnx"
14
+ },
15
+ "components": {
16
+ "preprocess": {
17
+ "type": "nmt-source",
18
+ "lang_markers": {
19
+ "en": "<2en>",
20
+ "km": "<2km>"
21
+ },
22
+ "max_len": 256,
23
+ "en_source": "nfc-collapse-whitespace-lowercase",
24
+ "km_source": "khmercut-segment"
25
+ },
26
+ "decoder": {
27
+ "type": "kv-cache",
28
+ "layers": 2,
29
+ "heads": 8,
30
+ "head_dim": 64,
31
+ "vocab_size": 32000,
32
+ "pad_id": 0,
33
+ "bos_id": 2,
34
+ "eos_id": 3
35
+ },
36
+ "tokenizer": {
37
+ "type": "sentencepiece",
38
+ "model": "spm_32k.model"
39
+ },
40
+ "postprocess": [
41
+ {
42
+ "type": "km-desegment"
43
+ }
44
+ ]
45
+ },
46
+ "metadata": {
47
+ "source_checkpoint": "export_rope",
48
+ "architecture": "encoder-decoder, 12 enc / 2 dec layers, d_model 512, RoPE, RMSNorm, SwiGLU, tied embeddings",
49
+ "license": "MIT"
50
+ },
51
+ "files": {
52
+ "decoder_step.onnx": "23ca5422992f1cc388a1b58109bf1b68cc6352b35ef2e2f7c60c5c9cd5538a2d",
53
+ "encoder.onnx": "7e04885e0c170a2f945de8482c3b83da67fe44716a698875c151caf339b37eae",
54
+ "spm_32k.model": "213884dadb76370b50098e0b5cfeacad3d9813aa415657c7abdbb3bddde61ab7"
55
+ }
56
+ }
model/spm_32k.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:213884dadb76370b50098e0b5cfeacad3d9813aa415657c7abdbb3bddde61ab7
3
+ size 897214
pytorch/config.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "d_model": 512,
3
+ "enc_layers": 12,
4
+ "dec_layers": 2,
5
+ "n_heads": 8,
6
+ "ffn_dim": 2048,
7
+ "max_len": 256,
8
+ "pad_id": 0,
9
+ "bos_id": 2,
10
+ "eos_id": 3,
11
+ "vocab_size": 32000,
12
+ "pos_encoding": "rope",
13
+ "norm": "rmsnorm",
14
+ "tie_all_embeddings": true,
15
+ "lang_markers": {
16
+ "en": "<2en>",
17
+ "km": "<2km>"
18
+ },
19
+ "dtype": "float16"
20
+ }
pytorch/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e202b349cd57be2886e373bdc83033299a3332cbc1d6c31318cb5114fa4ba7d0
3
+ size 154448952
pytorch/spm_32k.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:213884dadb76370b50098e0b5cfeacad3d9813aa415657c7abdbb3bddde61ab7
3
+ size 897214