davidmelash commited on
Commit
892c141
·
verified ·
1 Parent(s): 75f6ee4

Expand model card: usage, evaluation, training data and procedure, limitations

Browse files
Files changed (1) hide show
  1. README.md +311 -5
README.md CHANGED
@@ -1,12 +1,318 @@
1
  ---
2
- language: uk
 
 
3
  library_name: transformers
4
  pipeline_tag: token-classification
5
- license: mit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  ---
7
 
8
- # wechsel_base
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
- Token classification model that finds personal data in Ukrainian court decisions for pseudonymization.
11
 
12
- Entity types: `ОСОБА`, `АДРЕСА`, `НОМЕР`, `ІНФОРМАЦІЯ`.
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ language:
3
+ - uk
4
+ license: mit
5
  library_name: transformers
6
  pipeline_tag: token-classification
7
+ base_model: benjamin/roberta-base-wechsel-ukrainian
8
+ datasets:
9
+ - lang-uk/court-decisions-uk
10
+ metrics:
11
+ - f1
12
+ - precision
13
+ - recall
14
+ tags:
15
+ - token-classification
16
+ - ner
17
+ - named-entity-recognition
18
+ - pii
19
+ - pii-detection
20
+ - personal-data
21
+ - anonymization
22
+ - pseudonymization
23
+ - de-identification
24
+ - data-privacy
25
+ - privacy
26
+ - redaction
27
+ - legal
28
+ - legal-nlp
29
+ - court-decisions
30
+ - ukrainian
31
+ - ukraine
32
+ - synthetic-data
33
+ - roberta
34
+ new_version: davidmelash/ukrainian-pii-ner-roberta-base
35
+ widget:
36
+ - text: >-
37
+ Позивач Мельничук Андрій Васильович, 12.03.1985 року народження, зареєстрований за адресою: м. Житомир, вул. Лесі Українки, буд. 14, кв. 7, РНОКПП 3124509876, проходив службу у військовій частині А4123.
38
+ - text: >-
39
+ Представник позивача - адвокат Кравчук Олена Миколаївна, електронна пошта: kravchuk.law@ukr.net. Транспортний засіб Toyota Camry, номерний знак АА1234ВС, VIN JTNB11HK103456789, належить відповідачу Шевчуку Т. П.
40
+ model-index:
41
+ - name: wechsel_base
42
+ results:
43
+ - task:
44
+ type: token-classification
45
+ name: Personal data detection (NER)
46
+ dataset:
47
+ type: ukrainian-court-decisions-pseudonymization-test
48
+ name: Ukrainian court decisions pseudonymization test set (240 decisions)
49
+ split: test
50
+ metrics:
51
+ - type: f1
52
+ value: 0.8699
53
+ name: Macro F1 (relaxed, IoU >= 0.5)
54
+ - type: precision
55
+ value: 0.9511
56
+ name: Macro precision (relaxed)
57
+ - type: recall
58
+ value: 0.8084
59
+ name: Macro recall (relaxed)
60
+ - type: f1
61
+ value: 0.8281
62
+ name: Macro F1 (strict, exact boundaries)
63
+ - type: f1
64
+ value: 0.9961
65
+ name: F1 ОСОБА (relaxed)
66
+ - type: f1
67
+ value: 0.7907
68
+ name: F1 АДРЕСА (relaxed)
69
+ - type: f1
70
+ value: 0.9269
71
+ name: F1 НОМЕР (relaxed)
72
+ - type: f1
73
+ value: 0.7660
74
+ name: F1 ІНФОРМАЦІЯ (relaxed)
75
  ---
76
 
