Model card: run it without a server, in Python or JavaScript
#1
by byamasupatrick - opened
- ARCHITECTURE.md +1 -1
- README.md +113 -51
- millid.py +1 -1
ARCHITECTURE.md
CHANGED
|
@@ -204,7 +204,7 @@ flowchart LR
|
|
| 204 |
is (α = 1), where the largest languages fill every batch, and uniform (α = 0), where a
|
| 205 |
100-passage language is seen until memorised. XLM-R and mT5 sample their languages the same way.
|
| 206 |
- **How long.** A quarter of passages are cut to a 20 to 80 character snippet, on word boundaries
|
| 207 |
-
where the script has them: short text is the hard case, and what a document
|
| 208 |
headers, captions and table cells.
|
| 209 |
- **Why macro F1 chooses.** It weighs every language equally, the score a thousand-language model
|
| 210 |
should be judged on. Top-1 accuracy, which the largest languages dominate, is reported beside it.
|
|
|
|
| 204 |
is (α = 1), where the largest languages fill every batch, and uniform (α = 0), where a
|
| 205 |
100-passage language is seen until memorised. XLM-R and mT5 sample their languages the same way.
|
| 206 |
- **How long.** A quarter of passages are cut to a 20 to 80 character snippet, on word boundaries
|
| 207 |
+
where the script has them: short text is the hard case, and what a document holds in its
|
| 208 |
headers, captions and table cells.
|
| 209 |
- **Why macro F1 chooses.** It weighs every language equally, the score a thousand-language model
|
| 210 |
should be judged on. Top-1 accuracy, which the largest languages dominate, is reported beside it.
|
README.md
CHANGED
|
@@ -1,44 +1,105 @@
|
|
| 1 |
---
|
|
|
|
| 2 |
library_name: pytorch
|
| 3 |
pipeline_tag: text-classification
|
| 4 |
tags:
|
| 5 |
- language-identification
|
|
|
|
|
|
|
| 6 |
datasets:
|
| 7 |
- baobabtech/millid-dataset
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
# MillID tiny: MultiLingual Language IDentifier
|
| 11 |
|
| 12 |
-
A byte-level, encoder-only transformer that names the language of a passage: **
|
| 13 |
-
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
|
| 16 |
```python
|
| 17 |
-
from millid import MillID
|
| 18 |
|
| 19 |
model = MillID.from_pretrained("baobabtech/millid-tiny-v1.5")
|
| 20 |
-
model.predict(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
```
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
## Architecture
|
| 24 |
|
| 25 |
-
UTF-8 bytes (after Unicode NFKC), each embedded as byte + Unicode script + byte-in-character + hashed character
|
| 26 |
-
2-, 3- and 4-grams (4,096 buckets) -> depthwise convolution stem (kernel 5) -> strided
|
| 27 |
-
convolution, 1 bytes per token -> 3 pre-norm blocks (RMSNorm, attention with RoPE,
|
| 28 |
-
3 heads, SwiGLU; d=192) -> masked mean pooling -> language head, each language's vector the sum of
|
| 29 |
-
its own, its language's and its script's. Up to 256 bytes per passage. See `ARCHITECTURE.md`.
|
| 30 |
|
| 31 |
## Evaluation against GlotLID and fastText
|
| 32 |
|
| 33 |
-
`validation` chose the checkpoint; `test` is split by document from training; `udhr` is the Universal Declaration
|
| 34 |
-
of Human Rights, labelled by its translators, over the languages MillID knows, and `udhr-all` over all of them.
|
| 35 |
-
`glotlid` is [GlotLID](https://huggingface.co/cis-lmu/glotlid) as it is; `glotlid@millid` is GlotLID restricted to
|
| 36 |
-
MillID's labels, the like-for-like comparison. GlotLID's own labels came from training on data that includes UDHR
|
| 37 |
-
and labelled FinePDFs and FineWeb-2, so its scores on `udhr` and on those sources are optimistic. `fasttext` is
|
| 38 |
-
Meta's [fastText language identifier](https://huggingface.co/facebook/fasttext-language-identification) (NLLB,
|
| 39 |
-
218 labels), its answers mapped onto MillID's spelling (Simplified and Traditional Han as `Hani`, `pes`/`prs` as
|
| 40 |
-
`fas`, `est` as `ekk`). It cannot answer most of the 1,600 languages here, so `test-common` and `udhr-common`
|
| 41 |
-
score every model on the passages whose language all of them know: the head-to-head on equal terms.
|
| 42 |
|
| 43 |
| Set | Model | Top-1 | Top-3 | Top-5 | Macro P | Macro R | Macro F1 | Median F1 | Languages |
|
| 44 |
|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -87,8 +148,7 @@ Top-1 accuracy by passage length:
|
|
| 87 |
|
| 88 |
### Leaderboard: test
|
| 89 |
|
| 90 |
-
MillID's F1 against the others', language by language: against GlotLID restricted to MillID's labels, MillID is better on **103** languages, worse on **869** and within 0.01 on 649; against fastText restricted to MillID's labels, MillID is better on **1616** languages, worse on **0** and within 0.01 on 5. The full table, with precision and recall, is
|
| 91 |
-
`reports/test/leaderboard.csv`.
|
| 92 |
|
| 93 |
The 20 languages with the most passages:
|
| 94 |
|
|
@@ -96,15 +156,15 @@ The 20 languages with the most passages:
|
|
| 96 |
|---|---|---|---|---|---|---|---|
|
| 97 |
| `fra_Latn` | French | 1652 | 0.929 | 0.928 | 0.928 | 0.808 | 0.808 |
|
| 98 |
| `eng_Latn` | English | 1444 | 0.917 | 0.858 | 0.859 | 0.653 | 0.648 |
|
| 99 |
-
| `spa_Latn` | Spanish | 1136 | 0.
|
| 100 |
| `tam_Taml` | Tamil | 754 | 0.997 | 0.993 | 0.993 | 0.965 | 0.965 |
|
| 101 |
| `arb_Arab` | Arabic (Modern Standard) | 745 | 0.814 | 0.785 | 0.785 | 0.513 | 0.512 |
|
| 102 |
| `por_Latn` | Portuguese | 657 | 0.947 | 0.947 | 0.949 | 0.756 | 0.755 |
|
| 103 |
| `kan_Knda` | Kannada | 601 | 0.969 | 0.993 | 0.993 | 0.922 | 0.922 |
|
| 104 |
| `zul_Latn` | Zulu | 594 | 0.846 | 0.896 | 0.896 | 0.539 | 0.539 |
|
| 105 |
-
| `swh_Latn` | Swahili | 592 | 0.848 | 0.
|
| 106 |
| `mar_Deva` | Marathi | 589 | 0.965 | 0.989 | 0.990 | 0.926 | 0.926 |
|
| 107 |
-
| `tso_Latn` | Tsonga | 581 | 0.965 | 0.956 | 0.956 | 0.
|
| 108 |
| `hun_Latn` | Hungarian | 576 | 0.987 | 0.999 | 0.999 | 0.232 | 0.232 |
|
| 109 |
| `afr_Latn` | Afrikaans | 569 | 0.967 | 0.985 | 0.985 | 0.861 | 0.860 |
|
| 110 |
| `tel_Telu` | Telugu | 555 | 0.991 | 0.994 | 0.994 | 0.951 | 0.951 |
|
|
@@ -112,7 +172,7 @@ The 20 languages with the most passages:
|
|
| 112 |
| `nbl_Latn` | South Ndebele | 528 | 0.903 | 0.948 | 0.949 | 0.000 | 0.000 |
|
| 113 |
| `ory_Orya` | Odia (individual language) | 511 | 0.988 | 0.991 | 0.994 | 0.976 | 0.976 |
|
| 114 |
| `sot_Latn` | Southern Sotho | 491 | 0.966 | 0.977 | 0.978 | 0.660 | 0.660 |
|
| 115 |
-
| `nso_Latn` | Northern Sotho | 479 | 0.956 | 0.
|
| 116 |
| `kua_Latn` | Kuanyama | 476 | 0.962 | 0.986 | 0.986 | 0.000 | 0.000 |
|
| 117 |
|
| 118 |
Where MillID gains most over GlotLID:
|
|
@@ -121,7 +181,7 @@ Where MillID gains most over GlotLID:
|
|
| 121 |
|---|---|---|---|---|---|---|---|
|
| 122 |
| `lbj_Tibt` | Ladakhi | 66 | 0.943 | 0.000 | 0.000 | 0.000 | 0.000 |
|
| 123 |
| `ain_Latn` | Ainu | 1 | 0.667 | 0.000 | 0.000 | 0.000 | 0.000 |
|
| 124 |
-
| `ajp_Arab` | South Levantine Arabic | 28 | 0.
|
| 125 |
| `und_Laoo` | und | 20 | 0.923 | 0.621 | 0.621 | 0.000 | 0.000 |
|
| 126 |
| `und_Thaa` | und | 29 | 0.881 | 0.651 | 0.651 | 0.000 | 0.000 |
|
| 127 |
| `sgh_Cyrl` | Shughni | 9 | 0.857 | 0.667 | 0.667 | 0.000 | 0.000 |
|
|
@@ -140,7 +200,7 @@ Where MillID loses most to GlotLID:
|
|
| 140 |
| Label | Language | Passages | MillID F1 | GlotLID F1 | GlotLID F1, restricted | fastText F1 | fastText F1, restricted |
|
| 141 |
|---|---|---|---|---|---|---|---|
|
| 142 |
| `mus_Latn` | Muscogee | 2 | 0.333 | 1.000 | 1.000 | 0.000 | 0.000 |
|
| 143 |
-
| `ttj_Latn` | Tooro | 28 | 0.485 | 0.
|
| 144 |
| `mbd_Latn` | Dibabawon Manobo | 14 | 0.596 | 1.000 | 1.000 | 0.000 | 0.000 |
|
| 145 |
| `knc_Arab` | Central Kanuri | 68 | 0.462 | 0.823 | 0.825 | 0.007 | 0.007 |
|
| 146 |
| `biu_Latn` | Biete | 7 | 0.667 | 1.000 | 1.000 | 0.000 | 0.000 |
|
|
@@ -157,15 +217,14 @@ Where MillID loses most to GlotLID:
|
|
| 157 |
|
| 158 |
### Leaderboard: udhr
|
| 159 |
|
| 160 |
-
MillID's F1 against the others', language by language: against GlotLID restricted to MillID's labels, MillID is better on **52** languages, worse on **105** and within 0.01 on 201; against fastText restricted to MillID's labels, MillID is better on **303** languages, worse on **15** and within 0.01 on 40. The full table, with precision and recall, is
|
| 161 |
-
`reports/udhr/leaderboard.csv`.
|
| 162 |
|
| 163 |
The 20 languages with the most passages:
|
| 164 |
|
| 165 |
| Label | Language | Passages | MillID F1 | GlotLID F1 | GlotLID F1, restricted | fastText F1 | fastText F1, restricted |
|
| 166 |
|---|---|---|---|---|---|---|---|
|
| 167 |
-
| `roh_Latn` | Romansh | 399 | 0.994 | 0.999 | 0.999 | 0.
|
| 168 |
-
| `oci_Latn` | Occitan | 398 | 0.277 | 0.376 | 0.376 | 0.
|
| 169 |
| `cmn_Hani` | Chinese (Mandarin) | 319 | 0.892 | 0.868 | 0.868 | 0.468 | 0.468 |
|
| 170 |
| `krl_Latn` | Karelian | 183 | 0.000 | 0.011 | 0.011 | 0.000 | 0.000 |
|
| 171 |
| `qug_Latn` | Chimborazo Highland Quichua | 182 | 0.011 | 0.000 | 0.000 | 0.000 | 0.000 |
|
|
@@ -175,29 +234,29 @@ The 20 languages with the most passages:
|
|
| 175 |
| `auc_Latn` | Waorani | 154 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
|
| 176 |
| `kwi_Latn` | Awa-Cuaiquer | 145 | 0.880 | 0.877 | 0.877 | 0.000 | 0.000 |
|
| 177 |
| `jpn_Jpan` | Japanese | 140 | 1.000 | 1.000 | 1.000 | 0.944 | 0.944 |
|
| 178 |
-
| `snn_Latn` | Siona | 136 | 0.
|
| 179 |
| `ktu_Latn` | Kituba (Democratic Republic of Congo) | 118 | 0.765 | 0.680 | 0.680 | 0.000 | 0.000 |
|
| 180 |
-
| `lat_Latn` | Latin | 118 | 0.996 | 0.
|
| 181 |
-
| `hat_Latn` | Haitian Creole | 117 | 0.
|
| 182 |
| `nya_Latn` | Nyanja | 116 | 0.991 | 1.000 | 1.000 | 0.806 | 0.806 |
|
| 183 |
| `kmb_Latn` | Kimbundu | 116 | 0.970 | 1.000 | 1.000 | 0.877 | 0.877 |
|
| 184 |
| `rmn_Latn` | Balkan Romani | 116 | 0.678 | 0.857 | 0.857 | 0.000 | 0.000 |
|
| 185 |
| `twi_Latn` | Twi | 116 | 0.983 | 0.996 | 0.996 | 0.399 | 0.396 |
|
| 186 |
-
| `chr_Cher` | Cherokee | 115 | 0.
|
| 187 |
|
| 188 |
Where MillID gains most over GlotLID:
|
| 189 |
|
| 190 |
| Label | Language | Passages | MillID F1 | GlotLID F1 | GlotLID F1, restricted | fastText F1 | fastText F1, restricted |
|
| 191 |
|---|---|---|---|---|---|---|---|
|
| 192 |
-
| `mic_Latn` | Mi'kmaw | 59 | 0.
|
| 193 |
| `tet_Latn` | Tetum | 58 | 0.638 | 0.167 | 0.167 | 0.000 | 0.000 |
|
| 194 |
| `fuf_Latn` | Pular | 58 | 0.906 | 0.483 | 0.483 | 0.000 | 0.000 |
|
| 195 |
-
| `sag_Latn` | Sango | 59 | 0.
|
| 196 |
| `skr_Arab` | Saraiki | 63 | 0.867 | 0.500 | 0.500 | 0.000 | 0.000 |
|
| 197 |
| `qvh_Latn` | Huamalíes-Dos de Mayo Huánuco Quechua | 58 | 0.468 | 0.154 | 0.154 | 0.000 | 0.000 |
|
| 198 |
| `zgh_Tfng` | Standard Moroccan Tamazight | 60 | 0.750 | 0.462 | 0.462 | 0.000 | 0.000 |
|
| 199 |
| `lld_Latn` | Ladin | 59 | 0.909 | 0.731 | 0.731 | 0.000 | 0.000 |
|
| 200 |
-
| `tah_Latn` | Tahitian | 57 | 0.973 | 0.
|
| 201 |
| `yue_Hani` | Cantonese | 49 | 0.734 | 0.580 | 0.580 | 0.111 | 0.111 |
|
| 202 |
| `ote_Latn` | Mezquital Otomi | 59 | 0.154 | 0.000 | 0.000 | 0.000 | 0.000 |
|
| 203 |
| `pnb_Arab` | Western Panjabi | 61 | 0.882 | 0.739 | 0.739 | 0.000 | 0.000 |
|
|
@@ -215,10 +274,10 @@ Where MillID loses most to GlotLID:
|
|
| 215 |
| `tbz_Latn` | Ditammari | 60 | 0.000 | 0.378 | 0.378 | 0.000 | 0.000 |
|
| 216 |
| `cbu_Latn` | Candoshi-Shapra | 57 | 0.500 | 0.882 | 0.874 | 0.000 | 0.000 |
|
| 217 |
| `idu_Latn` | Idoma | 51 | 0.603 | 0.879 | 0.938 | 0.000 | 0.000 |
|
| 218 |
-
| `ell_Grek` | Greek | 115 | 0.
|
| 219 |
| `qvc_Latn` | Cajamarca Quechua | 58 | 0.648 | 0.906 | 0.906 | 0.000 | 0.000 |
|
| 220 |
| `cpu_Latn` | Pichis Ashéninka | 60 | 0.729 | 0.974 | 0.974 | 0.000 | 0.000 |
|
| 221 |
-
| `qvn_Latn` | North Junín Quechua | 57 | 0.219 | 0.
|
| 222 |
| `hin_Deva` | Hindi | 59 | 0.723 | 0.957 | 0.957 | 0.975 | 0.975 |
|
| 223 |
| `hrv_Latn` | Croatian | 58 | 0.500 | 0.727 | 0.727 | 0.474 | 0.474 |
|
| 224 |
| `kbp_Latn` | Kabiyè | 59 | 0.781 | 1.000 | 1.000 | 0.389 | 0.389 |
|
|
@@ -227,8 +286,7 @@ Where MillID loses most to GlotLID:
|
|
| 227 |
|
| 228 |
### Leaderboard: test-common
|
| 229 |
|
| 230 |
-
MillID's F1 against the others', language by language: against GlotLID restricted to MillID's labels, MillID is better on **6** languages, worse on **154** and within 0.01 on 53; against fastText restricted to MillID's labels, MillID is better on **85** languages, worse on **51** and within 0.01 on 77. The full table, with precision and recall, is
|
| 231 |
-
`reports/test-common/leaderboard.csv`.
|
| 232 |
|
| 233 |
The 20 languages with the most passages:
|
| 234 |
|
|
@@ -266,12 +324,12 @@ Where MillID gains most over GlotLID:
|
|
| 266 |
| `fuv_Latn` | Nigerian Fulfulde | 164 | 0.907 | 0.877 | 0.892 | 0.859 | 0.859 |
|
| 267 |
| `knc_Latn` | Central Kanuri | 293 | 0.967 | 0.952 | 0.952 | 0.981 | 0.981 |
|
| 268 |
| `quy_Latn` | Ayacucho Quechua | 271 | 0.940 | 0.925 | 0.933 | 0.979 | 0.979 |
|
| 269 |
-
| `kam_Latn` | Kamba | 272 | 0.980 | 0.972 | 0.974 | 0.
|
| 270 |
-
| `bjn_Arab` | Banjar | 116 | 0.
|
| 271 |
| `por_Latn` | Portuguese | 657 | 0.959 | 0.954 | 0.956 | 0.950 | 0.949 |
|
| 272 |
| `mlt_Latn` | Maltese | 291 | 0.995 | 0.993 | 0.993 | 0.961 | 0.961 |
|
| 273 |
-
| `san_Deva` | Sanskrit | 239 | 0.990 | 0.989 | 0.989 | 0.970 | 0.970 |
|
| 274 |
| `hye_Armn` | Armenian | 178 | 1.000 | 1.000 | 1.000 | 0.977 | 0.977 |
|
|
|
|
| 275 |
| `guj_Gujr` | Gujarati | 354 | 1.000 | 1.000 | 1.000 | 0.984 | 0.984 |
|
| 276 |
| `mal_Mlym` | Malayalam | 338 | 1.000 | 1.000 | 1.000 | 0.994 | 0.994 |
|
| 277 |
|
|
@@ -282,7 +340,7 @@ Where MillID loses most to GlotLID:
|
|
| 282 |
| `knc_Arab` | Central Kanuri | 68 | 0.522 | 0.857 | 0.860 | 0.029 | 0.029 |
|
| 283 |
| `hrv_Latn` | Croatian | 168 | 0.659 | 0.994 | 0.994 | 0.856 | 0.856 |
|
| 284 |
| `bos_Latn` | Bosnian | 198 | 0.685 | 1.000 | 1.000 | 0.897 | 0.897 |
|
| 285 |
-
| `tzm_Tfng` | Central Atlas Tamazight | 157 | 0.697 | 0.
|
| 286 |
| `zsm_Latn` | Standard Malay | 244 | 0.789 | 0.998 | 0.998 | 0.908 | 0.908 |
|
| 287 |
| `taq_Tfng` | Tamasheq | 104 | 0.654 | 0.805 | 0.805 | 0.000 | 0.000 |
|
| 288 |
| `ind_Latn` | Indonesian | 335 | 0.842 | 0.991 | 0.991 | 0.887 | 0.887 |
|
|
@@ -292,13 +350,17 @@ Where MillID loses most to GlotLID:
|
|
| 292 |
| `kin_Latn` | Kinyarwanda | 210 | 0.849 | 0.981 | 0.981 | 0.854 | 0.854 |
|
| 293 |
| `mag_Deva` | Magahi | 97 | 0.890 | 1.000 | 1.000 | 0.772 | 0.772 |
|
| 294 |
| `lim_Latn` | Limburgish | 196 | 0.896 | 1.000 | 1.000 | 0.956 | 0.956 |
|
| 295 |
-
| `run_Latn` | Rundi | 291 | 0.883 | 0.985 | 0.985 | 0.
|
| 296 |
| `taq_Latn` | Tamasheq | 106 | 0.902 | 1.000 | 1.000 | 0.838 | 0.838 |
|
| 297 |
|
| 298 |
Per-language precision, recall (sensitivity), F1 and specificity for every model are in `reports/<set>/`.
|
| 299 |
|
| 300 |
## Training
|
| 301 |
|
| 302 |
-
1,943,957 passages
|
| 303 |
-
|
| 304 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
license: apache-2.0
|
| 3 |
library_name: pytorch
|
| 4 |
pipeline_tag: text-classification
|
| 5 |
tags:
|
| 6 |
- language-identification
|
| 7 |
+
- onnx
|
| 8 |
+
- byte-level
|
| 9 |
datasets:
|
| 10 |
- baobabtech/millid-dataset
|
| 11 |
+
metrics:
|
| 12 |
+
- f1
|
| 13 |
+
- accuracy
|
| 14 |
+
model-index:
|
| 15 |
+
- name: millid-tiny-v1.5
|
| 16 |
+
results:
|
| 17 |
+
- task:
|
| 18 |
+
type: text-classification
|
| 19 |
+
name: Language identification
|
| 20 |
+
dataset:
|
| 21 |
+
name: MillID test split (the full build)
|
| 22 |
+
type: baobabtech/millid-dataset
|
| 23 |
+
split: test
|
| 24 |
+
metrics:
|
| 25 |
+
- type: f1
|
| 26 |
+
name: Macro F1
|
| 27 |
+
value: 0.9554
|
| 28 |
+
- type: accuracy
|
| 29 |
+
name: Top-1 accuracy
|
| 30 |
+
value: 0.9587
|
| 31 |
+
- task:
|
| 32 |
+
type: text-classification
|
| 33 |
+
name: Language identification
|
| 34 |
+
dataset:
|
| 35 |
+
name: UDHR-LID, the languages MillID knows
|
| 36 |
+
type: baobabtech/millid-dataset
|
| 37 |
+
config: udhr
|
| 38 |
+
split: test
|
| 39 |
+
metrics:
|
| 40 |
+
- type: f1
|
| 41 |
+
name: Macro F1
|
| 42 |
+
value: 0.8764
|
| 43 |
+
- type: accuracy
|
| 44 |
+
name: Top-1 accuracy
|
| 45 |
+
value: 0.8492
|
| 46 |
---
|
| 47 |
|
| 48 |
+
# MillID tiny v1.5: MultiLingual Language IDentifier
|
| 49 |
|
| 50 |
+
A byte-level, encoder-only transformer that names the language of a passage, from a table cell to a paragraph: **1,641 language-script labels** (ISO 639-3 + script, e.g. `eng_Latn`, `amh_Ethi`). 2.9M parameters, trained from scratch. Apache-2.0.
|
| 51 |
+
|
| 52 |
+
## The MillID models
|
| 53 |
+
|
| 54 |
+
| Model | Size | Macro F1, `test` / `udhr` | Runs best on |
|
| 55 |
+
|---|---|---|---|
|
| 56 |
+
| **MillID tiny v1.5** (this model) | 2.9M parameters, ONNX 11 MB | 0.9554 / 0.8764 | a CPU, or a web page |
|
| 57 |
+
| [MillID medium v1](https://huggingface.co/baobabtech/millid-medium-v1) | 115M parameters, ONNX 455 MB | 0.9576 / 0.8780 | a GPU |
|
| 58 |
+
| [MillID large v1.5](https://huggingface.co/baobabtech/millid-large-v1.5) | 193M parameters, ONNX 764 MB | 0.9646 / 0.8812 | a GPU: the most accurate |
|
| 59 |
+
|
| 60 |
+
All three, language by language, against GlotLID and Meta's fastText: the [leaderboard](https://huggingface.co/baobabtech/millid). GlotLID, restricted to MillID's labels, scores 0.9755 / 0.8873 on the same sets.
|
| 61 |
+
|
| 62 |
+
## Use it
|
| 63 |
+
|
| 64 |
+
No server and no PyTorch: the model runs in your process from `onnx/model.onnx`, in Python or JavaScript, and the two give the same answers (one encoder, ported line for line and tested against the same fixtures in [baobab-tech/millid](https://github.com/baobab-tech/millid)).
|
| 65 |
+
|
| 66 |
+
```bash
|
| 67 |
+
pip install "millid[cpu] @ git+https://github.com/baobab-tech/millid.git" # [gpu] for CUDA
|
| 68 |
+
```
|
| 69 |
|
| 70 |
```python
|
| 71 |
+
from millid import MillID
|
| 72 |
|
| 73 |
model = MillID.from_pretrained("baobabtech/millid-tiny-v1.5")
|
| 74 |
+
model.predict("Lave men ou ak savon anvan ou manje.", k=3)
|
| 75 |
+
# [Prediction(label='hat_Latn', language='Haitian Creole', probability=...), ...]
|
| 76 |
+
model.predict(["one text", "another"], k=3) # one list of answers per text
|
| 77 |
+
model.identify_document(long_text) # any length: its languages and segments
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
```bash
|
| 81 |
+
millid predict "Lave men ou ak savon anvan ou manje." --model baobabtech/millid-tiny-v1.5 -k 3
|
| 82 |
```
|
| 83 |
|
| 84 |
+
JavaScript, in Node or a browser (`js/` in the same repository; not on npm yet):
|
| 85 |
+
|
| 86 |
+
```js
|
| 87 |
+
import { MillID } from "@baobabtech/millid"; // "@baobabtech/millid/web" in a browser, with { ort }
|
| 88 |
+
const model = await MillID.fromPretrained("baobabtech/millid-tiny-v1.5");
|
| 89 |
+
await model.predict("Lave men ou ak savon anvan ou manje.", 3);
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
`millid.py` in this repository is the PyTorch training code, which reads `model.safetensors` to fine-tune or export.
|
| 93 |
+
|
| 94 |
+
The ONNX graph takes, for each UTF-8 byte of a passage cut to 255 bytes after a CLS token, `ids`, `script` and `charpos` (int64, `[batch, bytes]`), `ngrams` (int64, `[batch, bytes, 3]`) and `mask` (bool, `[batch, bytes]`), and returns `logits` (float32, `[batch, labels]`). `millid.encode_batch` and the JavaScript `encodeBatch` build them; script ids come from a frozen table (Unicode 15.0), so every runtime gives the same ones.
|
| 95 |
+
|
| 96 |
## Architecture
|
| 97 |
|
| 98 |
+
UTF-8 bytes (after Unicode NFKC), each embedded as byte + Unicode script + byte-in-character + hashed character 2-, 3- and 4-grams (4,096 buckets) -> depthwise convolution stem (kernel 5) -> strided convolution, 1 bytes per token -> 3 pre-norm blocks (RMSNorm, attention with RoPE, 3 heads, SwiGLU; d=192) -> masked mean pooling -> language head, each language's vector the sum of its own, its language's and its script's. Up to 256 bytes per passage. See `ARCHITECTURE.md`.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
|
| 100 |
## Evaluation against GlotLID and fastText
|
| 101 |
|
| 102 |
+
`validation` chose the checkpoint; `test` is split by document from training; `udhr` is the Universal Declaration of Human Rights, labelled by its translators, over the languages MillID knows, and `udhr-all` over all of them. `glotlid` is [GlotLID](https://huggingface.co/cis-lmu/glotlid) as it is; `glotlid@millid` is GlotLID restricted to MillID's labels, the like-for-like comparison. GlotLID's own labels came from training on data that includes UDHR and labelled FinePDFs and FineWeb-2, so its scores on `udhr` and on those sources are optimistic. `fasttext` is Meta's [fastText language identifier](https://huggingface.co/facebook/fasttext-language-identification) (NLLB, 218 labels), its answers mapped onto MillID's spelling (Simplified and Traditional Han as `Hani`, `pes`/`prs` as `fas`, `est` as `ekk`). It cannot answer most of the 1,600 languages here, so `test-common` and `udhr-common` score every model on the passages whose language all of them know: the head-to-head on equal terms.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 103 |
|
| 104 |
| Set | Model | Top-1 | Top-3 | Top-5 | Macro P | Macro R | Macro F1 | Median F1 | Languages |
|
| 105 |
|---|---|---|---|---|---|---|---|---|---|
|
|
|
|
| 148 |
|
| 149 |
### Leaderboard: test
|
| 150 |
|
| 151 |
+
MillID's F1 against the others', language by language: against GlotLID restricted to MillID's labels, MillID is better on **103** languages, worse on **869** and within 0.01 on 649; against fastText restricted to MillID's labels, MillID is better on **1616** languages, worse on **0** and within 0.01 on 5. The full table, with precision and recall, is `reports/test/leaderboard.csv`.
|
|
|
|
| 152 |
|
| 153 |
The 20 languages with the most passages:
|
| 154 |
|
|
|
|
| 156 |
|---|---|---|---|---|---|---|---|
|
| 157 |
| `fra_Latn` | French | 1652 | 0.929 | 0.928 | 0.928 | 0.808 | 0.808 |
|
| 158 |
| `eng_Latn` | English | 1444 | 0.917 | 0.858 | 0.859 | 0.653 | 0.648 |
|
| 159 |
+
| `spa_Latn` | Spanish | 1136 | 0.930 | 0.951 | 0.951 | 0.574 | 0.574 |
|
| 160 |
| `tam_Taml` | Tamil | 754 | 0.997 | 0.993 | 0.993 | 0.965 | 0.965 |
|
| 161 |
| `arb_Arab` | Arabic (Modern Standard) | 745 | 0.814 | 0.785 | 0.785 | 0.513 | 0.512 |
|
| 162 |
| `por_Latn` | Portuguese | 657 | 0.947 | 0.947 | 0.949 | 0.756 | 0.755 |
|
| 163 |
| `kan_Knda` | Kannada | 601 | 0.969 | 0.993 | 0.993 | 0.922 | 0.922 |
|
| 164 |
| `zul_Latn` | Zulu | 594 | 0.846 | 0.896 | 0.896 | 0.539 | 0.539 |
|
| 165 |
+
| `swh_Latn` | Swahili | 592 | 0.848 | 0.917 | 0.916 | 0.346 | 0.346 |
|
| 166 |
| `mar_Deva` | Marathi | 589 | 0.965 | 0.989 | 0.990 | 0.926 | 0.926 |
|
| 167 |
+
| `tso_Latn` | Tsonga | 581 | 0.965 | 0.956 | 0.956 | 0.425 | 0.425 |
|
| 168 |
| `hun_Latn` | Hungarian | 576 | 0.987 | 0.999 | 0.999 | 0.232 | 0.232 |
|
| 169 |
| `afr_Latn` | Afrikaans | 569 | 0.967 | 0.985 | 0.985 | 0.861 | 0.860 |
|
| 170 |
| `tel_Telu` | Telugu | 555 | 0.991 | 0.994 | 0.994 | 0.951 | 0.951 |
|
|
|
|
| 172 |
| `nbl_Latn` | South Ndebele | 528 | 0.903 | 0.948 | 0.949 | 0.000 | 0.000 |
|
| 173 |
| `ory_Orya` | Odia (individual language) | 511 | 0.988 | 0.991 | 0.994 | 0.976 | 0.976 |
|
| 174 |
| `sot_Latn` | Southern Sotho | 491 | 0.966 | 0.977 | 0.978 | 0.660 | 0.660 |
|
| 175 |
+
| `nso_Latn` | Northern Sotho | 479 | 0.956 | 0.969 | 0.969 | 0.915 | 0.914 |
|
| 176 |
| `kua_Latn` | Kuanyama | 476 | 0.962 | 0.986 | 0.986 | 0.000 | 0.000 |
|
| 177 |
|
| 178 |
Where MillID gains most over GlotLID:
|
|
|
|
| 181 |
|---|---|---|---|---|---|---|---|
|
| 182 |
| `lbj_Tibt` | Ladakhi | 66 | 0.943 | 0.000 | 0.000 | 0.000 | 0.000 |
|
| 183 |
| `ain_Latn` | Ainu | 1 | 0.667 | 0.000 | 0.000 | 0.000 | 0.000 |
|
| 184 |
+
| `ajp_Arab` | South Levantine Arabic | 28 | 0.946 | 0.581 | 0.581 | 0.000 | 0.000 |
|
| 185 |
| `und_Laoo` | und | 20 | 0.923 | 0.621 | 0.621 | 0.000 | 0.000 |
|
| 186 |
| `und_Thaa` | und | 29 | 0.881 | 0.651 | 0.651 | 0.000 | 0.000 |
|
| 187 |
| `sgh_Cyrl` | Shughni | 9 | 0.857 | 0.667 | 0.667 | 0.000 | 0.000 |
|
|
|
|
| 200 |
| Label | Language | Passages | MillID F1 | GlotLID F1 | GlotLID F1, restricted | fastText F1 | fastText F1, restricted |
|
| 201 |
|---|---|---|---|---|---|---|---|
|
| 202 |
| `mus_Latn` | Muscogee | 2 | 0.333 | 1.000 | 1.000 | 0.000 | 0.000 |
|
| 203 |
+
| `ttj_Latn` | Tooro | 28 | 0.485 | 0.946 | 0.946 | 0.000 | 0.000 |
|
| 204 |
| `mbd_Latn` | Dibabawon Manobo | 14 | 0.596 | 1.000 | 1.000 | 0.000 | 0.000 |
|
| 205 |
| `knc_Arab` | Central Kanuri | 68 | 0.462 | 0.823 | 0.825 | 0.007 | 0.007 |
|
| 206 |
| `biu_Latn` | Biete | 7 | 0.667 | 1.000 | 1.000 | 0.000 | 0.000 |
|
|
|
|
| 217 |
|
| 218 |
### Leaderboard: udhr
|
| 219 |
|
| 220 |
+
MillID's F1 against the others', language by language: against GlotLID restricted to MillID's labels, MillID is better on **52** languages, worse on **105** and within 0.01 on 201; against fastText restricted to MillID's labels, MillID is better on **303** languages, worse on **15** and within 0.01 on 40. The full table, with precision and recall, is `reports/udhr/leaderboard.csv`.
|
|
|
|
| 221 |
|
| 222 |
The 20 languages with the most passages:
|
| 223 |
|
| 224 |
| Label | Language | Passages | MillID F1 | GlotLID F1 | GlotLID F1, restricted | fastText F1 | fastText F1, restricted |
|
| 225 |
|---|---|---|---|---|---|---|---|
|
| 226 |
+
| `roh_Latn` | Romansh | 399 | 0.994 | 0.999 | 0.999 | 0.946 | 0.946 |
|
| 227 |
+
| `oci_Latn` | Occitan | 398 | 0.277 | 0.376 | 0.376 | 0.435 | 0.435 |
|
| 228 |
| `cmn_Hani` | Chinese (Mandarin) | 319 | 0.892 | 0.868 | 0.868 | 0.468 | 0.468 |
|
| 229 |
| `krl_Latn` | Karelian | 183 | 0.000 | 0.011 | 0.011 | 0.000 | 0.000 |
|
| 230 |
| `qug_Latn` | Chimborazo Highland Quichua | 182 | 0.011 | 0.000 | 0.000 | 0.000 | 0.000 |
|
|
|
|
| 234 |
| `auc_Latn` | Waorani | 154 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
|
| 235 |
| `kwi_Latn` | Awa-Cuaiquer | 145 | 0.880 | 0.877 | 0.877 | 0.000 | 0.000 |
|
| 236 |
| `jpn_Jpan` | Japanese | 140 | 1.000 | 1.000 | 1.000 | 0.944 | 0.944 |
|
| 237 |
+
| `snn_Latn` | Siona | 136 | 0.630 | 0.514 | 0.514 | 0.000 | 0.000 |
|
| 238 |
| `ktu_Latn` | Kituba (Democratic Republic of Congo) | 118 | 0.765 | 0.680 | 0.680 | 0.000 | 0.000 |
|
| 239 |
+
| `lat_Latn` | Latin | 118 | 0.996 | 0.992 | 0.992 | 0.000 | 0.000 |
|
| 240 |
+
| `hat_Latn` | Haitian Creole | 117 | 0.992 | 0.979 | 0.979 | 0.699 | 0.699 |
|
| 241 |
| `nya_Latn` | Nyanja | 116 | 0.991 | 1.000 | 1.000 | 0.806 | 0.806 |
|
| 242 |
| `kmb_Latn` | Kimbundu | 116 | 0.970 | 1.000 | 1.000 | 0.877 | 0.877 |
|
| 243 |
| `rmn_Latn` | Balkan Romani | 116 | 0.678 | 0.857 | 0.857 | 0.000 | 0.000 |
|
| 244 |
| `twi_Latn` | Twi | 116 | 0.983 | 0.996 | 0.996 | 0.399 | 0.396 |
|
| 245 |
+
| `chr_Cher` | Cherokee | 115 | 0.670 | 0.663 | 0.663 | 0.000 | 0.000 |
|
| 246 |
|
| 247 |
Where MillID gains most over GlotLID:
|
| 248 |
|
| 249 |
| Label | Language | Passages | MillID F1 | GlotLID F1 | GlotLID F1, restricted | fastText F1 | fastText F1, restricted |
|
| 250 |
|---|---|---|---|---|---|---|---|
|
| 251 |
+
| `mic_Latn` | Mi'kmaw | 59 | 0.992 | 0.427 | 0.427 | 0.000 | 0.000 |
|
| 252 |
| `tet_Latn` | Tetum | 58 | 0.638 | 0.167 | 0.167 | 0.000 | 0.000 |
|
| 253 |
| `fuf_Latn` | Pular | 58 | 0.906 | 0.483 | 0.483 | 0.000 | 0.000 |
|
| 254 |
+
| `sag_Latn` | Sango | 59 | 0.992 | 0.578 | 0.578 | 0.189 | 0.189 |
|
| 255 |
| `skr_Arab` | Saraiki | 63 | 0.867 | 0.500 | 0.500 | 0.000 | 0.000 |
|
| 256 |
| `qvh_Latn` | Huamalíes-Dos de Mayo Huánuco Quechua | 58 | 0.468 | 0.154 | 0.154 | 0.000 | 0.000 |
|
| 257 |
| `zgh_Tfng` | Standard Moroccan Tamazight | 60 | 0.750 | 0.462 | 0.462 | 0.000 | 0.000 |
|
| 258 |
| `lld_Latn` | Ladin | 59 | 0.909 | 0.731 | 0.731 | 0.000 | 0.000 |
|
| 259 |
+
| `tah_Latn` | Tahitian | 57 | 0.973 | 0.812 | 0.812 | 0.966 | 0.966 |
|
| 260 |
| `yue_Hani` | Cantonese | 49 | 0.734 | 0.580 | 0.580 | 0.111 | 0.111 |
|
| 261 |
| `ote_Latn` | Mezquital Otomi | 59 | 0.154 | 0.000 | 0.000 | 0.000 | 0.000 |
|
| 262 |
| `pnb_Arab` | Western Panjabi | 61 | 0.882 | 0.739 | 0.739 | 0.000 | 0.000 |
|
|
|
|
| 274 |
| `tbz_Latn` | Ditammari | 60 | 0.000 | 0.378 | 0.378 | 0.000 | 0.000 |
|
| 275 |
| `cbu_Latn` | Candoshi-Shapra | 57 | 0.500 | 0.882 | 0.874 | 0.000 | 0.000 |
|
| 276 |
| `idu_Latn` | Idoma | 51 | 0.603 | 0.879 | 0.938 | 0.000 | 0.000 |
|
| 277 |
+
| `ell_Grek` | Greek | 115 | 0.670 | 1.000 | 1.000 | 1.000 | 1.000 |
|
| 278 |
| `qvc_Latn` | Cajamarca Quechua | 58 | 0.648 | 0.906 | 0.906 | 0.000 | 0.000 |
|
| 279 |
| `cpu_Latn` | Pichis Ashéninka | 60 | 0.729 | 0.974 | 0.974 | 0.000 | 0.000 |
|
| 280 |
+
| `qvn_Latn` | North Junín Quechua | 57 | 0.219 | 0.460 | 0.460 | 0.000 | 0.000 |
|
| 281 |
| `hin_Deva` | Hindi | 59 | 0.723 | 0.957 | 0.957 | 0.975 | 0.975 |
|
| 282 |
| `hrv_Latn` | Croatian | 58 | 0.500 | 0.727 | 0.727 | 0.474 | 0.474 |
|
| 283 |
| `kbp_Latn` | Kabiyè | 59 | 0.781 | 1.000 | 1.000 | 0.389 | 0.389 |
|
|
|
|
| 286 |
|
| 287 |
### Leaderboard: test-common
|
| 288 |
|
| 289 |
+
MillID's F1 against the others', language by language: against GlotLID restricted to MillID's labels, MillID is better on **6** languages, worse on **154** and within 0.01 on 53; against fastText restricted to MillID's labels, MillID is better on **85** languages, worse on **51** and within 0.01 on 77. The full table, with precision and recall, is `reports/test-common/leaderboard.csv`.
|
|
|
|
| 290 |
|
| 291 |
The 20 languages with the most passages:
|
| 292 |
|
|
|
|
| 324 |
| `fuv_Latn` | Nigerian Fulfulde | 164 | 0.907 | 0.877 | 0.892 | 0.859 | 0.859 |
|
| 325 |
| `knc_Latn` | Central Kanuri | 293 | 0.967 | 0.952 | 0.952 | 0.981 | 0.981 |
|
| 326 |
| `quy_Latn` | Ayacucho Quechua | 271 | 0.940 | 0.925 | 0.933 | 0.979 | 0.979 |
|
| 327 |
+
| `kam_Latn` | Kamba | 272 | 0.980 | 0.972 | 0.974 | 0.863 | 0.863 |
|
| 328 |
+
| `bjn_Arab` | Banjar | 116 | 0.992 | 0.834 | 0.987 | 0.453 | 0.960 |
|
| 329 |
| `por_Latn` | Portuguese | 657 | 0.959 | 0.954 | 0.956 | 0.950 | 0.949 |
|
| 330 |
| `mlt_Latn` | Maltese | 291 | 0.995 | 0.993 | 0.993 | 0.961 | 0.961 |
|
|
|
|
| 331 |
| `hye_Armn` | Armenian | 178 | 1.000 | 1.000 | 1.000 | 0.977 | 0.977 |
|
| 332 |
+
| `khm_Khmr` | Khmer | 187 | 1.000 | 1.000 | 1.000 | 1.000 | 1.000 |
|
| 333 |
| `guj_Gujr` | Gujarati | 354 | 1.000 | 1.000 | 1.000 | 0.984 | 0.984 |
|
| 334 |
| `mal_Mlym` | Malayalam | 338 | 1.000 | 1.000 | 1.000 | 0.994 | 0.994 |
|
| 335 |
|
|
|
|
| 340 |
| `knc_Arab` | Central Kanuri | 68 | 0.522 | 0.857 | 0.860 | 0.029 | 0.029 |
|
| 341 |
| `hrv_Latn` | Croatian | 168 | 0.659 | 0.994 | 0.994 | 0.856 | 0.856 |
|
| 342 |
| `bos_Latn` | Bosnian | 198 | 0.685 | 1.000 | 1.000 | 0.897 | 0.897 |
|
| 343 |
+
| `tzm_Tfng` | Central Atlas Tamazight | 157 | 0.697 | 0.934 | 0.934 | 0.751 | 0.751 |
|
| 344 |
| `zsm_Latn` | Standard Malay | 244 | 0.789 | 0.998 | 0.998 | 0.908 | 0.908 |
|
| 345 |
| `taq_Tfng` | Tamasheq | 104 | 0.654 | 0.805 | 0.805 | 0.000 | 0.000 |
|
| 346 |
| `ind_Latn` | Indonesian | 335 | 0.842 | 0.991 | 0.991 | 0.887 | 0.887 |
|
|
|
|
| 350 |
| `kin_Latn` | Kinyarwanda | 210 | 0.849 | 0.981 | 0.981 | 0.854 | 0.854 |
|
| 351 |
| `mag_Deva` | Magahi | 97 | 0.890 | 1.000 | 1.000 | 0.772 | 0.772 |
|
| 352 |
| `lim_Latn` | Limburgish | 196 | 0.896 | 1.000 | 1.000 | 0.956 | 0.956 |
|
| 353 |
+
| `run_Latn` | Rundi | 291 | 0.883 | 0.985 | 0.985 | 0.855 | 0.855 |
|
| 354 |
| `taq_Latn` | Tamasheq | 106 | 0.902 | 1.000 | 1.000 | 0.838 | 0.838 |
|
| 355 |
|
| 356 |
Per-language precision, recall (sensitivity), F1 and specificity for every model are in `reports/<set>/`.
|
| 357 |
|
| 358 |
## Training
|
| 359 |
|
| 360 |
+
1,943,957 passages; the best validation macro F1 at step 106,000, after 0.6 hours on 1 GPU. Languages sampled in proportion to n^0.3; 25% of passages cut to a 20 to 80 character snippet; batch 512, AdamW at 0.001, cosine schedule, label smoothing 0.1.
|
| 361 |
+
|
| 362 |
+
The training data is the full MillID build. The public [baobabtech/millid-dataset](https://huggingface.co/datasets/baobabtech/millid-dataset) is that build without Save the Children's and Nal'ibali's text (1.6% of its passages), which is not ours to redistribute. Its splits are the same, so its `test` split is the one scored above, without those passages.
|
| 363 |
+
|
| 364 |
+
## Licence
|
| 365 |
+
|
| 366 |
+
The weights and the code are Apache-2.0. The training data carries its own licence row by row (see the [dataset card](https://huggingface.co/datasets/baobabtech/millid-dataset#licensing)), including text licensed for non-commercial use only (CC BY-NC, CC BY-NC-SA).
|
millid.py
CHANGED
|
@@ -657,7 +657,7 @@ class Sampler:
|
|
| 657 |
A language is drawn with probability proportional to n^alpha, n being its passage count:
|
| 658 |
alpha 1 is the data as it is, alpha 0 every language equally; 0.3 in between. Then a
|
| 659 |
passage of it is drawn, and sometimes cut short, because a short snippet is where
|
| 660 |
-
language identification is hardest and what a
|
| 661 |
"""
|
| 662 |
|
| 663 |
def __init__(self, texts: list[str], label_ids: np.ndarray, alpha: float, short_p: float, seed: int):
|
|
|
|
| 657 |
A language is drawn with probability proportional to n^alpha, n being its passage count:
|
| 658 |
alpha 1 is the data as it is, alpha 0 every language equally; 0.3 in between. Then a
|
| 659 |
passage of it is drawn, and sometimes cut short, because a short snippet is where
|
| 660 |
+
language identification is hardest and what a page holds in headers and table cells.
|
| 661 |
"""
|
| 662 |
|
| 663 |
def __init__(self, texts: list[str], label_ids: np.ndarray, alpha: float, short_p: float, seed: int):
|