vladimirbesk commited on
Commit
ac890a1
·
verified ·
1 Parent(s): 6aa441b

Bring the card to the preprint, and ship the scoring head as safetensors

Browse files

The wording bench now reports both candidate-set sizes and marks which rows are
controls. The Russian word and the English key are the wordings both releases
trained on, so those rows measure recall of a trained form and their near-zero
gap is what a control should show; the Russian phrase is a training style for
v1.3 only, so its gap is expected by construction. Only the held-out rows speak
to generalisation, and the reading they support is narrower than before:
training a label in several surface forms helps on unfamiliar wordings made of
words, and does nothing for abbreviations or opaque codes, where the label
string carries little of its meaning.

Confidence no longer follows accuracy in the summary either. With eighteen
candidates the count of confident errors rises on jargon and on slang, because
the augmented release is more confident overall, so a deployment that invents
its own label vocabulary is pointed at fit_temperature.py instead.

The calibration figures on the comparable rows are recomputed with a recorded
split seed. The previous implementation shuffled its index list in place without
resetting it between splits, so the numbers depended on the order of rows in the
file. The corrected figures are 2.0054 against 1.5593 for the fitted temperature
and 0.0190 against 0.0191 for the ECE that remains, favouring v1.3 in 14 of 25
splits rather than 12. Nothing turns over.

Latency is measured per decision at two, five and eighteen candidates against an
open comparison model on the same machine, replacing three figures that did not
say how many candidates they covered.

head.safetensors is added in this same commit because the usage snippet now
reads it. head.pt stays for older code.

The demo link is relabelled: its probabilities are precomputed, and a live CPU
space would need a paid plan.

Files changed (2) hide show
  1. README.md +99 -36
  2. head.safetensors +3 -0
README.md CHANGED
@@ -31,7 +31,7 @@ options, and ordinal scale. It is a compact encoder (mmBERT-base, 307M), so it
31
  runs on CPU and can be deployed inside a closed perimeter.
32
 
33
  - Project page: https://ru-jev.besk.tech
34
- - Interactive demo: https://huggingface.co/spaces/besktech/ru-jev-demo
35
  - Training and evaluation code: https://github.com/beskvladimir-create/ru-jev
36
 
37
  Earlier releases are kept on branches: `v1.1` and `v1`. Load one with
@@ -65,30 +65,79 @@ so the model has to read an option instead of recognising it. For the routing
65
  tasks that includes the English key written in Cyrillic and a clipped form of
66
  it, generated by rule.
67
 
68
- | Option wording | v1.1 accuracy | v1.1 mean confidence | v1.3 accuracy | v1.3 mean confidence |
69
- | --- | --- | --- | --- | --- |
70
- | Russian word, `погода` | 0.956 | 0.965 | 0.960 | 0.973 |
71
- | English key, `weather` | 0.957 | 0.968 | 0.962 | 0.974 |
72
- | Descriptive sentence | 0.939 | 0.930 | 0.958 | 0.961 |
73
- | Russian phrase, `прогноз погоды` | 0.881 | 0.896 | 0.957 | 0.972 |
74
- | Department name, `метеослужба` | 0.835 | 0.865 | 0.869 | 0.922 |
75
- | Jargon, `вэзер` | 0.633 | 0.754 | 0.855 | 0.885 |
76
-
77
- A thousand routing questions per row, the same eighteen categories every time,
78
- only the wording differs. Every row in this table covers all eighteen
79
- categories, for both versions.
80
-
81
- One caveat on the jargon row, because it is the headline number. An intent key
82
- begins with its scenario name, so three of the eighteen jargon labels coincide
83
- with what the transliteration rule produces and reach training as a first word.
84
- Restricted to the fifteen that do not coincide, which is the honest measure of
85
- generalisation to wording the model has never seen, the figures are 0.624
86
- for v1.1 and 0.838 for v1.3. That strict pair is the one this project
87
- quotes for the jargon result. The all-eighteen pair, 0.633 against
88
- 0.855, is the full test and is what the table above shows. The two pairs
89
- measure different label sets, so a figure from one never belongs beside a figure
90
- from the other. The rules were not tuned against this test
91
- vocabulary; `scripts/robustness.py` in the code repository reports both figures.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  ## Results
94
 
@@ -153,12 +202,14 @@ task can no longer move the split in another.
153
  | --- | --- | --- |
154
  | Correct answers | 8,120 | 8,120 |