77
+ # Ukrainian PII NER for court decisions — RoBERTa-base (WECHSEL), data v2, seed 42
78
+
79
+ **wechsel_base** is a Ukrainian **named-entity recognition (NER)** model that finds **personal data (PII)** in court decisions
80
+ and other legal texts, so they can be **anonymized or pseudonymized** before publication. It tags people's names,
81
+ addresses, personal ID numbers and other identifying details (dates of birth, e-mails, military units) with the four
82
+ categories that Ukrainian courts use when they de-identify decisions. It is a 124M-parameter
83
+ RoBERTa-base fine-tuned from [benjamin/roberta-base-wechsel-ukrainian](https://huggingface.co/benjamin/roberta-base-wechsel-ukrainian) on synthetic court decisions, and it runs
84
+ offline on a CPU.
85
+
86
+ > **Legacy release.** This is the first model of the family, trained on an early version of the data. The v7 models score about 0.09 higher macro F1, mostly on addresses, numbers and ІНФОРМАЦІЯ: use [ukrainian-pii-ner-roberta-base](https://huggingface.co/davidmelash/ukrainian-pii-ner-roberta-base) instead (same size and speed).
87
+
88
+ - **Macro F1 0.870** on a 240-document court-decision test set (precision 0.951, recall
89
+ 0.808): ОСОБА 0.996, АДРЕСА 0.791, НОМЕР 0.927, ІНФОРМАЦІЯ 0.766.
90
+ - Only **15 of 864 people** in the test decisions have any mention of their name left unmasked.
91
+ - Trained without any real personal data: 24,097 published decisions whose placeholders were refilled with synthetic values.
92
+ - CPU-friendly, no GPU needed: the 240 test decisions (1.4M characters) take about 100 s with PyTorch on a laptop CPU.
93
+ - MIT licence; code, data generator and evaluation on [GitHub](https://github.com/EnderLancer/anonimimizer).
94
+
95
+ ## Entity types
96
+
97
+ | Label | Meaning | Examples |
98
+ |---|---|---|
99
+ | `ОСОБА` (person) | Name of a natural person in any form and grammatical case | «Мельничук Андрій Васильович», «Мельничука А. В.», «А. Мельничук» |
100
+ | `АДРЕСА` (address) | Address of residence, stay or property | «м. Житомир, вул. Лесі Українки, буд. 14, кв. 7» |
101
+ | `НОМЕР` (number) | Identifier of a particular person: taxpayer number (РНОКПП / ІПН), passport or ID card, phone, IBAN, bank card, licence plate, VIN, military unit number, enforcement-proceeding number | «3124509876», «АА1234ВС», «А4123» |
102
+ | `ІНФОРМАЦІЯ` (information) | Other identifying information: date of birth or death, e-mail, URL, social-media nickname, name of a military unit or military body that is a party to the case | «12.03.1985 року народження», «kravchuk.law@ukr.net», «Житомирський обласний ТЦК та СП» as the defendant |
103
+
104
+ Labels use the BIO scheme (`B-ОСОБА`, `I-ОСОБА`, …, `O`). Following the conventions of the court register, case numbers,
105
+ cadastral numbers, contract numbers, accounts of state institutions and names of courts are *not* personal data, while
106
+ every natural person — including judges, lawyers and court secretaries — is labelled `ОСОБА`.
107
+
108
+ ## How to use
109
+
110
+ ```python
111
+ from transformers import pipeline
112
+
113
+ ner = pipeline("token-classification", model="davidmelash/wechsel_base", aggregation_strategy="simple")
114
+
115
+ text = (
116
+ "Позивач Мельничук Андрій Васильович, 12.03.1985 року народження, зареєстрований за адресою: "
117
+ "м. Житомир, вул. Лесі Українки, буд. 14, кв. 7, РНОКПП 3124509876, проходив службу у військовій частині А4123."
118
+ )
119
+ for e in ner(text):
120
+ print(e["entity_group"], text[e["start"]:e["end"]])
121
+ # ОСОБА Мельничук Андрій Васильович
122
+ # ІНФОРМАЦІЯ 12.03.1985 року народження
123
+ # АДРЕСА м. Житомир, вул. Лесі Українки, буд. 14, кв. 7
124
+ # НОМЕР 3124509876
125
+ # НОМЕР А4123
126
+ ```
127
+
128
+ ### Long documents
129
+
130
+ The model reads 512 tokens (about 1,500–2,000 characters of Ukrainian) at a time, and a court decision is usually
131
+ longer. Split the text into overlapping windows and merge the results (the pipeline's own `stride` option did not
132
+ cover long texts in transformers 5.19):
133
+
134
+ ```python
135
+ def find_entities(text: str, window: int = 500, stride: int = 100) -> list[dict]:
136
+ """Run the pipeline on overlapping windows of the text and merge the results."""
137
+ offsets = ner.tokenizer(text, add_special_tokens=False, return_offsets_mapping=True)["offset_mapping"]
138
+ found, start = [], 0
139
+ while start < len(offsets):
140
+ end = min(start + window, len(offsets))
141
+ a, b = offsets[start][0], offsets[end - 1][1]
142
+ found += [dict(e, start=e["start"] + a, end=e["end"] + a) for e in ner(text[a:b])]
143
+ if end == len(offsets):
144
+ break
145
+ start = end - stride
146
+ entities = []
147
+ for e in sorted(found, key=lambda e: (e["start"], e["start"] - e["end"])):
148
+ if not entities or e["start"] >= entities[-1]["end"]: # an entity seen by two windows is kept once
149
+ entities.append(e)
150
+ return entities
151
+ ```
152
+
153
+ ### Pseudonymize a document
154
+
155
+ Deterministic pseudonymization replaces each entity with a code and gives the same code to the same value, as Ukrainian
156
+ courts do:
157
+
158
+ ```python
159
+ def pseudonymize(text: str) -> str:
160
+ codes, counts, out, last = {}, {}, [], 0
161
+ for e in find_entities(text):
162
+ label, value = e["entity_group"], text[e["start"]:e["end"]]
163
+ if (label, value) not in codes:
164
+ counts[label] = counts.get(label, 0) + 1
165
+ codes[(label, value)] = f"{label}_{counts[label]}"
166
+ out += [text[last:e["start"]], codes[(label, value)]]
167
+ last = e["end"]
168
+ return "".join(out) + text[last:]
169
+
170
+ print(pseudonymize(text))
171
+ # Позивач ОСОБА_1, ІНФОРМАЦІЯ_1, зареєстрований за адресою: АДРЕСА_1, РНОКПП НОМЕР_1, проходив службу у військовій частині НОМЕР_2.
172
+ ```
173
+
174
+ The [GitHub repository](https://github.com/EnderLancer/anonimimizer) adds what a production pipeline needs on top of the model: linking of different
175
+ forms of one name («Мельничук Андрій Васильович», «Мельничук А. В.», «позивача Мельничука») to one pseudonym, optional
176
+ regex rules, a Gradio demo and an offline Docker image with ONNX Runtime.
177
+
178
+ ## Model family
179
+
180
+ All models were trained with the same code and evaluated on the same test set with the same code (model only). Two
181
+ seeds of one recipe differ by up to 0.010 macro F1, so compare recipes by their seed average. *Names leaked*
182
+ counts the people (of 864) with at least one mention of their name left unmasked.
183
+
184
+ | Model | Architecture | Training data | Seed | Macro F1 | Strict F1 | ОСОБА | АДРЕСА | НОМЕР | ІНФОРМАЦІЯ | Names leaked |
185
+ |---|---|---|---|---|---|---|---|---|---|---|
186
+ | [ukrainian-pii-ner-roberta-base](https://huggingface.co/davidmelash/ukrainian-pii-ner-roberta-base) | RoBERTa-base | data v7-large | 42 | 0.958 | 0.911 | 0.996 | 0.972 | 0.980 | 0.885 | 15 |
187
+ | [wechsel_base_v7large_2026-10-09_r4_s43](https://huggingface.co/davidmelash/wechsel_base_v7large_2026-10-09_r4_s43) | RoBERTa-base | data v7-large | 43 | 0.957 | 0.905 | 0.996 | 0.972 | 0.984 | 0.878 | 14 |
188
+ | [ukrainian-pii-ner-modernbert-large](https://huggingface.co/davidmelash/ukrainian-pii-ner-modernbert-large) | ModernBERT-large | data v7 | 43 | 0.957 | 0.921 | 0.996 | 0.967 | 0.982 | 0.882 | 15 |
189
+ | [wechsel_base_v7_2026-10-09_r5_s43](https://huggingface.co/davidmelash/wechsel_base_v7_2026-10-09_r5_s43) | RoBERTa-base | data v7 | 43 | 0.956 | 0.902 | 0.998 | 0.968 | 0.980 | 0.879 | 11 |
190
+ | [wechsel_base_v7_2026-10-09_r5](https://huggingface.co/davidmelash/wechsel_base_v7_2026-10-09_r5) | RoBERTa-base | data v7 | 42 | 0.955 | 0.904 | 0.997 | 0.968 | 0.980 | 0.873 | 12 |
191
+ | [modern_liberta_large_w2048_v7large_2026-10-09_r4_s43](https://huggingface.co/davidmelash/modern_liberta_large_w2048_v7large_2026-10-09_r4_s43) | ModernBERT-large | data v7-large | 43 | 0.953 | 0.925 | 0.997 | 0.972 | 0.963 | 0.881 | 19 |
192
+ | [modern_liberta_large_w2048_v7large_2026-10-09_r4](https://huggingface.co/davidmelash/modern_liberta_large_w2048_v7large_2026-10-09_r4) | ModernBERT-large | data v7-large | 42 | 0.952 | 0.920 | 0.996 | 0.974 | 0.956 | 0.883 | 17 |
193
+ | [modern_liberta_large_w2048_v7_2026-10-09_r5](https://huggingface.co/davidmelash/modern_liberta_large_w2048_v7_2026-10-09_r5) | ModernBERT-large | data v7 | 42 | 0.947 | 0.914 | 0.997 | 0.954 | 0.967 | 0.870 | 15 |
194
+ | **wechsel_base** (this model) | RoBERTa-base | data v2 | 42 | **0.870** | 0.828 | 0.996 | 0.791 | 0.927 | 0.766 | 15 |
195
+
196
+ ## Evaluation
197
+
198
+ The model was scored on the test set of a Ukrainian court-decision pseudonymization challenge: **240 real court decisions**
199
+ from the Unified State Register of Court Decisions of Ukraine (ЄДРСР, 1.4M characters), whose anonymized fragments the
200
+ organisers replaced with realistic synthetic values and annotated at the character level (3,685 entity mentions; 864 people). The test set was never used for training or checkpoint selection.
201
+
202
+ **Metric:** F1 per entity type, a predicted span counts as correct when it has the right type and an intersection over
203
+ union of at least 0.5 with a gold span (*relaxed*); *strict* requires exact boundaries. The headline number is the
204
+ unweighted (macro) average over the four types, so the rare types weigh as much as persons. The scores are for the
205
+ model alone — no rules, no post-processing — computed with exactly the code of [How to use](#how-to-use).
206
+
207
+ | Entity type | Precision | Recall | F1 (relaxed) | F1 (strict) | Gold mentions |
208
+ |---|---|---|---|---|---|
209
+ | ОСОБА | 0.997 | 0.995 | **0.996** | 0.914 | 2,837 |
210
+ | АДРЕСА | 0.863 | 0.730 | **0.791** | 0.753 | 233 |
211
+ | НОМЕР | 0.997 | 0.866 | **0.927** | 0.901 | 447 |
212
+ | ІНФОРМАЦІЯ | 0.947 | 0.643 | **0.766** | 0.745 | 168 |
213
+ | **Macro average** | 0.951 | 0.808 | **0.870** | 0.828 | |
214
+
215
+ | Other views of the same predictions | Value |
216
+ |---|---|
217
+ | Macro F1 on the corrected gold (18 mis-annotated test documents fixed) | 0.862 |
218
+ | Persons whose name leaks at least once (deanonymization risk by name, lower is better) | 0.017 (15 of 864) |
219
+
220
+ A 95 % bootstrap interval over documents is about ±0.03 for the macro F1, so models closer than about 0.01 are
221
+ statistically indistinguishable.
222
+
223
+ ## Training data
224
+
225
+ The model was trained on an early version (v2) of the synthetic data pipeline: **24,097 court decisions** from [lang-uk/court-decisions-uk](https://huggingface.co/datasets/lang-uk/court-decisions-uk) with **403,029 labelled entity spans** (ОСОБА 78 %, ІНФОРМАЦІЯ 8 %, НОМЕР 8 %, АДРЕСА 6 %) and 3,558 masked spans. Addresses come from the Ukrposhta directory only. This version predates the third corpus (2024 Supreme Court decisions from the court register), the generator of military-body names and the masking of ambiguous values used by the v7 models.
226
+
227
+ There is no public, labelled corpus of Ukrainian personal data, so the training set is built by *distant supervision*
228
+ from published court decisions (code: [`datagen/`](https://github.com/EnderLancer/anonimimizer/tree/main/datagen)). The v2 data of this model was built with an early version of these steps; the list describes the current (v7) pipeline.
229
+
230
+ 1. **Placeholders.** Court clerks publish decisions with personal data replaced by placeholders such as `ОСОБА_1`,
231
+ `АДРЕСА_1`, `НОМЕР_1`, `ІНФОРМАЦІЯ_1`. Each placeholder tells where an entity was and of which type.
232
+ 2. **Synthetic values.** Every placeholder is filled with a realistic value in the grammatical case its context needs:
233
+ names from [lang-uk/name_freq_dict_uk](https://github.com/lang-uk/name_freq_dict_uk); addresses from the Ukrposhta
234
+ directory in several writing styles; taxpayer numbers (РНОКПП), passports, ID cards, phones,
235
+ IBANs, bank cards, licence plates in Cyrillic and Latin letters, VINs, IMEIs, military unit numbers and
236
+ enforcement-proceeding numbers; dates of birth and death in five formats; e-mails, URLs and names of military bodies.
237
+ The same placeholder gets the same value throughout a decision.
238
+ 3. **Labels.** The filled values become character-level labels. People whose names the clerk left open (judges,
239
+ lawyers, secretaries) are labelled ОСОБА as well, by role, initials, heading and signature rules checked against a
240
+ general Ukrainian NER model, because in the target data *every* natural person is pseudonymized.
241
+ 4. **Masks.** Values whose type the context does not settle — for example a civil body or company in an anonymized
242
+ slot, an open phone number with no person nearby, or an enforcement-proceeding number with no natural person
243
+ involved — are excluded from the loss (label `-100`) instead of being taught as either entity or non-entity.
244
+ 5. **Hygiene.** The 250 decisions the challenge test set was cut from, other decisions of the same court cases and
245
+ near-duplicates (word 5-gram containment ≥ 0.5) are removed; the train / dev split is grouped by case number.
246
+ An independent audit of the v2 data, done after this model was trained, found no test document in it, but 3 training decisions belong to the same court cases as test documents: v2 predates the exclusion step.
247
+
248
+ ## Training procedure
249
+
250
+ Fine-tuned from [benjamin/roberta-base-wechsel-ukrainian](https://huggingface.co/benjamin/roberta-base-wechsel-ukrainian), a Ukrainian RoBERTa-base obtained from English RoBERTa with WECHSEL embedding transfer (MIT), with a token-classification head over 9 BIO labels (`O`, `B-`/`I-` × 4 types).
251
+
252
+ | Setting | Value |
253
+ |---|---|
254
+ | Epochs | 3 (the last checkpoint is published) |
255
+ | Learning rate | 4e-05, linear decay, warm-up 6 % of the steps |
256
+ | Optimizer | AdamW, weight decay 0.01 |
257
+ | Batch size | 64 windows |
258
+ | Window | 512 tokens, stride 128 (long decisions are split into overlapping windows) |
259
+ | Oversampling | decisions with a НОМЕР entity are seen twice per epoch (31,978 training documents, 97,592 windows) |
260
+ | Precision | bf16 mixed precision |
261
+ | Seed | 42 |
262
+ | Hardware | 1 × A100-SXM4-40GB, 22 min |
263
+ | Final training loss | 0.0195 |
264
+ | Dev F1 per epoch | 0.9869, 0.9893, 0.9906 (500 synthetic Supreme Court decisions; the dev set saturates and does not rank models like the test set) |
265
+
266
+ Training code: [`train/`](https://github.com/EnderLancer/anonimimizer/tree/main/train) (`python scripts/train.py --model benjamin/roberta-base-wechsel-ukrainian --epochs 3 --lr 4e-05 --batch 64 --seed 42`).
267
+
268
+ ## Intended use
269
+
270
+ - Pseudonymization of Ukrainian court decisions before publication in an open register, in the style of the Unified
271
+ State Register of Court Decisions (ЄДРСР).
272
+ - Finding personal data in other Ukrainian legal and administrative documents: claims, rulings, orders, letters.
273
+ - A PII detector inside a larger de-identification pipeline, together with rules and human review.
274
+ - Research on Ukrainian legal NLP, PII detection and synthetic training data.
275
+
276
+ ## Limitations
277
+
278
+ - **Domain.** The model learnt from court decisions, where names follow procedural roles («позивач», «відповідач»). On
279
+ news, encyclopaedia and web text an earlier model of this family found fewer than one name in five, so do not use it
280
+ as a general-purpose Ukrainian NER model.
281
+ - **Label conventions.** It follows the de-identification practice of Ukrainian courts, not a generic PII taxonomy:
282
+ civil bodies and companies are not labelled, a date is labelled only when it is a date of birth or death, and a
283
+ military body is labelled only as a party to the case. Clerks apply these rules inconsistently, which caps the
284
+ ІНФОРМАЦІЯ score.
285
+ - **Casing and noise.** Training text is normally cased: names written entirely in capitals (for example in signature
286
+ blocks, «Ольга КАШПУР») and words with Latin look-alike letters are recognised less reliably.
287
+ - **Phones and rare identifiers.** Open phone numbers were mostly masked in training, so phone recall is lower than for
288
+ other numbers.
289
+ - **Synthetic data.** Values were generated, so some inflected forms are imperfect, and the test set itself is
290
+ synthetic; real decisions may contain patterns that neither covers. A few data-generation choices (date formats,
291
+ excerpt length) follow published statistics of the test set.
292
+ - **Not a guarantee.** Automatic pseudonymization reduces but does not remove the risk of re-identification. Review
293
+ the output before publishing personal data.
294
+
295
+ ## Deployment
296
+
297
+ The model needs no GPU: with PyTorch the 240 test decisions (1.4M characters) take about 100 s on a laptop CPU (Apple M1 Pro); exported to ONNX with int8 quantization, the same test runs in a Docker container in about 290 s on 4 CPU cores with 0.5 GB of RAM (p50 1.2 s per decision), at a cost of about 0.001 F1. This fits the challenge limits of 8 GB RAM and 2 hours for the whole test set by
298
+ a wide margin. See [`docker/`](https://github.com/EnderLancer/anonimimizer/tree/main/docker) for the ONNX export and the offline image.
299
+
300
+ ## Licence and attribution
301
+
302
+ The weights are released under the **MIT licence**. Training texts come from
303
+ [lang-uk/court-decisions-uk](https://huggingface.co/datasets/lang-uk/court-decisions-uk) (MIT).
304
+ Synthetic names come from [lang-uk/name_freq_dict_uk](https://github.com/lang-uk/name_freq_dict_uk) and addresses from
305
+ the Ukrposhta directory.
306
 
307
+ ## Citation
308
 
309
+ ```bibtex
310
+ @misc{wechsel_base,
311
+ title = {Ukrainian PII NER for court decisions — RoBERTa-base (WECHSEL), data v2, seed 42},
312
+ author = {Melashych, David},
313
+ year = {2026},
314
+ publisher = {Hugging Face},
315
+ howpublished = {\url{https://huggingface.co/davidmelash/wechsel_base}},
316
+ note = {Code: https://github.com/EnderLancer/anonimimizer}
317
+ }
318
+ ```