155
  | Accuracy (micro) | 0.7994 | 0.7994 |
156
- | Fitted temperature on these rows | 1.995 | 1.541 |
157
- | ECE after each model's own temperature | 0.0185 | 0.0188 |
158
 
159
  Accuracy does not depend on the temperature, so it is reported on all 10,157 decisions rather than on a split half. The two releases land on the same count: 8,120 correct out of 10,157 each. They do not get the same rows right. They disagree on 1,680 of them, 840 where only v1.1 is right and 840 where only v1.3 is. One standard error on the difference is 0.0056, and the difference is +0.0000.
160
 
161
- The temperature and ECE rows are the mean over 25 random half-splits, fitting on one half and scoring the other. v1.3 needs a lower temperature in 25 of 25 splits, with the two ranges not overlapping (1.92 to 2.10 against 1.47 to 1.60), so its raw scores are genuinely less overconfident. The ECE that remains after each model gets its own temperature is the same for both: the difference averages +0.0004 and runs from -0.0146 to +0.0096, favouring v1.3 in 12 of 25 splits. An earlier version of this card reported 0.0172 against 0.0160 from a single fixed split and called v1.3 better calibrated here. On a different split the sign flips, so that claim is withdrawn.
 
 
162
 
163
  | Task | v1.1 | v1.3 | n |
164
  | --- | --- | --- | --- |
@@ -287,19 +338,29 @@ disturb the order, so nothing here should be assumed to carry over to it.
287
 
288
  ## Speed on CPU
289
 
290
- Apple M4, 4 threads, float32, median of 25 runs:
 
 
291
 
292
- | Decision | Latency |
293
- | --- | --- |
294
- | Short yes/no | 25 ms |
295
- | Choice from three options | 31 ms |
296
- | Full 256-token context | 131 ms |
 
 
 
 
 
 
 
297
 
298
  ## Usage
299
 
300
  ```python
301
  import json, torch, torch.nn as nn
302
  from huggingface_hub import hf_hub_download
 
303
  from transformers import AutoModel, AutoTokenizer
304
 
305
  REPO = "besktech/ru-jev"
@@ -311,7 +372,7 @@ class Scorer(nn.Module):
311
  self.backbone = AutoModel.from_pretrained(repo)
312
  self.head = nn.Linear(self.backbone.config.hidden_size, 1)
313
  self.head.load_state_dict(
314
- torch.load(hf_hub_download(repo, "head.pt"), map_location="cpu"))
315
 
316
  def forward(self, ids, mask):
317
  cls = self.backbone(input_ids=ids, attention_mask=mask).last_hidden_state[:, 0]
@@ -353,7 +414,9 @@ That check exists because an earlier run silently trained on eleven.
353
 
354
  ## License
355
 
356
- MIT, weights and code.
 
 
357
 
358
  Vladimir Beskorovainyi, Enterprise AI Architect & CTO, author of the Amazon
359
  bestseller "Enterprise AI: The KATA Way", founder of Besk Tech (besk.tech)
 
31
  runs on CPU and can be deployed inside a closed perimeter.
32
 
33
  - Project page: https://ru-jev.besk.tech
34
+ - Demo with precomputed examples: https://huggingface.co/spaces/besktech/ru-jev-demo
35
  - Training and evaluation code: https://github.com/beskvladimir-create/ru-jev
36
 
37
  Earlier releases are kept on branches: `v1.1` and `v1`. Load one with
 
65
  tasks that includes the English key written in Cyrillic and a clipped form of
66
  it, generated by rule.
67
 
68
+ The same 1,000 routing questions were then asked over and over with the label
69
+ wording varied and nothing else. Two candidate-set sizes are reported, because
70
+ the gap depends on the size in different ways for different vocabularies and a
71
+ probe at one size alone can misstate the effect: five candidates drawn from the
72
+ eighteen categories, which is what earlier versions of this card reported, and
73
+ all eighteen candidates at once. Chance is 0.20 and 0.056.
74
+
75
+ | Option wording, example for `weather` | Status | v1.1, 5 | v1.3, 5 | v1.1, 18 | v1.3, 18 |
76
+ | --- | --- | --- | --- | --- | --- |
77
+ | Russian word, `погода` | training style, both releases | 0.956 | 0.960 | 0.883 | 0.892 |
78
+ | English key, `weather` | training style, both releases | 0.957 | 0.962 | 0.894 | 0.900 |
79
+ | Russian phrase, `прогноз погоды` | training style, v1.3 only | 0.881 | 0.957 | 0.703 | 0.885 |
80
+ | Descriptive sentence | held out | 0.939 | 0.958 | 0.848 | 0.878 |
81
+ | Department name, `метеослужба` | held out | 0.835 | 0.869 | 0.632 | 0.733 |
82
+ | Anglicism jargon, `вэзер`, all 18 labels | held out | 0.633 | 0.855 | 0.431 | 0.640 |
83
+ | Anglicism jargon, 15 clean labels | held out | 0.624 | 0.838 | 0.427 | 0.595 |
84
+ | Anglicism jargon, 11 strict labels | held out | 0.550 | 0.786 | 0.328 | 0.470 |
85
+ | Office slang, `синоптик`, all 18 | held out | 0.648 | 0.780 | 0.428 | 0.476 |
86
+ | Office slang, 14 strict labels | held out | 0.595 | 0.761 | 0.369 | 0.419 |
87
+ | Abbreviation, `ПОГ`, 17 clean labels | held out | 0.420 | 0.360 | not scored | |
88
+ | Opaque code, `ПГД`, 9 strict labels | held out | 0.135 | 0.168 | 0.018 | 0.061 |
89
+ | Code identifier, `WEATHER_SCN` | contains the trained key | 0.856 | 0.889 | not scored | |
90
+
91
+ **The first two rows are controls, not results.** The Russian word and the
92
+ English key are the wordings both releases trained on: the bench vocabulary for
93
+ them is the training style itself, taken from the same table in the data
94
+ builder. Those two rows measure recall of a trained form, and the gap near zero
95
+ is what a control should show. The Russian phrase is a training style for v1.3
96
+ and not for v1.1, so its gap is expected by construction and is not evidence of
97
+ robustness either. Only the rows marked held out speak to generalisation.
98
+
99
+ Two caveats on the held-out rows. An intent key begins with its scenario name,
100
+ so three of the eighteen jargon labels coincide with what the transliteration
101
+ rule produces and reach training as a first word; the clean slice drops those
102
+ three and the strict slice drops every label with any exact or prefix relation
103
+ to a training option. The rules were not tuned against this test vocabulary, and
104
+ the vocabulary is the older of the two: it was committed six hours and
105
+ thirty-four minutes before the rules. Figures from different slices measure
106
+ different label sets, so one never belongs beside another.
107
+
108
+ **What the augmentation helps with.** Training a label in several surface forms
109
+ helps on held-out wordings made of words, ordinary or borrowed, including kinds
110
+ of words that were never in training at all: jargon gains +0.235 with five
111
+ candidates and +0.142 with eighteen on the strict slice, office slang +0.166 and
112
+ +0.050, department names +0.034 and +0.101, descriptive sentences +0.019 and
113
+ +0.030. The direction is the same in all fourteen word-vocabulary cells.
114
+
115
+ **What it does not help with.** On three-letter abbreviations v1.3 is not better:
116
+ -0.024 on all labels and -0.060 on the clean slice. Opaque codes are unreadable
117
+ for both releases, with v1.1 below chance and v1.3 at chance on the strict slice
118
+ with eighteen candidates. Code identifiers such as `WEATHER_SCN` contain the
119
+ trained key and are easy for both, so they are not treated as a test of
120
+ robustness. Where the label string carries little of its meaning, several
121
+ surface forms in training buy nothing.
122
+
123
+ **Confidence does not follow accuracy here.** With five candidates the count of
124
+ confident errors falls on jargon, from 110 to 62 per 1,000 on the strict slice.
125
+ With eighteen it rises, on jargon from 79 to 109 on all labels and on slang from
126
+ 151 to 191 on the strict slice, because the augmented release is more confident
127
+ overall and more of its errors cross the 0.8 threshold. On abbreviations it
128
+ rises from 77 to 118. The augmentation does not by itself make confidence safer
129
+ on unfamiliar wording. A deployment that invents its own label vocabulary should
130
+ refit the temperature on its own decisions; `scripts/fit_temperature.py` in the
131
+ code repository does that on a few hundred rows and reports whether there were
132
+ enough of them.
133
+
134
+ Significance is exact McNemar on the paired questions with a Holm correction
135
+ over the 23 held-out cells, and the interval resamples labels before questions.
136
+ The five-candidate columns for slang and opaque codes are obtained by
137
+ renormalising the eighteen-candidate scores over the same five candidates the
138
+ main bench uses, which is exact for Ru-Jev because every candidate is scored in
139
+ its own pass. Raw counts, per-label tables and the analysis script are in the
140
+ code repository under `results/analysis/`.
141
 
142
  ## Results
143
 
 
202
  | --- | --- | --- |
203
  | Correct answers | 8,120 | 8,120 |
204
  | Accuracy (micro) | 0.7994 | 0.7994 |
205
+ | Fitted temperature on these rows | 2.0054 | 1.5593 |
206
+ | ECE after each model's own temperature | 0.0190 | 0.0191 |
207
 
208
  Accuracy does not depend on the temperature, so it is reported on all 10,157 decisions rather than on a split half. The two releases land on the same count: 8,120 correct out of 10,157 each. They do not get the same rows right. They disagree on 1,680 of them, 840 where only v1.1 is right and 840 where only v1.3 is. One standard error on the difference is 0.0056, and the difference is +0.0000.
209
 
210
+ The temperature and ECE rows are the mean over 25 random half-splits, fitting on one half and scoring the other. v1.3 needs a lower temperature in 25 of 25 splits, with the two ranges not overlapping (1.942 to 2.098 against 1.500 to 1.604), so its raw scores are genuinely less overconfident. The ECE that remains after each model gets its own temperature is the same for both: the difference averages +0.0001 and runs from -0.0063 to +0.0109, favouring v1.3 in 14 of 25 splits. An earlier version of this card reported 0.0172 against 0.0160 from a single fixed split and called v1.3 better calibrated here. On a different split the sign flips, so that claim is withdrawn.
211
+
212
+ The split seed is recorded as `SPLIT_SEED = 20261105` in `scripts/calib.py`. An earlier implementation shuffled its index list in place without resetting it between splits, so each split was applied to the permutation left by the previous one and the result depended on the order of rows in the file. These figures come from the corrected code; the shift it caused is in the third decimal and turns over nothing.
213
 
214
  | Task | v1.1 | v1.3 | n |
215
  | --- | --- | --- | --- |
 
338
 
339
  ## Speed on CPU
340
 
341
+ Apple M4, float32, median of 25 runs after 5 warm-up runs, nothing else running
342
+ on the machine. Latency is the whole decision: tokenisation, the forward passes
343
+ and the softmax.
344
 
345
+ | Candidates | Ru-Jev v1.3 | Laya | Ratio |
346
+ | --- | --- | --- | --- |
347
+ | 2 | 18.5 ms | 15.5 ms | 1.19 |
348
+ | 5 | 32.8 ms | 17.8 ms | 1.84 |
349
+ | 18 | 73.8 ms | 30.5 ms | 2.42 |
350
+
351
+ Ru-Jev scores each (context, option) pair in its own forward pass, so the cost
352
+ of a decision grows linearly with the number of candidates, by roughly 4 ms per
353
+ candidate on this machine. That is also why option order is not an input to it.
354
+ Laya reads all options in one pass, so its cost is almost flat in the number of
355
+ candidates and order is an input. Ru-Jev is slower in both settings and no
356
+ speed advantage is claimed here.
357
 
358
  ## Usage
359
 
360
  ```python
361
  import json, torch, torch.nn as nn
362
  from huggingface_hub import hf_hub_download
363
+ from safetensors.torch import load_file
364
  from transformers import AutoModel, AutoTokenizer
365
 
366
  REPO = "besktech/ru-jev"
 
372
  self.backbone = AutoModel.from_pretrained(repo)
373
  self.head = nn.Linear(self.backbone.config.hidden_size, 1)
374
  self.head.load_state_dict(
375
+ load_file(hf_hub_download(repo, "head.safetensors")))
376
 
377
  def forward(self, ids, mask):
378
  cls = self.backbone(input_ids=ids, attention_mask=mask).last_hidden_state[:, 0]
 
414
 
415
  ## License
416
 
417
+ MIT covers the code and the weights. The training data keeps the licences of
418
+ its sources, which are listed task by task in `DATASETS.md` in the code
419
+ repository.
420
 
421
  Vladimir Beskorovainyi, Enterprise AI Architect & CTO, author of the Amazon
422
  bestseller "Enterprise AI: The KATA Way", founder of Besk Tech (besk.tech)
head.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:724740455841c6c4c14ff53489b8c9e3956952d2cbf32ab1884b1f0855508bcf
3
+ size 3244