9mark9 commited on
Commit
5e7bf77
·
verified ·
1 Parent(s): 8192fa9

Add DeBERTa-v3-large financial sentiment model, card, training and scoring scripts

Browse files
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nagizaaz Shaik
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language: en
3
+ license: mit
4
+ library_name: transformers
5
+ pipeline_tag: text-classification
6
+ base_model: microsoft/deberta-v3-large
7
+ tags:
8
+ - financial-sentiment
9
+ - finance
10
+ - sentiment-analysis
11
+ - text-classification
12
+ - deberta-v3
13
+ datasets:
14
+ - takala/financial_phrasebank
15
+ - zeroshot/twitter-financial-news-sentiment
16
+ - Jean-Baptiste/financial_news_sentiment
17
+ metrics:
18
+ - accuracy
19
+ - f1
20
+ model-index:
21
+ - name: finbert-deberta-large-sentiment
22
+ results:
23
+ - task:
24
+ type: text-classification
25
+ name: Financial Sentiment Classification
26
+ dataset:
27
+ name: Financial PhraseBank (Sentences_AllAgree)
28
+ type: takala/financial_phrasebank
29
+ config: sentences_allagree
30
+ metrics:
31
+ - type: accuracy
32
+ value: 0.9941
33
+ name: Test Accuracy
34
+ - type: f1
35
+ value: 0.9928
36
+ name: Test Macro-F1
37
+ - task:
38
+ type: text-classification
39
+ name: Financial Sentiment Classification
40
+ dataset:
41
+ name: Twitter Financial News Sentiment
42
+ type: zeroshot/twitter-financial-news-sentiment
43
+ split: validation
44
+ metrics:
45
+ - type: accuracy
46
+ value: 0.9016
47
+ name: Validation Accuracy
48
+ - type: f1
49
+ value: 0.8793
50
+ name: Validation Macro-F1
51
+ - task:
52
+ type: text-classification
53
+ name: Financial Sentiment Classification
54
+ dataset:
55
+ name: Jean-Baptiste financial news sentiment (headlines)
56
+ type: Jean-Baptiste/financial_news_sentiment
57
+ split: test
58
+ metrics:
59
+ - type: accuracy
60
+ value: 0.7828
61
+ name: Test Accuracy
62
+ - type: f1
63
+ value: 0.6137
64
+ name: Test Macro-F1
65
+ - task:
66
+ type: text-classification
67
+ name: Financial Sentiment Classification
68
+ dataset:
69
+ name: SEntFiN headlines (unanimous, test split)
70
+ type: tasksource/sentfin
71
+ split: test
72
+ metrics:
73
+ - type: accuracy
74
+ value: 0.7974
75
+ name: Test Accuracy
76
+ - type: f1
77
+ value: 0.8030
78
+ name: Test Macro-F1
79
+ widget:
80
+ - text: "The company reported record quarterly profit, beating analyst expectations."
81
+ - text: "Net sales decreased by 12% and the firm warned of further losses ahead."
82
+ - text: "The board will meet next Tuesday to review the quarterly schedule."
83
+ ---
84
+
85
+ # finbert-deberta-large-sentiment
86
+
87
+ **A larger, more accurate sibling of [finbert-minilm-sentiment](https://huggingface.co/9mark9/finbert-minilm-sentiment): 90.2% on finance tweets (+3.7 points), 99.4% on PhraseBank test, at 13x the parameters and about 19x the CPU latency.**
88
+
89
+ `finbert-deberta-large-sentiment` classifies short financial text into **negative / neutral / positive**.
90
+ It is `microsoft/deberta-v3-large` (435M parameters) fine-tuned with the same data mix as the compact
91
+ model (v3): Financial PhraseBank, finance tweets and press-release headlines. Use it when accuracy
92
+ matters more than speed. For CPU serving at scale the 33.4M-parameter compact model is still the
93
+ better trade (see [Size and speed](#size-and-speed)).
94
+
95
+ ## Results (held-out sets)
96
+
97
+ None of these sets was used for training or for choosing the model. Differences are against v3
98
+ (`9mark9/finbert-minilm-sentiment`), with paired bootstrap 95% intervals (2,000 resamples of the same
99
+ rows for both models). All numbers are for this repository's weights loaded in fp32.
100
+
101
+ | Set | n | v3 accuracy | This model | Change (points) [95% CI] | v3 macro-F1 | This model | Change [95% CI] |
102
+ |-----|---|-------------|------------|--------------------------|-------------|------------|-----------------|
103
+ | PhraseBank `AllAgree` test (15%) | 340 | 97.94 | **99.41** | +1.47 [+0.00, +3.24] | 96.43 | **99.28** | +2.85 [+0.28, +5.97] |
104
+ | Finance tweets, validation file | 2,388 | 86.43 | **90.16** | +3.73 [+2.47, +5.07] | 83.00 | **87.93** | +4.94 [+3.36, +6.57] |
105
+ | Press-release headlines (JB), test | 267 | 75.28 | **78.28** | +3.00 [-2.25, +8.24] | 59.04 | **61.37** | +2.33 [-9.45, +14.79] |
106
+ | SEntFiN headlines, test (one label per headline) | 933 | 75.99 | **79.74** | +3.75 [+1.29, +6.22] | 76.27 | **80.30** | +4.03 [+1.53, +6.51] |
107
+
108
+ Per-class precision / recall (negative, neutral, positive):
109
+
110
+ | Set | v3 precision | v3 recall | This model precision | This model recall |
111
+ |-----|--------------|-----------|----------------------|-------------------|
112
+ | PhraseBank | 0.953 / 1.000 / 0.944 | 0.911 / 0.990 / 0.988 | 0.978 / 1.000 / 0.989 | 1.000 / 0.990 / 1.000 |
113
+ | Tweets | 0.725 / 0.946 / 0.752 | 0.850 / 0.870 / 0.857 | 0.831 / 0.947 / 0.819 | 0.879 / 0.908 / 0.897 |
114
+ | JB headlines | 0.667 / 0.764 / 0.733 | 0.167 / 0.853 / 0.667 | 0.667 / 0.794 / 0.766 | 0.167 / 0.865 / 0.727 |
115
+ | SEntFiN | 0.850 / 0.676 / 0.811 | 0.722 / 0.825 / 0.723 | 0.891 / 0.696 / 0.866 | 0.792 / 0.836 / 0.762 |
116
+
117
+ Datasets and splits: PhraseBank `Sentences_AllAgree`, stratified 70/15/15 with
118
+ `train_test_split(random_state=42)` (test carved first). Tweets: `zeroshot/twitter-financial-news-sentiment`
119
+ `sent_valid.csv` (labels 0 bearish, 1 bullish, 2 neutral). JB: `Jean-Baptiste/financial_news_sentiment`
120
+ test split, headline text (0 negative, 1 neutral, 2 positive). SEntFiN: `tasksource/sentfin` test split
121
+ (revision d6294b7), headlines where every entity has the same label. All revisions are pinned in
122
+ `training/common.py`.
123
+
124
+ ## Release rule
125
+
126
+ Fixed before training started: release a new repository only if tweet accuracy beats v3 by at least
127
+ 2.0 points with a paired 95% interval entirely above zero, and PhraseBank accuracy is not more than
128
+ 1.0 point worse. Result: +3.73 [+2.47, +5.07] on tweets and +1.47 on PhraseBank, so it passes.
129
+
130
+ ### How this model was chosen
131
+
132
+ Every candidate was ranked by the mean macro-F1 over three validation slices carved from the
133
+ training files (PhraseBank validation split, 10% of the tweet training file, 10% of the headline
134
+ training file). The held-out sets above were scored for every candidate but not used to choose.
135
+
136
+ One change was made during the search, and it is stated here. Once this model was trained, a
137
+ probability-average ensemble containing it ranked slightly higher on validation (by 0.0005). A
138
+ tie-break rule was added at that point, after this model's own held-out scores had been seen, but
139
+ before roberta-large had finished and before any ensemble containing this model had been scored on
140
+ the held-out sets. The rule: an ensemble wins only if it leads the best single model on validation by at
141
+ least 0.005, because it costs at least 1.5x the CPU time for a gap inside validation noise. The final
142
+ top ensemble (this model + roberta-large + v3, 0.8772) led this model (0.8751) by 0.0021, so the single
143
+ model was kept. For transparency, that ensemble scored 99.12 / 90.12 / 79.03 / 80.92 on the four sets
144
+ (tweets +3.69 [+2.51, +4.94]), about the same as this model.
145
+
146
+ ### All candidates
147
+
148
+ Accuracy on the held-out sets; validation = mean macro-F1 over the three validation slices.
149
+ `ens_*` = average of class probabilities. Runs marked (Mac) were trained on an Apple GPU in fp32,
150
+ the others on a ZeroGPU Space with bf16 autocast.
151
+
152
+ | Candidate | Params | Validation | PhraseBank | Tweets | JB | SEntFiN | Tweets vs v3 [95% CI] |
153
+ |-----------|--------|------------|------------|--------|----|---------|-----------------------|
154
+ | v3 (finbert-minilm-sentiment) | 33.4M | 0.8239 | 97.94 | 86.43 | 75.28 | 75.99 | - |
155
+ | deberta-v3-base, seed 42 | 184.4M | 0.8650 | 99.12 | 88.61 | 80.15 | 79.96 | +2.18 [+0.96, +3.48] |
156
+ | deberta-v3-base, seed 1 | 184.4M | 0.8486 | 99.41 | 87.48 | 77.90 | 79.31 | +1.05 [-0.21, +2.35] |
157
+ | deberta-v3-base, seed 2 | 184.4M | 0.8500 | 98.82 | 86.64 | 74.91 | 80.39 | +0.21 [-1.09, +1.55] |
158
+ | deberta-v3-base, weight average of the 3 seeds | 184.4M | 0.8375 | 98.53 | 83.88 | 78.65 | 80.60 | -2.55 [-3.94, -1.17] |
159
+ | roberta-base, seed 42 (Mac) | 124.6M | 0.8463 | 99.41 | 88.32 | 68.91 | 80.17 | +1.88 [+0.63, +3.22] |
160
+ | roberta-base, seed 1 | 124.6M | 0.8421 | 99.41 | 88.86 | 72.28 | 77.17 | +2.43 [+1.13, +3.73] |
161
+ | distilroberta-base, seed 42 (Mac) | 82.1M | 0.8389 | 97.94 | 87.56 | 77.53 | 75.99 | +1.13 [-0.21, +2.43] |
162
+ | ProsusAI/finbert, seed 42 (Mac) * | 109.5M | 0.8283 | 99.71 | 87.23 | 72.66 | 75.88 | +0.80 [-0.50, +2.05] |
163
+ | roberta-large, seed 42 | 355.4M | 0.8617 | 98.82 | 86.77 | 78.28 | 80.71 | +0.34 [-1.01, +1.84] |
164
+ | **deberta-v3-large, seed 42 (this model)** | 435.1M | 0.8751 | 99.41 | 90.16 | 78.28 | 79.74 | +3.73 [+2.47, +5.07] |
165
+ | ens: deberta-v3-base s42 + s1 + v3 | 402.2M | 0.8700 | 99.41 | 88.74 | 77.53 | 80.39 | +2.30 [+1.17, +3.52] |
166
+ | ens: deberta-v3-large + roberta-large + v3 | 823.8M | 0.8772 | 99.12 | 90.12 | 79.03 | 80.92 | +3.69 [+2.51, +4.94] |
167
+ | ens: deberta-v3-large + deberta-v3-base s2 + v3 | 652.9M | 0.8756 | 99.12 | 90.62 | 79.40 | 80.28 | +4.19 [+2.97, +5.40] |
168
+
169
+ \* ProsusAI/finbert is CC-BY-NC-SA-4.0 and was itself fine-tuned on Financial PhraseBank, so its
170
+ PhraseBank score is not a clean held-out number; it was a reference only.
171
+
172
+ Seeds matter: three deberta-v3-base seeds span 86.6 to 88.6 on tweets. deberta-v3-large was trained
173
+ with one seed only, so part of its margin may be seed luck.
174
+
175
+ ## Size and speed
176
+
177
+ CPU latency per sentence, batch size 1, 4 threads, median (90th percentile) over 300 tweets after 20
178
+ warm-up calls, fp32, measured on a shared cloud CPU (absolute numbers vary by machine; ratios are
179
+ the useful part):
180
+
181
+ | Model | Parameters | Weights (fp32) | CPU latency | Tweets accuracy |
182
+ |-------|------------|----------------|-------------|-----------------|
183
+ | finbert-minilm-sentiment (v3) | 33.4M | 0.13 GB | 13.5 ms (18.5) | 86.43 |
184
+ | deberta-v3-base fine-tune (seed 42) | 184.4M | 0.74 GB | 83.6 ms (104.9) | 88.61 |
185
+ | roberta-large fine-tune | 355.4M | 1.4 GB | 127.3 ms (155.6) | 86.77 |
186
+ | **this model** | 435.1M | 1.7 GB | 259.3 ms (301.2) | 90.16 |
187
+
188
+ ## How far can tweet accuracy go? (label-noise estimate)
189
+
190
+ This model gets 235 of the 2,388 validation tweets wrong. I read 100 of those errors, drawn at
191
+ random (seed 0), and judged each one against the text:
192
+
193
+ | Judgement | Count |
194
+ |-----------|-------|
195
+ | Gold label looks wrong; the model's label fits the text better | 32 |
196
+ | Genuinely ambiguous (either label defensible) | 29 |
197
+ | Clear model error (gold label is right) | 39 |
198
+
199
+ Examples of the first kind: "Margins suffer at Ituran Location in Q3" (gold neutral, model negative),
200
+ "iAnthus Defaults On Debt" (gold neutral), "Howard Bancorp Shareholders Have Enjoyed A 54% Share
201
+ Price Gain" (gold neutral, model positive), "U.S. oil firms vented or flared record amount of gas"
202
+ (gold bullish).
203
+
204
+ If a model fixed every clear error and nothing else, it would reach about **94.0%** (95% interval
205
+ 93.1% to 95.0%, from the Wilson interval on 39/100). Going past that means agreeing with labels that look
206
+ wrong or with coin-flip judgements, which is fitting the annotators, not the sentiment. So 95% or more on
207
+ this tweet set is not a realistic honest target. This is one reviewer's judgement, made while seeing
208
+ the model's prediction, so treat it as an estimate.
209
+
210
+ ## Training data
211
+
212
+ Held out and never used for training or model selection: the PhraseBank 15% test split, the full
213
+ tweet validation file, the headline test split and all of SEntFiN. Before training, any row whose text
214
+ matches a held-out or validation row was dropped. The match key is lower-cased text with URLs and
215
+ punctuation removed. 111 rows were dropped.
216
+
217
+ Note on v3: v3 deduplicated on lower-cased, whitespace-normalised text only. With the stricter key, 80
218
+ rows of the tweet training file and 8 rows of the headline training file match held-out text (for
219
+ example the same headline with a different link). v3 was trained with those rows; this model was not.
220
+
221
+ | Source | Used for training | Used for validation |
222
+ |--------|-------------------|---------------------|
223
+ | PhraseBank `Sentences_AllAgree` | 70% train split (1,584), repeated 3x per epoch | 15% validation split (340) |
224
+ | PhraseBank `Sentences_66Agree` | only sentences not in the all-agree file at all (1,951); majority label | - |
225
+ | Tweets, `sent_train.csv` | 90% stratified (8,588) | 10% stratified (955) |
226
+ | Headlines (JB), train split | 90% stratified (1,360), repeated 2x per epoch | 10% stratified (152) |
227
+
228
+ 17,900 training rows per epoch after deduplication. Dataset licences apply to the data.
229
+
230
+ ## Training details
231
+
232
+ | Setting | Value |
233
+ |---------|-------|
234
+ | Base encoder | `microsoft/deberta-v3-large` (MIT) |
235
+ | Parameters | 435,064,835 |
236
+ | Objective | class-weighted cross-entropy (inverse class frequency) |
237
+ | Optimizer | AdamW, lr 1e-5, weight decay 0.01, gradient clip 1.0 |
238
+ | Schedule | linear, 10% warmup; batch 16; max 96 tokens; 3 epochs (3,357 steps) |
239
+ | Precision | fp32 weights, bf16 autocast for the forward pass |
240
+ | Checkpoint | best mean validation macro-F1, evaluated twice per epoch (step 3,354) |
241
+ | Hardware | Hugging Face ZeroGPU (half of an RTX Pro 6000), 481 GPU-seconds |
242
+
243
+ The learning rate (1e-5 for the large encoders, 2e-5 for base, 3e-5 for distilroberta) was fixed
244
+ before training, not tuned.
245
+
246
+ ## Reproduce
247
+
248
+ `training/` holds the code that produced and scored this model: `app.py` (a Gradio app for a
249
+ ZeroGPU Space: `train_chunk`, `evaluate`, `latency`, `soup`), `common.py` (data loading at pinned
250
+ revisions, dedupe key, splits), `requirements.txt`, `drive.py` (client that calls the Space) and
251
+ `analyze.py` (accuracy, macro-F1, per-class precision/recall, paired bootstrap against v3).
252
+
253
+ 1. Create a Gradio Space with ZeroGPU hardware, add `app.py`, `common.py` and `requirements.txt`, and
254
+ set a write token as the secret `HF_TOKEN` (used to push checkpoints to private repos).
255
+ 2. Point `SPACE` in `drive.py` at it, then run:
256
+
257
+ ```bash
258
+ mkdir -p probs
259
+ python drive.py train debL_s42 '{"base":"microsoft/deberta-v3-large","lr":1e-5,"pb_extra":"66Agree","jb_rep":2,"seed":42,"gpu_seconds":600,"margin":80}' 2
260
+ python drive.py eval debL_s42_fp32 <your-user>/tmp-train-debL_s42 best:fp32 probs/debL_s42_fp32.npz
261
+ python drive.py eval v3 9mark9/finbert-minilm-sentiment - probs/v3.npz
262
+ python analyze.py results.json v3 debL_s42_fp32
263
+ ```
264
+
265
+ GPU training is not bit-for-bit deterministic, so a rerun lands close to, not exactly on, these numbers.
266
+
267
+ ## Usage
268
+
269
+ ```python
270
+ import torch
271
+ from transformers import AutoModelForSequenceClassification, AutoTokenizer
272
+
273
+ model_id = "9mark9/finbert-deberta-large-sentiment"
274
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
275
+ model = AutoModelForSequenceClassification.from_pretrained(model_id)
276
+ model.eval()
277
+
278
+ texts = [
279
+ "The company reported record quarterly profit, beating analyst expectations.",
280
+ "Net sales decreased by 12% and the firm warned of further losses ahead.",
281
+ "The board will meet next Tuesday to review the quarterly schedule.",
282
+ ]
283
+
284
+ enc = tokenizer(texts, padding=True, truncation=True, max_length=96, return_tensors="pt")
285
+ with torch.no_grad():
286
+ probs = model(**enc).logits.softmax(-1)
287
+
288
+ for text, p in zip(texts, probs):
289
+ label = model.config.id2label[int(p.argmax())]
290
+ print(f"[{label:8s} {p.max():.2f}] {text}")
291
+ ```
292
+
293
+ Tested with `torch` 2.8, `transformers` 4.x and `sentencepiece` installed. The three example
294
+ sentences come out positive, negative and neutral.
295
+
296
+ ## Intended use
297
+
298
+ - Sentiment scoring of **short financial text**: news sentences, headlines, finance tweets, analyst notes.
299
+ - Research and offline or GPU batch scoring where accuracy matters more than latency.
300
+
301
+ ## Limitations
302
+
303
+ - English only. Max sequence length 96 tokens; longer text is truncated.
304
+ - **Weak on negative press-release headlines**: it finds 2 of the 12 negatives in the JB test split,
305
+ the same as v3. On the larger SEntFiN set (259 negatives) negative recall is 0.792.
306
+ - On finance tweets about 17% of the tweets it calls negative are labelled neutral or bullish.
307
+ - Tweet labels have a noise ceiling (see above); about 94% is a realistic upper bound on that set.
308
+ - PhraseBank `AllAgree` is the cleanest, easiest part of that benchmark; expect lower accuracy on
309
+ ambiguous sentences.
310
+ - Tweet labels describe bullish / bearish market direction, which is not the same as the tone of a
311
+ sentence. The model mixes both conventions.
312
+ - About 19x slower than the compact model on CPU.
313
+ - Not financial advice. Outputs are sentiment labels, not buy/sell signals.
314
+
315
+ ## Citation
316
+
317
+ Dataset:
318
+
319
+ ```bibtex
320
+ @article{malo2014good,
321
+ title={Good debt or bad debt: Detecting semantic orientations in economic texts},
322
+ author={Malo, Pekka and Sinha, Ankur and Korhonen, Pekka and Wallenius, Jyrki and Takala, Pyry},
323
+ journal={Journal of the Association for Information Science and Technology},
324
+ volume={65}, number={4}, pages={782--796}, year={2014}
325
+ }
326
+ ```
327
+
328
+ ## Contact
329
+
330
+ Maintainer: nagizaazs@gmail.com
331
+
332
+ ## License
333
+
334
+ MIT
added_tokens.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ {
2
+ "[MASK]": 128000
3
+ }
config.json ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "DebertaV2ForSequenceClassification"
4
+ ],
5
+ "attention_probs_dropout_prob": 0.1,
6
+ "dtype": "float32",
7
+ "hidden_act": "gelu",
8
+ "hidden_dropout_prob": 0.1,
9
+ "hidden_size": 1024,
10
+ "id2label": {
11
+ "0": "negative",
12
+ "1": "neutral",
13
+ "2": "positive"
14
+ },
15
+ "initializer_range": 0.02,
16
+ "intermediate_size": 4096,
17
+ "label2id": {
18
+ "negative": 0,
19
+ "neutral": 1,
20
+ "positive": 2
21
+ },
22
+ "layer_norm_eps": 1e-07,
23
+ "legacy": true,
24
+ "max_position_embeddings": 512,
25
+ "max_relative_positions": -1,
26
+ "model_type": "deberta-v2",
27
+ "norm_rel_ebd": "layer_norm",
28
+ "num_attention_heads": 16,
29
+ "num_hidden_layers": 24,
30
+ "pad_token_id": 0,
31
+ "pooler_dropout": 0,
32
+ "pooler_hidden_act": "gelu",
33
+ "pooler_hidden_size": 1024,
34
+ "pos_att_type": [
35
+ "p2c",
36
+ "c2p"
37
+ ],
38
+ "position_biased_input": false,
39
+ "position_buckets": 256,
40
+ "relative_attention": true,
41
+ "share_att_key": true,
42
+ "transformers_version": "4.57.6",
43
+ "type_vocab_size": 0,
44
+ "vocab_size": 128100
45
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:dba5705c2a3e00e979426826596f6febd25c5c24d2e2b2b83250c860a238d7b1
3
+ size 1740308548
results.json ADDED
@@ -0,0 +1,1663 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "candidates": {
3
+ "v3": {
4
+ "spec": "v3",
5
+ "params": 33361155,
6
+ "val_mean_mf1": 0.8239,
7
+ "val_tw_acc": 0.8524,
8
+ "phrasebank_test": {
9
+ "acc": 97.94,
10
+ "mf1": 96.43,
11
+ "d_acc": 0.0,
12
+ "d_acc_ci": [
13
+ 0.0,
14
+ 0.0
15
+ ],
16
+ "d_mf1": 0.0,
17
+ "d_mf1_ci": [
18
+ 0.0,
19
+ 0.0
20
+ ],
21
+ "P": [
22
+ 0.953,
23
+ 1.0,
24
+ 0.944
25
+ ],
26
+ "R": [
27
+ 0.911,
28
+ 0.99,
29
+ 0.988
30
+ ]
31
+ },
32
+ "twitter_valid": {
33
+ "acc": 86.43,
34
+ "mf1": 83.0,
35
+ "d_acc": 0.0,
36
+ "d_acc_ci": [
37
+ 0.0,
38
+ 0.0
39
+ ],
40
+ "d_mf1": 0.0,
41
+ "d_mf1_ci": [
42
+ 0.0,
43
+ 0.0
44
+ ],
45
+ "P": [
46
+ 0.725,
47
+ 0.946,
48
+ 0.752
49
+ ],
50
+ "R": [
51
+ 0.85,
52
+ 0.87,
53
+ 0.857
54
+ ]
55
+ },
56
+ "jb_test": {
57
+ "acc": 75.28,
58
+ "mf1": 59.04,
59
+ "d_acc": 0.0,
60
+ "d_acc_ci": [
61
+ 0.0,
62
+ 0.0
63
+ ],
64
+ "d_mf1": 0.0,
65
+ "d_mf1_ci": [
66
+ 0.0,
67
+ 0.0
68
+ ],
69
+ "P": [
70
+ 0.667,
71
+ 0.764,
72
+ 0.733
73
+ ],
74
+ "R": [
75
+ 0.167,
76
+ 0.853,
77
+ 0.667
78
+ ]
79
+ },
80
+ "sentfin_test": {
81
+ "acc": 75.99,
82
+ "mf1": 76.27,
83
+ "d_acc": 0.0,
84
+ "d_acc_ci": [
85
+ 0.0,
86
+ 0.0
87
+ ],
88
+ "d_mf1": 0.0,
89
+ "d_mf1_ci": [
90
+ 0.0,
91
+ 0.0
92
+ ],
93
+ "P": [
94
+ 0.85,
95
+ 0.676,
96
+ 0.811
97
+ ],
98
+ "R": [
99
+ 0.722,
100
+ 0.825,
101
+ 0.723
102
+ ]
103
+ }
104
+ },
105
+ "deb_s42": {
106
+ "spec": "deb_s42",
107
+ "params": 184424451,
108
+ "val_mean_mf1": 0.865,
109
+ "val_tw_acc": 0.8639,
110
+ "phrasebank_test": {
111
+ "acc": 99.12,
112
+ "mf1": 99.01,
113
+ "d_acc": 1.18,
114
+ "d_acc_ci": [
115
+ -0.29,
116
+ 2.94
117
+ ],
118
+ "d_mf1": 2.58,
119
+ "d_mf1_ci": [
120
+ 0.09,
121
+ 5.62
122
+ ],
123
+ "P": [
124
+ 0.978,
125
+ 1.0,
126
+ 0.977
127
+ ],
128
+ "R": [
129
+ 1.0,
130
+ 0.986,
131
+ 1.0
132
+ ]
133
+ },
134
+ "twitter_valid": {
135
+ "acc": 88.61,
136
+ "mf1": 86.34,
137
+ "d_acc": 2.18,
138
+ "d_acc_ci": [
139
+ 0.96,
140
+ 3.48
141
+ ],
142
+ "d_mf1": 3.34,
143
+ "d_mf1_ci": [
144
+ 1.77,
145
+ 5.02
146
+ ],
147
+ "P": [
148
+ 0.815,
149
+ 0.948,
150
+ 0.772
151
+ ],
152
+ "R": [
153
+ 0.865,
154
+ 0.883,
155
+ 0.914
156
+ ]
157
+ },
158
+ "jb_test": {
159
+ "acc": 80.15,
160
+ "mf1": 62.1,
161
+ "d_acc": 4.87,
162
+ "d_acc_ci": [
163
+ 0.37,
164
+ 9.36
165
+ ],
166
+ "d_mf1": 3.07,
167
+ "d_mf1_ci": [
168
+ -7.61,
169
+ 14.44
170
+ ],
171
+ "P": [
172
+ 0.4,
173
+ 0.831,
174
+ 0.775
175
+ ],
176
+ "R": [
177
+ 0.167,
178
+ 0.853,
179
+ 0.798
180
+ ]
181
+ },
182
+ "sentfin_test": {
183
+ "acc": 79.96,
184
+ "mf1": 80.25,
185
+ "d_acc": 3.97,
186
+ "d_acc_ci": [
187
+ 1.29,
188
+ 6.32
189
+ ],
190
+ "d_mf1": 3.98,
191
+ "d_mf1_ci": [
192
+ 1.37,
193
+ 6.27
194
+ ],
195
+ "P": [
196
+ 0.873,
197
+ 0.726,
198
+ 0.834
199
+ ],
200
+ "R": [
201
+ 0.772,
202
+ 0.804,
203
+ 0.816
204
+ ]
205
+ }
206
+ },
207
+ "deb_s1": {
208
+ "spec": "deb_s1",
209
+ "params": 184424451,
210
+ "val_mean_mf1": 0.8486,
211
+ "val_tw_acc": 0.8377,
212
+ "phrasebank_test": {
213
+ "acc": 99.41,
214
+ "mf1": 99.28,
215
+ "d_acc": 1.47,
216
+ "d_acc_ci": [
217
+ -0.29,
218
+ 3.24
219
+ ],
220
+ "d_mf1": 2.85,
221
+ "d_mf1_ci": [
222
+ 0.24,
223
+ 5.99
224
+ ],
225
+ "P": [
226
+ 0.978,
227
+ 0.995,
228
+ 1.0
229
+ ],
230
+ "R": [
231
+ 1.0,
232
+ 0.995,
233
+ 0.988
234
+ ]
235
+ },
236
+ "twitter_valid": {
237
+ "acc": 87.48,
238
+ "mf1": 84.93,
239
+ "d_acc": 1.05,
240
+ "d_acc_ci": [
241
+ -0.21,
242
+ 2.35
243
+ ],
244
+ "d_mf1": 1.94,
245
+ "d_mf1_ci": [
246
+ 0.4,
247
+ 3.55
248
+ ],
249
+ "P": [
250
+ 0.7,
251
+ 0.951,
252
+ 0.818
253
+ ],
254
+ "R": [
255
+ 0.916,
256
+ 0.863,
257
+ 0.882
258
+ ]
259
+ },
260
+ "jb_test": {
261
+ "acc": 77.9,
262
+ "mf1": 65.34,
263
+ "d_acc": 2.62,
264
+ "d_acc_ci": [
265
+ -1.87,
266
+ 7.12
267
+ ],
268
+ "d_mf1": 6.3,
269
+ "d_mf1_ci": [
270
+ -0.4,
271
+ 14.95
272
+ ],
273
+ "P": [
274
+ 1.0,
275
+ 0.809,
276
+ 0.725
277
+ ],
278
+ "R": [
279
+ 0.25,
280
+ 0.84,
281
+ 0.747
282
+ ]
283
+ },
284
+ "sentfin_test": {
285
+ "acc": 79.31,
286
+ "mf1": 79.65,
287
+ "d_acc": 3.32,
288
+ "d_acc_ci": [
289
+ 0.96,
290
+ 5.79
291
+ ],
292
+ "d_mf1": 3.37,
293
+ "d_mf1_ci": [
294
+ 1.02,
295
+ 5.8
296
+ ],
297
+ "P": [
298
+ 0.793,
299
+ 0.722,
300
+ 0.885
301
+ ],
302
+ "R": [
303
+ 0.846,
304
+ 0.781,
305
+ 0.765
306
+ ]
307
+ }
308
+ },
309
+ "deb_s2": {
310
+ "spec": "deb_s2",
311
+ "params": 184424451,
312
+ "val_mean_mf1": 0.85,
313
+ "val_tw_acc": 0.8366,
314
+ "phrasebank_test": {
315
+ "acc": 98.82,
316
+ "mf1": 98.74,
317
+ "d_acc": 0.88,
318
+ "d_acc_ci": [
319
+ -0.59,
320
+ 2.65
321
+ ],
322
+ "d_mf1": 2.31,
323
+ "d_mf1_ci": [
324
+ -0.18,
325
+ 5.37
326
+ ],
327
+ "P": [
328
+ 0.978,
329
+ 1.0,
330
+ 0.966
331
+ ],
332
+ "R": [
333
+ 1.0,
334
+ 0.981,
335
+ 1.0
336
+ ]
337
+ },
338
+ "twitter_valid": {
339
+ "acc": 86.64,
340
+ "mf1": 84.27,
341
+ "d_acc": 0.21,
342
+ "d_acc_ci": [
343
+ -1.09,
344
+ 1.55
345
+ ],
346
+ "d_mf1": 1.27,
347
+ "d_mf1_ci": [
348
+ -0.3,
349
+ 2.94
350
+ ],
351
+ "P": [
352
+ 0.728,
353
+ 0.955,
354
+ 0.755
355
+ ],
356
+ "R": [
357
+ 0.911,
358
+ 0.846,
359
+ 0.901
360
+ ]
361
+ },
362
+ "jb_test": {
363
+ "acc": 74.91,
364
+ "mf1": 58.68,
365
+ "d_acc": -0.37,
366
+ "d_acc_ci": [
367
+ -5.24,
368
+ 4.12
369
+ ],
370
+ "d_mf1": -0.36,
371
+ "d_mf1_ci": [
372
+ -4.67,
373
+ 3.33
374
+ ],
375
+ "P": [
376
+ 0.4,
377
+ 0.824,
378
+ 0.675
379
+ ],
380
+ "R": [
381
+ 0.167,
382
+ 0.75,
383
+ 0.818
384
+ ]
385
+ },
386
+ "sentfin_test": {
387
+ "acc": 80.39,
388
+ "mf1": 80.55,
389
+ "d_acc": 4.39,
390
+ "d_acc_ci": [
391
+ 1.82,
392
+ 6.97
393
+ ],
394
+ "d_mf1": 4.28,
395
+ "d_mf1_ci": [
396
+ 1.79,
397
+ 6.85
398
+ ],
399
+ "P": [
400
+ 0.835,
401
+ 0.753,
402
+ 0.833
403
+ ],
404
+ "R": [
405
+ 0.803,
406
+ 0.766,
407
+ 0.843
408
+ ]
409
+ }
410
+ },
411
+ "deb_soup3": {
412
+ "spec": "deb_soup3",
413
+ "params": 184424451,
414
+ "val_mean_mf1": 0.8375,
415
+ "val_tw_acc": 0.8031,
416
+ "phrasebank_test": {
417
+ "acc": 98.53,
418
+ "mf1": 98.3,
419
+ "d_acc": 0.59,
420
+ "d_acc_ci": [
421
+ -1.18,
422
+ 2.35
423
+ ],
424
+ "d_mf1": 1.87,
425
+ "d_mf1_ci": [
426
+ -0.82,
427
+ 5.04
428
+ ],
429
+ "P": [
430
+ 0.957,
431
+ 1.0,
432
+ 0.966
433
+ ],
434
+ "R": [
435
+ 1.0,
436
+ 0.976,
437
+ 1.0
438
+ ]
439
+ },
440
+ "twitter_valid": {
441
+ "acc": 83.88,
442
+ "mf1": 81.55,
443
+ "d_acc": -2.55,
444
+ "d_acc_ci": [
445
+ -3.94,
446
+ -1.17
447
+ ],
448
+ "d_mf1": -1.45,
449
+ "d_mf1_ci": [
450
+ -3.02,
451
+ 0.2
452
+ ],
453
+ "P": [
454
+ 0.632,
455
+ 0.966,
456
+ 0.742
457
+ ],
458
+ "R": [
459
+ 0.939,
460
+ 0.793,
461
+ 0.916
462
+ ]
463
+ },
464
+ "jb_test": {
465
+ "acc": 78.65,
466
+ "mf1": 64.37,
467
+ "d_acc": 3.37,
468
+ "d_acc_ci": [
469
+ -0.76,
470
+ 7.49
471
+ ],
472
+ "d_mf1": 5.33,
473
+ "d_mf1_ci": [
474
+ -1.01,
475
+ 13.48
476
+ ],
477
+ "P": [
478
+ 0.5,
479
+ 0.854,
480
+ 0.718
481
+ ],
482
+ "R": [
483
+ 0.25,
484
+ 0.788,
485
+ 0.848
486
+ ]
487
+ },
488
+ "sentfin_test": {
489
+ "acc": 80.6,
490
+ "mf1": 80.68,
491
+ "d_acc": 4.61,
492
+ "d_acc_ci": [
493
+ 1.93,
494
+ 7.4
495
+ ],
496
+ "d_mf1": 4.41,
497
+ "d_mf1_ci": [
498
+ 1.72,
499
+ 7.12
500
+ ],
501
+ "P": [
502
+ 0.792,
503
+ 0.793,
504
+ 0.828
505
+ ],
506
+ "R": [
507
+ 0.884,
508
+ 0.696,
509
+ 0.858
510
+ ]
511
+ }
512
+ },
513
+ "rob_s42": {
514
+ "spec": "rob_s42",
515
+ "params": 124647939,
516
+ "val_mean_mf1": 0.8463,
517
+ "val_tw_acc": 0.8618,
518
+ "phrasebank_test": {
519
+ "acc": 99.41,
520
+ "mf1": 99.28,
521
+ "d_acc": 1.47,
522
+ "d_acc_ci": [
523
+ -0.29,
524
+ 3.24
525
+ ],
526
+ "d_mf1": 2.85,
527
+ "d_mf1_ci": [
528
+ 0.19,
529
+ 6.08
530
+ ],
531
+ "P": [
532
+ 0.978,
533
+ 1.0,
534
+ 0.989
535
+ ],
536
+ "R": [
537
+ 1.0,
538
+ 0.99,
539
+ 1.0
540
+ ]
541
+ },
542
+ "twitter_valid": {
543
+ "acc": 88.32,
544
+ "mf1": 85.91,
545
+ "d_acc": 1.88,
546
+ "d_acc_ci": [
547
+ 0.63,
548
+ 3.22
549
+ ],
550
+ "d_mf1": 2.92,
551
+ "d_mf1_ci": [
552
+ 1.36,
553
+ 4.55
554
+ ],
555
+ "P": [
556
+ 0.774,
557
+ 0.959,
558
+ 0.769
559
+ ],
560
+ "R": [
561
+ 0.896,
562
+ 0.872,
563
+ 0.909
564
+ ]
565
+ },
566
+ "jb_test": {
567
+ "acc": 68.91,
568
+ "mf1": 54.97,
569
+ "d_acc": -6.37,
570
+ "d_acc_ci": [
571
+ -11.61,
572
+ -1.12
573
+ ],
574
+ "d_mf1": -4.07,
575
+ "d_mf1_ci": [
576
+ -15.56,
577
+ 7.66
578
+ ],
579
+ "P": [
580
+ 0.5,
581
+ 0.789,
582
+ 0.592
583
+ ],
584
+ "R": [
585
+ 0.167,
586
+ 0.673,
587
+ 0.778
588
+ ]
589
+ },
590
+ "sentfin_test": {
591
+ "acc": 80.17,
592
+ "mf1": 80.51,
593
+ "d_acc": 4.18,
594
+ "d_acc_ci": [
595
+ 1.61,
596
+ 6.65
597
+ ],
598
+ "d_mf1": 4.24,
599
+ "d_mf1_ci": [
600
+ 1.7,
601
+ 6.62
602
+ ],
603
+ "P": [
604
+ 0.879,
605
+ 0.737,
606
+ 0.818
607
+ ],
608
+ "R": [
609
+ 0.788,
610
+ 0.787,
611
+ 0.828
612
+ ]
613
+ }
614
+ },
615
+ "rob_s1": {
616
+ "spec": "rob_s1",
617
+ "params": 124647939,
618
+ "val_mean_mf1": 0.8421,
619
+ "val_tw_acc": 0.8743,
620
+ "phrasebank_test": {
621
+ "acc": 99.41,
622
+ "mf1": 98.99,
623
+ "d_acc": 1.47,
624
+ "d_acc_ci": [
625
+ -0.29,
626
+ 3.24
627
+ ],
628
+ "d_mf1": 2.56,
629
+ "d_mf1_ci": [
630
+ -0.32,
631
+ 5.81
632
+ ],
633
+ "P": [
634
+ 0.978,
635
+ 1.0,
636
+ 0.989
637
+ ],
638
+ "R": [
639
+ 0.978,
640
+ 0.995,
641
+ 1.0
642
+ ]
643
+ },
644
+ "twitter_valid": {
645
+ "acc": 88.86,
646
+ "mf1": 85.98,
647
+ "d_acc": 2.43,
648
+ "d_acc_ci": [
649
+ 1.13,
650
+ 3.73
651
+ ],
652
+ "d_mf1": 2.98,
653
+ "d_mf1_ci": [
654
+ 1.35,
655
+ 4.6
656
+ ],
657
+ "P": [
658
+ 0.825,
659
+ 0.925,
660
+ 0.82
661
+ ],
662
+ "R": [
663
+ 0.83,
664
+ 0.915,
665
+ 0.844
666
+ ]
667
+ },
668
+ "jb_test": {
669
+ "acc": 72.28,
670
+ "mf1": 59.7,
671
+ "d_acc": -3.0,
672
+ "d_acc_ci": [
673
+ -7.87,
674
+ 1.87
675
+ ],
676
+ "d_mf1": 0.66,
677
+ "d_mf1_ci": [
678
+ -12.13,
679
+ 13.68
680
+ ],
681
+ "P": [
682
+ 0.5,
683
+ 0.781,
684
+ 0.655
685
+ ],
686
+ "R": [
687
+ 0.25,
688
+ 0.756,
689
+ 0.727
690
+ ]
691
+ },
692
+ "sentfin_test": {
693
+ "acc": 77.17,
694
+ "mf1": 77.6,
695
+ "d_acc": 1.18,
696
+ "d_acc_ci": [
697
+ -1.29,
698
+ 3.54
699
+ ],
700
+ "d_mf1": 1.33,
701
+ "d_mf1_ci": [
702
+ -1.05,
703
+ 3.65
704
+ ],
705
+ "P": [
706
+ 0.889,
707
+ 0.658,
708
+ 0.862
709
+ ],
710
+ "R": [
711
+ 0.714,
712
+ 0.851,
713
+ 0.735
714
+ ]
715
+ }
716
+ },
717
+ "drob_s42": {
718
+ "spec": "drob_s42",
719
+ "params": 82120707,
720
+ "val_mean_mf1": 0.8389,
721
+ "val_tw_acc": 0.8586,
722
+ "phrasebank_test": {
723
+ "acc": 97.94,
724
+ "mf1": 97.49,
725
+ "d_acc": 0.0,
726
+ "d_acc_ci": [
727
+ -1.76,
728
+ 1.76
729
+ ],
730
+ "d_mf1": 1.06,
731
+ "d_mf1_ci": [
732
+ -1.8,
733
+ 4.39
734
+ ],
735
+ "P": [
736
+ 0.938,
737
+ 1.0,
738
+ 0.955
739
+ ],
740
+ "R": [
741
+ 1.0,
742
+ 0.971,
743
+ 0.988
744
+ ]
745
+ },
746
+ "twitter_valid": {
747
+ "acc": 87.56,
748
+ "mf1": 84.57,
749
+ "d_acc": 1.13,
750
+ "d_acc_ci": [
751
+ -0.21,
752
+ 2.43
753
+ ],
754
+ "d_mf1": 1.57,
755
+ "d_mf1_ci": [
756
+ -0.05,
757
+ 3.27
758
+ ],
759
+ "P": [
760
+ 0.781,
761
+ 0.932,
762
+ 0.78
763
+ ],
764
+ "R": [
765
+ 0.844,
766
+ 0.89,
767
+ 0.853
768
+ ]
769
+ },
770
+ "jb_test": {
771
+ "acc": 77.53,
772
+ "mf1": 62.67,
773
+ "d_acc": 2.25,
774
+ "d_acc_ci": [
775
+ -1.87,
776
+ 6.37
777
+ ],
778
+ "d_mf1": 3.63,
779
+ "d_mf1_ci": [
780
+ -3.03,
781
+ 12.43
782
+ ],
783
+ "P": [
784
+ 0.429,
785
+ 0.784,
786
+ 0.787
787
+ ],
788
+ "R": [
789
+ 0.25,
790
+ 0.859,
791
+ 0.707
792
+ ]
793
+ },
794
+ "sentfin_test": {
795
+ "acc": 75.99,
796
+ "mf1": 76.39,
797
+ "d_acc": 0.0,
798
+ "d_acc_ci": [
799
+ -2.36,
800
+ 2.14
801
+ ],
802
+ "d_mf1": 0.12,
803
+ "d_mf1_ci": [
804
+ -2.2,
805
+ 2.21
806
+ ],
807
+ "P": [
808
+ 0.851,
809
+ 0.659,
810
+ 0.842
811
+ ],
812
+ "R": [
813
+ 0.726,
814
+ 0.825,
815
+ 0.72
816
+ ]
817
+ }
818
+ },
819
+ "fin_s42": {
820
+ "spec": "fin_s42",
821
+ "params": 109484547,
822
+ "val_mean_mf1": 0.8283,
823
+ "val_tw_acc": 0.8545,
824
+ "phrasebank_test": {
825
+ "acc": 99.71,
826
+ "mf1": 99.55,
827
+ "d_acc": 1.76,
828
+ "d_acc_ci": [
829
+ 0.59,
830
+ 3.24
831
+ ],
832
+ "d_mf1": 3.12,
833
+ "d_mf1_ci": [
834
+ 0.99,
835
+ 5.96
836
+ ],
837
+ "P": [
838
+ 0.978,
839
+ 1.0,
840
+ 1.0
841
+ ],
842
+ "R": [
843
+ 1.0,
844
+ 0.995,
845
+ 1.0
846
+ ]
847
+ },
848
+ "twitter_valid": {
849
+ "acc": 87.23,
850
+ "mf1": 83.85,
851
+ "d_acc": 0.8,
852
+ "d_acc_ci": [
853
+ -0.5,
854
+ 2.05
855
+ ],
856
+ "d_mf1": 0.86,
857
+ "d_mf1_ci": [
858
+ -0.75,
859
+ 2.43
860
+ ],
861
+ "P": [
862
+ 0.751,
863
+ 0.927,
864
+ 0.801
865
+ ],
866
+ "R": [
867
+ 0.85,
868
+ 0.895,
869
+ 0.815
870
+ ]
871
+ },
872
+ "jb_test": {
873
+ "acc": 72.66,
874
+ "mf1": 57.64,
875
+ "d_acc": -2.62,
876
+ "d_acc_ci": [
877
+ -7.12,
878
+ 1.87
879
+ ],
880
+ "d_mf1": -1.39,
881
+ "d_mf1_ci": [
882
+ -8.38,
883
+ 7.06
884
+ ],
885
+ "P": [
886
+ 0.273,
887
+ 0.756,
888
+ 0.727
889
+ ],
890
+ "R": [
891
+ 0.25,
892
+ 0.814,
893
+ 0.646
894
+ ]
895
+ },
896
+ "sentfin_test": {
897
+ "acc": 75.88,
898
+ "mf1": 76.2,
899
+ "d_acc": -0.11,
900
+ "d_acc_ci": [
901
+ -2.36,
902
+ 2.14
903
+ ],
904
+ "d_mf1": -0.07,
905
+ "d_mf1_ci": [
906
+ -2.34,
907
+ 2.16
908
+ ],
909
+ "P": [
910
+ 0.87,
911
+ 0.641,
912
+ 0.886
913
+ ],
914
+ "R": [
915
+ 0.699,
916
+ 0.883,
917
+ 0.678
918
+ ]
919
+ }
920
+ },
921
+ "ens_deb42_deb1_v3": {
922
+ "spec": "deb_s42+deb_s1+v3",
923
+ "params": 402210057,
924
+ "val_mean_mf1": 0.87,
925
+ "val_tw_acc": 0.8639,
926
+ "phrasebank_test": {
927
+ "acc": 99.41,
928
+ "mf1": 99.28,
929
+ "d_acc": 1.47,
930
+ "d_acc_ci": [
931
+ 0.0,
932
+ 2.94
933
+ ],
934
+ "d_mf1": 2.85,
935
+ "d_mf1_ci": [
936
+ 0.28,
937
+ 5.79
938
+ ],
939
+ "P": [
940
+ 0.978,
941
+ 1.0,
942
+ 0.989
943
+ ],
944
+ "R": [
945
+ 1.0,
946
+ 0.99,
947
+ 1.0
948
+ ]
949
+ },
950
+ "twitter_valid": {
951
+ "acc": 88.74,
952
+ "mf1": 86.38,
953
+ "d_acc": 2.3,
954
+ "d_acc_ci": [
955
+ 1.17,
956
+ 3.52
957
+ ],
958
+ "d_mf1": 3.38,
959
+ "d_mf1_ci": [
960
+ 1.99,
961
+ 4.87
962
+ ],
963
+ "P": [
964
+ 0.753,
965
+ 0.954,
966
+ 0.812
967
+ ],
968
+ "R": [
969
+ 0.914,
970
+ 0.88,
971
+ 0.893
972
+ ]
973
+ },
974
+ "jb_test": {
975
+ "acc": 77.53,
976
+ "mf1": 60.59,
977
+ "d_acc": 2.25,
978
+ "d_acc_ci": [
979
+ -1.5,
980
+ 5.99
981
+ ],
982
+ "d_mf1": 1.56,
983
+ "d_mf1_ci": [
984
+ -1.58,
985
+ 4.64
986
+ ],
987
+ "P": [
988
+ 0.5,
989
+ 0.811,
990
+ 0.731
991
+ ],
992
+ "R": [
993
+ 0.167,
994
+ 0.827,
995
+ 0.768
996
+ ]
997
+ },
998
+ "sentfin_test": {
999
+ "acc": 80.39,
1000
+ "mf1": 80.64,
1001
+ "d_acc": 4.39,
1002
+ "d_acc_ci": [
1003
+ 2.14,
1004
+ 6.54
1005
+ ],
1006
+ "d_mf1": 4.37,
1007
+ "d_mf1_ci": [
1008
+ 2.16,
1009
+ 6.55
1010
+ ],
1011
+ "P": [
1012
+ 0.824,
1013
+ 0.733,
1014
+ 0.874
1015
+ ],
1016
+ "R": [
1017
+ 0.815,
1018
+ 0.804,
1019
+ 0.795
1020
+ ]
1021
+ }
1022
+ },
1023
+ "ens_deb42_deb1": {
1024
+ "spec": "deb_s42+deb_s1",
1025
+ "params": 368848902,
1026
+ "val_mean_mf1": 0.868,
1027
+ "val_tw_acc": 0.8597,
1028
+ "phrasebank_test": {
1029
+ "acc": 99.41,
1030
+ "mf1": 99.28,
1031
+ "d_acc": 1.47,
1032
+ "d_acc_ci": [
1033
+ 0.0,
1034
+ 2.94
1035
+ ],
1036
+ "d_mf1": 2.85,
1037
+ "d_mf1_ci": [
1038
+ 0.28,
1039
+ 5.79
1040
+ ],
1041
+ "P": [
1042
+ 0.978,
1043
+ 1.0,
1044
+ 0.989
1045
+ ],
1046
+ "R": [
1047
+ 1.0,
1048
+ 0.99,
1049
+ 1.0
1050
+ ]
1051
+ },
1052
+ "twitter_valid": {
1053
+ "acc": 88.44,
1054
+ "mf1": 86.06,
1055
+ "d_acc": 2.01,
1056
+ "d_acc_ci": [
1057
+ 0.79,
1058
+ 3.23
1059
+ ],
1060
+ "d_mf1": 3.06,
1061
+ "d_mf1_ci": [
1062
+ 1.6,
1063
+ 4.62
1064
+ ],
1065
+ "P": [
1066
+ 0.74,
1067
+ 0.954,
1068
+ 0.812
1069
+ ],
1070
+ "R": [
1071
+ 0.916,
1072
+ 0.875,
1073
+ 0.893
1074
+ ]
1075
+ },
1076
+ "jb_test": {
1077
+ "acc": 77.15,
1078
+ "mf1": 56.62,
1079
+ "d_acc": 1.87,
1080
+ "d_acc_ci": [
1081
+ -2.25,
1082
+ 5.99
1083
+ ],
1084
+ "d_mf1": -2.42,
1085
+ "d_mf1_ci": [
1086
+ -11.75,
1087
+ 4.21
1088
+ ],
1089
+ "P": [
1090
+ 0.333,
1091
+ 0.806,
1092
+ 0.731
1093
+ ],
1094
+ "R": [
1095
+ 0.083,
1096
+ 0.827,
1097
+ 0.768
1098
+ ]
1099
+ },
1100
+ "sentfin_test": {
1101
+ "acc": 79.96,
1102
+ "mf1": 80.24,
1103
+ "d_acc": 3.97,
1104
+ "d_acc_ci": [
1105
+ 1.71,
1106
+ 6.11
1107
+ ],
1108
+ "d_mf1": 3.97,
1109
+ "d_mf1_ci": [
1110
+ 1.64,
1111
+ 6.15
1112
+ ],
1113
+ "P": [
1114
+ 0.819,
1115
+ 0.729,
1116
+ 0.87
1117
+ ],
1118
+ "R": [
1119
+ 0.819,
1120
+ 0.795,
1121
+ 0.789
1122
+ ]
1123
+ }
1124
+ },
1125
+ "ens_deb3_v3": {
1126
+ "spec": "deb_s42+deb_s2+deb_s1+v3",
1127
+ "params": 586634508,
1128
+ "val_mean_mf1": 0.8664,
1129
+ "val_tw_acc": 0.8597,
1130
+ "phrasebank_test": {
1131
+ "acc": 99.12,
1132
+ "mf1": 99.01,
1133
+ "d_acc": 1.18,
1134
+ "d_acc_ci": [
1135
+ -0.29,
1136
+ 2.94
1137
+ ],
1138
+ "d_mf1": 2.58,
1139
+ "d_mf1_ci": [
1140
+ 0.09,
1141
+ 5.62
1142
+ ],
1143
+ "P": [
1144
+ 0.978,
1145
+ 1.0,
1146
+ 0.977
1147
+ ],
1148
+ "R": [
1149
+ 1.0,
1150
+ 0.986,
1151
+ 1.0
1152
+ ]
1153
+ },
1154
+ "twitter_valid": {
1155
+ "acc": 88.69,
1156
+ "mf1": 86.41,
1157
+ "d_acc": 2.26,
1158
+ "d_acc_ci": [
1159
+ 1.09,
1160
+ 3.52
1161
+ ],
1162
+ "d_mf1": 3.41,
1163
+ "d_mf1_ci": [
1164
+ 2.0,
1165
+ 4.91
1166
+ ],
1167
+ "P": [
1168
+ 0.751,
1169
+ 0.957,
1170
+ 0.806
1171
+ ],
1172
+ "R": [
1173
+ 0.914,
1174
+ 0.875,
1175
+ 0.907
1176
+ ]
1177
+ },
1178
+ "jb_test": {
1179
+ "acc": 77.15,
1180
+ "mf1": 60.02,
1181
+ "d_acc": 1.87,
1182
+ "d_acc_ci": [
1183
+ -1.87,
1184
+ 5.62
1185
+ ],
1186
+ "d_mf1": 0.98,
1187
+ "d_mf1_ci": [
1188
+ -2.78,
1189
+ 4.26
1190
+ ],
1191
+ "P": [
1192
+ 0.4,
1193
+ 0.814,
1194
+ 0.726
1195
+ ],
1196
+ "R": [
1197
+ 0.167,
1198
+ 0.814,
1199
+ 0.778
1200
+ ]
1201
+ },
1202
+ "sentfin_test": {
1203
+ "acc": 79.74,
1204
+ "mf1": 80.03,
1205
+ "d_acc": 3.75,
1206
+ "d_acc_ci": [
1207
+ 1.5,
1208
+ 5.89
1209
+ ],
1210
+ "d_mf1": 3.76,
1211
+ "d_mf1_ci": [
1212
+ 1.52,
1213
+ 5.91
1214
+ ],
1215
+ "P": [
1216
+ 0.824,
1217
+ 0.726,
1218
+ 0.864
1219
+ ],
1220
+ "R": [
1221
+ 0.811,
1222
+ 0.798,
1223
+ 0.786
1224
+ ]
1225
+ }
1226
+ },
1227
+ "debL_s42": {
1228
+ "spec": "debL_s42_fp32",
1229
+ "params": 435064835,
1230
+ "val_mean_mf1": 0.8751,
1231
+ "val_tw_acc": 0.8901,
1232
+ "phrasebank_test": {
1233
+ "acc": 99.41,
1234
+ "mf1": 99.28,
1235
+ "d_acc": 1.47,
1236
+ "d_acc_ci": [
1237
+ 0.0,
1238
+ 3.24
1239
+ ],
1240
+ "d_mf1": 2.85,
1241
+ "d_mf1_ci": [
1242
+ 0.28,
1243
+ 5.97
1244
+ ],
1245
+ "P": [
1246
+ 0.978,
1247
+ 1.0,
1248
+ 0.989
1249
+ ],
1250
+ "R": [
1251
+ 1.0,
1252
+ 0.99,
1253
+ 1.0
1254
+ ]
1255
+ },
1256
+ "twitter_valid": {
1257
+ "acc": 90.16,
1258
+ "mf1": 87.93,
1259
+ "d_acc": 3.73,
1260
+ "d_acc_ci": [
1261
+ 2.47,
1262
+ 5.07
1263
+ ],
1264
+ "d_mf1": 4.94,
1265
+ "d_mf1_ci": [
1266
+ 3.36,
1267
+ 6.57
1268
+ ],
1269
+ "P": [
1270
+ 0.831,
1271
+ 0.947,
1272
+ 0.819
1273
+ ],
1274
+ "R": [
1275
+ 0.879,
1276
+ 0.908,
1277
+ 0.897
1278
+ ]
1279
+ },
1280
+ "jb_test": {
1281
+ "acc": 78.28,
1282
+ "mf1": 61.37,
1283
+ "d_acc": 3.0,
1284
+ "d_acc_ci": [
1285
+ -2.25,
1286
+ 8.24
1287
+ ],
1288
+ "d_mf1": 2.33,
1289
+ "d_mf1_ci": [
1290
+ -9.45,
1291
+ 14.79
1292
+ ],
1293
+ "P": [
1294
+ 0.667,
1295
+ 0.794,
1296
+ 0.766
1297
+ ],
1298
+ "R": [
1299
+ 0.167,
1300
+ 0.865,
1301
+ 0.727
1302
+ ]
1303
+ },
1304
+ "sentfin_test": {
1305
+ "acc": 79.74,
1306
+ "mf1": 80.3,
1307
+ "d_acc": 3.75,
1308
+ "d_acc_ci": [
1309
+ 1.29,
1310
+ 6.22
1311
+ ],
1312
+ "d_mf1": 4.03,
1313
+ "d_mf1_ci": [
1314
+ 1.53,
1315
+ 6.51
1316
+ ],
1317
+ "P": [
1318
+ 0.891,
1319
+ 0.696,
1320
+ 0.866
1321
+ ],
1322
+ "R": [
1323
+ 0.792,
1324
+ 0.836,
1325
+ 0.762
1326
+ ]
1327
+ },
1328
+ "note": "this model, fp32 inference"
1329
+ },
1330
+ "robL_s42": {
1331
+ "spec": "robL_s42",
1332
+ "params": 355362819,
1333
+ "val_mean_mf1": 0.8617,
1334
+ "val_tw_acc": 0.8429,
1335
+ "phrasebank_test": {
1336
+ "acc": 98.82,
1337
+ "mf1": 98.57,
1338
+ "d_acc": 0.88,
1339
+ "d_acc_ci": [
1340
+ -0.88,
1341
+ 2.65
1342
+ ],
1343
+ "d_mf1": 2.14,
1344
+ "d_mf1_ci": [
1345
+ -0.57,
1346
+ 5.26
1347
+ ],
1348
+ "P": [
1349
+ 0.957,
1350
+ 1.0,
1351
+ 0.977
1352
+ ],
1353
+ "R": [
1354
+ 1.0,
1355
+ 0.981,
1356
+ 1.0
1357
+ ]
1358
+ },
1359
+ "twitter_valid": {
1360
+ "acc": 86.77,
1361
+ "mf1": 84.81,
1362
+ "d_acc": 0.34,
1363
+ "d_acc_ci": [
1364
+ -1.01,
1365
+ 1.84
1366
+ ],
1367
+ "d_mf1": 1.82,
1368
+ "d_mf1_ci": [
1369
+ 0.21,
1370
+ 3.61
1371
+ ],
1372
+ "P": [
1373
+ 0.711,
1374
+ 0.98,
1375
+ 0.744
1376
+ ],
1377
+ "R": [
1378
+ 0.951,
1379
+ 0.823,
1380
+ 0.954
1381
+ ]
1382
+ },
1383
+ "jb_test": {
1384
+ "acc": 78.28,
1385
+ "mf1": 67.45,
1386
+ "d_acc": 3.0,
1387
+ "d_acc_ci": [
1388
+ -1.5,
1389
+ 7.5
1390
+ ],
1391
+ "d_mf1": 8.41,
1392
+ "d_mf1_ci": [
1393
+ -1.63,
1394
+ 19.11
1395
+ ],
1396
+ "P": [
1397
+ 0.455,
1398
+ 0.838,
1399
+ 0.741
1400
+ ],
1401
+ "R": [
1402
+ 0.417,
1403
+ 0.795,
1404
+ 0.808
1405
+ ]
1406
+ },
1407
+ "sentfin_test": {
1408
+ "acc": 80.71,
1409
+ "mf1": 80.9,
1410
+ "d_acc": 4.72,
1411
+ "d_acc_ci": [
1412
+ 1.82,
1413
+ 7.5
1414
+ ],
1415
+ "d_mf1": 4.62,
1416
+ "d_mf1_ci": [
1417
+ 1.79,
1418
+ 7.37
1419
+ ],
1420
+ "P": [
1421
+ 0.821,
1422
+ 0.783,
1423
+ 0.818
1424
+ ],
1425
+ "R": [
1426
+ 0.865,
1427
+ 0.719,
1428
+ 0.852
1429
+ ]
1430
+ }
1431
+ },
1432
+ "ens_debL_robL_v3": {
1433
+ "spec": "debL_s42+robL_s42+v3",
1434
+ "params": 823788809,
1435
+ "val_mean_mf1": 0.8772,
1436
+ "val_tw_acc": 0.888,
1437
+ "phrasebank_test": {
1438
+ "acc": 99.12,
1439
+ "mf1": 99.01,
1440
+ "d_acc": 1.18,
1441
+ "d_acc_ci": [
1442
+ -0.29,
1443
+ 2.94
1444
+ ],
1445
+ "d_mf1": 2.58,
1446
+ "d_mf1_ci": [
1447
+ 0.09,
1448
+ 5.62
1449
+ ],
1450
+ "P": [
1451
+ 0.978,
1452
+ 1.0,
1453
+ 0.977
1454
+ ],
1455
+ "R": [
1456
+ 1.0,
1457
+ 0.986,
1458
+ 1.0
1459
+ ]
1460
+ },
1461
+ "twitter_valid": {
1462
+ "acc": 90.12,
1463
+ "mf1": 88.19,
1464
+ "d_acc": 3.69,
1465
+ "d_acc_ci": [
1466
+ 2.51,
1467
+ 4.94
1468
+ ],
1469
+ "d_mf1": 5.19,
1470
+ "d_mf1_ci": [
1471
+ 3.76,
1472
+ 6.79
1473
+ ],
1474
+ "P": [
1475
+ 0.808,
1476
+ 0.965,
1477
+ 0.802
1478
+ ],
1479
+ "R": [
1480
+ 0.919,
1481
+ 0.889,
1482
+ 0.928
1483
+ ]
1484
+ },
1485
+ "jb_test": {
1486
+ "acc": 79.03,
1487
+ "mf1": 61.01,
1488
+ "d_acc": 3.75,
1489
+ "d_acc_ci": [
1490
+ -0.75,
1491
+ 8.24
1492
+ ],
1493
+ "d_mf1": 1.97,
1494
+ "d_mf1_ci": [
1495
+ -8.9,
1496
+ 13.14
1497
+ ],
1498
+ "P": [
1499
+ 0.333,
1500
+ 0.815,
1501
+ 0.778
1502
+ ],
1503
+ "R": [
1504
+ 0.167,
1505
+ 0.846,
1506
+ 0.778
1507
+ ]
1508
+ },
1509
+ "sentfin_test": {
1510
+ "acc": 80.92,
1511
+ "mf1": 81.33,
1512
+ "d_acc": 4.93,
1513
+ "d_acc_ci": [
1514
+ 2.68,
1515
+ 7.29
1516
+ ],
1517
+ "d_mf1": 5.06,
1518
+ "d_mf1_ci": [
1519
+ 2.79,
1520
+ 7.33
1521
+ ],
1522
+ "P": [
1523
+ 0.862,
1524
+ 0.729,
1525
+ 0.864
1526
+ ],
1527
+ "R": [
1528
+ 0.822,
1529
+ 0.804,
1530
+ 0.804
1531
+ ]
1532
+ }
1533
+ },
1534
+ "ens_debL_deb2_v3": {
1535
+ "spec": "debL_s42+deb_s2+v3",
1536
+ "params": 652850441,
1537
+ "val_mean_mf1": 0.8756,
1538
+ "val_tw_acc": 0.8817,
1539
+ "phrasebank_test": {
1540
+ "acc": 99.12,
1541
+ "mf1": 99.01,
1542
+ "d_acc": 1.18,
1543
+ "d_acc_ci": [
1544
+ -0.29,
1545
+ 2.94
1546
+ ],
1547
+ "d_mf1": 2.58,
1548
+ "d_mf1_ci": [
1549
+ 0.09,
1550
+ 5.62
1551
+ ],
1552
+ "P": [
1553
+ 0.978,
1554
+ 1.0,
1555
+ 0.977
1556
+ ],
1557
+ "R": [
1558
+ 1.0,
1559
+ 0.986,
1560
+ 1.0
1561
+ ]
1562
+ },
1563
+ "twitter_valid": {
1564
+ "acc": 90.62,
1565
+ "mf1": 88.6,
1566
+ "d_acc": 4.19,
1567
+ "d_acc_ci": [
1568
+ 2.97,
1569
+ 5.4
1570
+ ],
1571
+ "d_mf1": 5.61,
1572
+ "d_mf1_ci": [
1573
+ 4.14,
1574
+ 7.13
1575
+ ],
1576
+ "P": [
1577
+ 0.835,
1578
+ 0.956,
1579
+ 0.817
1580
+ ],
1581
+ "R": [
1582
+ 0.902,
1583
+ 0.906,
1584
+ 0.909
1585
+ ]
1586
+ },
1587
+ "jb_test": {
1588
+ "acc": 79.4,
1589
+ "mf1": 61.84,
1590
+ "d_acc": 4.12,
1591
+ "d_acc_ci": [
1592
+ -0.37,
1593
+ 8.61
1594
+ ],
1595
+ "d_mf1": 2.8,
1596
+ "d_mf1_ci": [
1597
+ -8.47,
1598
+ 14.5
1599
+ ],
1600
+ "P": [
1601
+ 0.5,
1602
+ 0.817,
1603
+ 0.768
1604
+ ],
1605
+ "R": [
1606
+ 0.167,
1607
+ 0.859,
1608
+ 0.768
1609
+ ]
1610
+ },
1611
+ "sentfin_test": {
1612
+ "acc": 80.28,
1613
+ "mf1": 80.68,
1614
+ "d_acc": 4.29,
1615
+ "d_acc_ci": [
1616
+ 2.04,
1617
+ 6.43
1618
+ ],
1619
+ "d_mf1": 4.41,
1620
+ "d_mf1_ci": [
1621
+ 2.23,
1622
+ 6.54
1623
+ ],
1624
+ "P": [
1625
+ 0.872,
1626
+ 0.713,
1627
+ 0.867
1628
+ ],
1629
+ "R": [
1630
+ 0.792,
1631
+ 0.827,
1632
+ 0.786
1633
+ ]
1634
+ }
1635
+ }
1636
+ },
1637
+ "cpu_latency_ms_batch1_4threads": {
1638
+ "v3": [
1639
+ 13.5,
1640
+ 18.5
1641
+ ],
1642
+ "deberta-v3-base_s42": [
1643
+ 83.6,
1644
+ 104.9
1645
+ ],
1646
+ "roberta-large_s42": [
1647
+ 127.3,
1648
+ 155.6
1649
+ ],
1650
+ "this_model": [
1651
+ 259.3,
1652
+ 301.2
1653
+ ]
1654
+ },
1655
+ "tweet_error_audit": {
1656
+ "errors": 235,
1657
+ "sampled": 100,
1658
+ "seed": 0,
1659
+ "gold_wrong": 32,
1660
+ "ambiguous": 29,
1661
+ "model_wrong": 39
1662
+ }
1663
+ }
special_tokens_map.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bos_token": "[CLS]",
3
+ "cls_token": "[CLS]",
4
+ "eos_token": "[SEP]",
5
+ "mask_token": "[MASK]",
6
+ "pad_token": "[PAD]",
7
+ "sep_token": "[SEP]",
8
+ "unk_token": {
9
+ "content": "[UNK]",
10
+ "lstrip": false,
11
+ "normalized": true,
12
+ "rstrip": false,
13
+ "single_word": false
14
+ }
15
+ }
spm.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c679fbf93643d19aab7ee10c0b99e460bdbc02fedf34b92b05af343b4af586fd
3
+ size 2464616
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "added_tokens_decoder": {
3
+ "0": {
4
+ "content": "[PAD]",
5
+ "lstrip": false,
6
+ "normalized": false,
7
+ "rstrip": false,
8
+ "single_word": false,
9
+ "special": true
10
+ },
11
+ "1": {
12
+ "content": "[CLS]",
13
+ "lstrip": false,
14
+ "normalized": false,
15
+ "rstrip": false,
16
+ "single_word": false,
17
+ "special": true
18
+ },
19
+ "2": {
20
+ "content": "[SEP]",
21
+ "lstrip": false,
22
+ "normalized": false,
23
+ "rstrip": false,
24
+ "single_word": false,
25
+ "special": true
26
+ },
27
+ "3": {
28
+ "content": "[UNK]",
29
+ "lstrip": false,
30
+ "normalized": true,
31
+ "rstrip": false,
32
+ "single_word": false,
33
+ "special": true
34
+ },
35
+ "128000": {
36
+ "content": "[MASK]",
37
+ "lstrip": false,
38
+ "normalized": false,
39
+ "rstrip": false,
40
+ "single_word": false,
41
+ "special": true
42
+ }
43
+ },
44
+ "bos_token": "[CLS]",
45
+ "clean_up_tokenization_spaces": false,
46
+ "cls_token": "[CLS]",
47
+ "do_lower_case": false,
48
+ "eos_token": "[SEP]",
49
+ "extra_special_tokens": {},
50
+ "mask_token": "[MASK]",
51
+ "model_max_length": 1000000000000000019884624838656,
52
+ "pad_token": "[PAD]",
53
+ "sep_token": "[SEP]",
54
+ "sp_model_kwargs": {},
55
+ "split_by_punct": false,
56
+ "tokenizer_class": "DebertaV2Tokenizer",
57
+ "unk_token": "[UNK]",
58
+ "vocab_type": "spm"
59
+ }
training/analyze.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Usage: analyze.py out.json name[=a+b+...] ... - scores models (probs/<name>.npz) or probability-averaged
2
+ ensembles on the held-out sets, with paired bootstrap 95% intervals of the difference vs v3."""
3
+ import sys, json
4
+ import numpy as np
5
+ from sklearn.metrics import f1_score, precision_recall_fscore_support
6
+
7
+ HELD = ["phrasebank_test", "twitter_valid", "jb_test", "sentfin_test"]
8
+ VAL = ["val_pb", "val_tw", "val_jb"]
9
+ LAB = ["negative", "neutral", "positive"]
10
+ cache = {}
11
+
12
+
13
+ def load(name):
14
+ if name not in cache:
15
+ cache[name] = dict(np.load(f"probs/{name}.npz"))
16
+ return cache[name]
17
+
18
+
19
+ def probs(spec, k):
20
+ return np.mean([load(m)[k] for m in spec.split("+")], axis=0)
21
+
22
+
23
+ def mf1(g, p):
24
+ return f1_score(g, p, labels=[0, 1, 2], average="macro", zero_division=0)
25
+
26
+
27
+ def paired(g, p, q, n=2000, seed=0):
28
+ """95% percentile intervals of (candidate - v3) accuracy and macro-F1, same resampled rows for both."""
29
+ rng = np.random.default_rng(seed)
30
+ da, df = [], []
31
+ for _ in range(n):
32
+ i = rng.integers(0, len(g), len(g))
33
+ da.append((p[i] == g[i]).mean() - (q[i] == g[i]).mean())
34
+ df.append(mf1(g[i], p[i]) - mf1(g[i], q[i]))
35
+ c = lambda a: [round(float(np.percentile(a, 2.5)) * 100, 2), round(float(np.percentile(a, 97.5)) * 100, 2)]
36
+ return c(da), c(df)
37
+
38
+
39
+ out = {}
40
+ path, specs = sys.argv[1], sys.argv[2:]
41
+ for s in specs:
42
+ name, spec = s.split("=") if "=" in s else (s, s)
43
+ r = {"spec": spec, "params": int(sum(load(m)["params"] for m in spec.split("+")))}
44
+ r["val_mean_mf1"] = round(float(np.mean([mf1(load(spec.split("+")[0])[k + "_gold"], probs(spec, k).argmax(1)) for k in VAL])), 4)
45
+ r["val_tw_acc"] = round(float((probs(spec, "val_tw").argmax(1) == load(spec.split("+")[0])["val_tw_gold"]).mean()), 4)
46
+ for k in HELD:
47
+ g = load("v3")[k + "_gold"]
48
+ p, q = probs(spec, k).argmax(1), load("v3")[k].argmax(1)
49
+ P, R, _, _ = precision_recall_fscore_support(g, p, labels=[0, 1, 2], zero_division=0)
50
+ ca, cf = paired(g, p, q)
51
+ r[k] = {"acc": round(float((p == g).mean()) * 100, 2), "mf1": round(mf1(g, p) * 100, 2),
52
+ "d_acc": round(float((p == g).mean() - (q == g).mean()) * 100, 2), "d_acc_ci": ca,
53
+ "d_mf1": round((mf1(g, p) - mf1(g, q)) * 100, 2), "d_mf1_ci": cf,
54
+ "P": [round(float(x), 3) for x in P], "R": [round(float(x), 3) for x in R]}
55
+ out[name] = r
56
+ print(f"{name:28s} {r['params']/1e6:6.1f}M val {r['val_mean_mf1']:.4f} valtw {r['val_tw_acc']:.4f} | " + " | ".join(
57
+ f"{k[:5]} {r[k]['acc']:.2f} ({r[k]['d_acc']:+.2f} [{r[k]['d_acc_ci'][0]:+.2f},{r[k]['d_acc_ci'][1]:+.2f}]) F1 {r[k]['mf1']:.2f}" for k in HELD), flush=True)
58
+ json.dump(out, open(path, "w"), indent=1)
training/app.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Resumable fine-tuning and held-out scoring for financial-sentiment encoders (private working Space).
2
+ train_chunk trains for at most one GPU call and pushes resumable state to a private model repo; evaluate
3
+ returns class probabilities on the four held-out sets and the three training-derived validation slices."""
4
+ import os, json, time
5
+ import numpy as np, torch, gradio as gr, spaces
6
+ from huggingface_hub import HfApi, snapshot_download
7
+ from transformers import AutoModelForSequenceClassification, AutoTokenizer, get_linear_schedule_with_warmup
8
+ from common import LABELS, L2I, dnorm, carve, phrasebank_split, phrasebank_extra, nosible, twitter, jb, heldout_sets, report
9
+
10
+ TOKEN = os.environ.get("HF_TOKEN")
11
+ api = HfApi(token=TOKEN)
12
+
13
+ # Data is built once at start-up (CPU). Held-out and validation text never enters training.
14
+ HELD = heldout_sets()
15
+ (PBX, PBY), (PBVX, PBVY), _ = phrasebank_split()
16
+ TWX, TWVX, TWY, TWVY = carve(*twitter("train"))
17
+ JBX, JBVX, JBY, JBVY = carve(*jb("train"))
18
+ VAL = {"pb": (PBVX, PBVY), "tw": (TWVX, TWVY), "jb": (JBVX, JBVY)}
19
+ BLOCK = {dnorm(t) for X, _ in list(HELD.values()) + list(VAL.values()) for t in X}
20
+ # Fetch base weights at start-up so downloads are not billed as GPU time.
21
+ for _b in os.environ.get("PRELOAD", "microsoft/deberta-v3-base,FacebookAI/roberta-base").split(","):
22
+ snapshot_download(_b, ignore_patterns=["*.h5", "*.msgpack", "*.ot", "onnx/*", "tf_*", "flax_*", "rust_*"])
23
+
24
+
25
+ def build_train(c):
26
+ exX, exy = phrasebank_extra(c["pb_extra"]) if c.get("pb_extra") else ([], [])
27
+ nsX, nsy = nosible(c["nosible"]) if c.get("nosible") else ([], [])
28
+ raw = (list(zip(PBX, PBY)) * c.get("pb_rep", 3) + list(zip(TWX, TWY)) + list(zip(JBX, JBY)) * c.get("jb_rep", 1)
29
+ + list(zip(exX, exy)) * c.get("extra_rep", 1) + list(zip(nsX, nsy)))
30
+ return [(t, l) for t, l in raw if dnorm(t) not in BLOCK], len(raw)
31
+
32
+
33
+ @torch.no_grad()
34
+ def probs(model, tok, texts, bs=128, amp=True):
35
+ model.eval()
36
+ order = [{v.lower(): int(k) for k, v in model.config.id2label.items()}[l] for l in LABELS]
37
+ out = []
38
+ for i in range(0, len(texts), bs):
39
+ enc = tok(texts[i:i + bs], padding=True, truncation=True, max_length=96, return_tensors="pt").to("cuda")
40
+ with torch.autocast("cuda", dtype=torch.bfloat16, enabled=amp):
41
+ out.append(model(**enc).logits.float().softmax(-1)[:, order].cpu().numpy())
42
+ return np.concatenate(out)
43
+
44
+
45
+ def _train_dur(config_json, resume_repo):
46
+ return int(json.loads(config_json).get("gpu_seconds", 120))
47
+
48
+
49
+ @spaces.GPU(duration=_train_dur)
50
+ def _train_gpu(config_json, resume_repo):
51
+ t0 = time.time()
52
+ c = json.loads(config_json)
53
+ budget = c.get("gpu_seconds", 120) - c.get("margin", 45)
54
+ work = f"/tmp/runs/{c['run']}"
55
+ seed, bs, epochs = c.get("seed", 42), c.get("bs", 16), c.get("epochs", 3)
56
+ torch.manual_seed(seed)
57
+ train, n_raw = build_train(c)
58
+ tok = AutoTokenizer.from_pretrained(c["base"])
59
+ model = AutoModelForSequenceClassification.from_pretrained(
60
+ c["base"], num_labels=3, id2label=dict(enumerate(LABELS)), label2id=L2I, torch_dtype=torch.float32,
61
+ ignore_mismatched_sizes=True).cuda()
62
+ counts = np.bincount([L2I[l] for _, l in train], minlength=3)
63
+ w = len(train) / (3 * counts)
64
+ loss_fn = torch.nn.CrossEntropyLoss(weight=torch.tensor(w, dtype=torch.float32, device="cuda"), label_smoothing=c.get("ls", 0.0))
65
+ opt = torch.optim.AdamW(model.parameters(), lr=c["lr"], weight_decay=0.01)
66
+ steps_ep = (len(train) + bs - 1) // bs
67
+ total = steps_ep * epochs
68
+ sched = get_linear_schedule_with_warmup(opt, int(c.get("warmup", 0.1) * total), total)
69
+ eval_every = steps_ep // c.get("evals_per_epoch", 2)
70
+ st = {"step": 0, "best": -1.0, "bad": 0, "hist": [], "done": False, "train_rows": len(train), "dropped": n_raw - len(train)}
71
+ if os.path.exists(f"{work}/state.json") and os.path.exists(f"{work}/state.pt"):
72
+ st = json.load(open(f"{work}/state.json"))
73
+ if not st["done"]:
74
+ s = torch.load(f"{work}/state.pt", map_location="cuda", weights_only=False)
75
+ model.load_state_dict(s["model"]); opt.load_state_dict(s["opt"]); sched.load_state_dict(s["sched"])
76
+ torch.set_rng_state(s["rng"])
77
+ start = st["step"]
78
+ while not st["done"] and st["step"] < total:
79
+ ep, i = divmod(st["step"], steps_ep)
80
+ idx = np.random.RandomState(seed * 1000 + ep).permutation(len(train))[i * bs:(i + 1) * bs]
81
+ batch = [train[j] for j in idx]
82
+ model.train()
83
+ enc = tok([t for t, _ in batch], padding=True, truncation=True, max_length=96, return_tensors="pt").to("cuda")
84
+ with torch.autocast("cuda", dtype=torch.bfloat16):
85
+ logits = model(**enc).logits
86
+ loss = loss_fn(logits.float(), torch.tensor([L2I[l] for _, l in batch], device="cuda"))
87
+ if not torch.isfinite(loss):
88
+ raise gr.Error(f"non-finite loss at step {st['step']}")
89
+ loss.backward(); torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
90
+ opt.step(); sched.step(); opt.zero_grad(); st["step"] += 1
91
+ if st["step"] % eval_every == 0 or st["step"] == total:
92
+ r = {k: report(y, [LABELS[j] for j in probs(model, tok, X).argmax(1)]) for k, (X, y) in VAL.items()}
93
+ s = float(np.mean([v["macro_f1"] for v in r.values()]))
94
+ st["hist"].append({"step": st["step"], "val_mean_f1": round(s, 4), "f1": {k: round(v["macro_f1"], 4) for k, v in r.items()},
95
+ "acc": {k: round(v["accuracy"], 4) for k, v in r.items()}, "loss": round(loss.item(), 4)})
96
+ if s > st["best"]:
97
+ st["best"], st["bad"] = s, 0
98
+ model.save_pretrained(f"{work}/best"); tok.save_pretrained(f"{work}/best")
99
+ else:
100
+ st["bad"] += 1
101
+ st["done"] = st["bad"] >= c.get("patience", 2)
102
+ if time.time() - t0 > budget:
103
+ break
104
+ st["done"] = st["done"] or st["step"] >= total
105
+ st["config"] = c
106
+ if not st["done"]:
107
+ torch.save({"model": model.state_dict(), "opt": opt.state_dict(), "sched": sched.state_dict(), "rng": torch.get_rng_state()}, f"{work}/state.pt")
108
+ json.dump(st, open(f"{work}/state.json", "w"), indent=1)
109
+ return json.dumps({"run": c["run"], "steps_this_call": st["step"] - start, "step": st["step"], "total": total, "done": st["done"],
110
+ "best": st["best"], "last_val": st["hist"][-1] if st["hist"] else None, "gpu_wall_s": round(time.time() - t0, 1)})
111
+
112
+
113
+ def train_chunk(config_json, resume_repo):
114
+ c = json.loads(config_json)
115
+ work = f"/tmp/runs/{c['run']}"
116
+ os.makedirs(work, exist_ok=True)
117
+ api.create_repo(resume_repo, private=True, exist_ok=True)
118
+ if "state.json" in api.list_repo_files(resume_repo) and not os.path.exists(f"{work}/state.json"):
119
+ snapshot_download(resume_repo, local_dir=work, token=TOKEN)
120
+ out = json.loads(_train_gpu(config_json, resume_repo))
121
+ ignore = ["state.pt"] if out["done"] else []
122
+ api.upload_folder(folder_path=work, repo_id=resume_repo, commit_message=f"step {out['step']}", ignore_patterns=ignore)
123
+ return json.dumps(out)
124
+
125
+
126
+ @spaces.GPU(duration=90)
127
+ def _eval_gpu(path, amp=True):
128
+ t0 = time.time()
129
+ tok = AutoTokenizer.from_pretrained(path)
130
+ model = AutoModelForSequenceClassification.from_pretrained(path, torch_dtype=torch.float32).cuda()
131
+ sets = dict(HELD) | {"val_pb": VAL["pb"], "val_tw": VAL["tw"], "val_jb": VAL["jb"]}
132
+ out = {"params": sum(p.numel() for p in model.parameters())}
133
+ for k, (X, y) in sets.items():
134
+ out[k] = np.round(probs(model, tok, X, amp=amp), 5).tolist()
135
+ out[k + "_gold"] = [LABELS.index(l) for l in y]
136
+ out["gpu_wall_s"] = round(time.time() - t0, 1)
137
+ return json.dumps(out)
138
+
139
+
140
+ def evaluate(model_repo, subfolder):
141
+ """subfolder may end in ":fp32" to score without bf16 autocast (what a default fp32 load gives)."""
142
+ subfolder, _, prec = subfolder.partition(":")
143
+ path = snapshot_download(model_repo, token=TOKEN, allow_patterns=[f"{subfolder}/*"] if subfolder else None,
144
+ ignore_patterns=["state.pt", "*.bin"] if not subfolder else None)
145
+ return _eval_gpu(os.path.join(path, subfolder) if subfolder else path, amp=prec != "fp32")
146
+
147
+
148
+ def soup(repos, out_repo):
149
+ """CPU only: uniform average of the best checkpoints of same-architecture runs, pushed to out_repo/best."""
150
+ from safetensors.torch import load_file, save_file
151
+ import shutil
152
+ paths = [os.path.join(snapshot_download(r, token=TOKEN, allow_patterns=["best/*"]), "best") for r in repos.split(",")]
153
+ sds = [load_file(f"{p}/model.safetensors") for p in paths]
154
+ avg = {k: (sum(sd[k].float() for sd in sds) / len(sds)).to(sds[0][k].dtype) for k in sds[0]}
155
+ work = f"/tmp/soup/{out_repo.split('/')[-1]}/best"
156
+ shutil.copytree(paths[0], work, dirs_exist_ok=True)
157
+ save_file({k: v.contiguous() for k, v in avg.items()}, f"{work}/model.safetensors", metadata={"format": "pt"})
158
+ api.create_repo(out_repo, private=True, exist_ok=True)
159
+ api.upload_folder(folder_path=os.path.dirname(work), repo_id=out_repo, commit_message=f"average of {repos}")
160
+ return json.dumps({"averaged": len(sds), "out": out_repo})
161
+
162
+
163
+ def latency(model_repo, subfolder):
164
+ """CPU only: batch-1 latency over 300 tweet-validation texts after 20 warm-up calls, 4 threads; also
165
+ returns the labels the loaded model gives three fixed sentences (a load check)."""
166
+ torch.set_num_threads(4)
167
+ kw = {"subfolder": subfolder} if subfolder else {}
168
+ tok = AutoTokenizer.from_pretrained(model_repo, token=TOKEN, **kw)
169
+ model = AutoModelForSequenceClassification.from_pretrained(model_repo, token=TOKEN, **kw).eval()
170
+ X = HELD["twitter_valid"][0][:320]
171
+ ts = []
172
+ with torch.no_grad():
173
+ for i, t in enumerate(X):
174
+ t0 = time.perf_counter()
175
+ model(**tok(t, truncation=True, max_length=96, return_tensors="pt"))
176
+ if i >= 20:
177
+ ts.append((time.perf_counter() - t0) * 1000)
178
+ demo_texts = ["The company reported record quarterly profit, beating analyst expectations.",
179
+ "Net sales decreased by 12% and the firm warned of further losses ahead.",
180
+ "The board will meet next Tuesday to review the quarterly schedule."]
181
+ enc = tok(demo_texts, padding=True, truncation=True, max_length=96, return_tensors="pt")
182
+ labels = [model.config.id2label[int(i)] for i in model(**enc).logits.argmax(-1)]
183
+ return json.dumps({"params": sum(p.numel() for p in model.parameters()), "threads": torch.get_num_threads(), "cpu_count": os.cpu_count(),
184
+ "median_ms": round(float(np.median(ts)), 1), "p90_ms": round(float(np.percentile(ts, 90)), 1), "demo_labels": labels})
185
+
186
+
187
+ def _probe_dur(seconds):
188
+ return int(seconds)
189
+
190
+
191
+ @spaces.GPU(duration=_probe_dur)
192
+ def probe(seconds):
193
+ return json.dumps({"device": torch.cuda.get_device_name(0), "torch": torch.__version__, "requested": int(seconds)})
194
+
195
+
196
+ with gr.Blocks() as demo:
197
+ gr.Markdown("Private working Space: resumable fine-tuning and held-out scoring.")
198
+ cfg, repo, sub, sec, out = gr.Textbox(label="config"), gr.Textbox(label="repo"), gr.Textbox(label="subfolder"), gr.Number(label="seconds"), gr.Textbox(label="out")
199
+ gr.Button("train").click(train_chunk, [cfg, repo], out, api_name="train_chunk")
200
+ gr.Button("eval").click(evaluate, [repo, sub], out, api_name="evaluate")
201
+ gr.Button("probe").click(probe, [sec], out, api_name="probe")
202
+ gr.Button("soup").click(soup, [repo, sub], out, api_name="soup")
203
+ gr.Button("latency").click(latency, [repo, sub], out, api_name="latency")
204
+
205
+ demo.queue(default_concurrency_limit=1).launch()
training/common.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Shared data loading and evaluation for old-vs-new comparison (same code for both models)."""
2
+ import csv, zipfile, json, sys, re
3
+ import numpy as np, torch
4
+ import pyarrow.parquet as pq
5
+ from huggingface_hub import hf_hub_download
6
+ from sklearn.model_selection import train_test_split
7
+ from sklearn.metrics import accuracy_score, f1_score, precision_recall_fscore_support
8
+
9
+ LABELS = ["negative", "neutral", "positive"]
10
+ L2I = {l: i for i, l in enumerate(LABELS)}
11
+ TW_REV = "ccbe24de388e287beb92dd393a335c376b350ac3"
12
+ JB_REV = "547fa98342d2c80734a1c841dbf3de2cfcaaab95"
13
+ TW_MAP = {"0": "negative", "1": "positive", "2": "neutral"} # Bearish, Bullish, Neutral
14
+ JB_MAP = {0: "negative", 1: "neutral", 2: "positive"} # ClassLabel names in dataset_infos.json
15
+
16
+
17
+ PB_REV = "8d3fe0c36d5feec6b3cc5e455b0fcb4820fb9964"
18
+ SF_REV = "d6294b768091ae7198051294c7fdeee2fbfbd224"
19
+ NS_REV = "9bd8206a729ccd64fa259f0368f0b4025bb472af"
20
+
21
+
22
+ def norm(t):
23
+ return " ".join(t.lower().split())
24
+
25
+
26
+ def dnorm(t):
27
+ """Dedupe key: lower-case, URLs removed, punctuation removed, whitespace collapsed."""
28
+ t = re.sub(r"(https?://\S+|www\.\S+)", " ", t.lower())
29
+ return " ".join(re.sub(r"[^\w\s]|_", " ", t).split())
30
+
31
+
32
+ def carve(X, y):
33
+ """90/10 stratified train/validation slice of a training file (random_state=42)."""
34
+ return train_test_split(X, y, test_size=0.10, stratify=y, random_state=42)
35
+
36
+
37
+ def phrasebank(agree="AllAgree"): # AllAgree, 75Agree, 66Agree or 50Agree
38
+ z = zipfile.ZipFile(hf_hub_download("takala/financial_phrasebank", "data/FinancialPhraseBank-v1.0.zip", repo_type="dataset", revision=PB_REV))
39
+ name = [x for x in z.namelist() if x.endswith(f"Sentences_{agree}.txt") and not x.startswith("__MACOSX")][0]
40
+ rows = [l.rsplit("@", 1) for l in z.read(name).decode("latin-1").splitlines() if "@" in l]
41
+ return [t.strip() for t, _ in rows], [s.strip() for _, s in rows]
42
+
43
+
44
+ def phrasebank_split():
45
+ """Stratified 70/15/15, random_state=42: test first, then validation from the rest."""
46
+ X, y = phrasebank()
47
+ Xtv, Xte, ytv, yte = train_test_split(X, y, test_size=0.15, stratify=y, random_state=42)
48
+ Xtr, Xva, ytr, yva = train_test_split(Xtv, ytv, test_size=0.15 / 0.85, stratify=ytv, random_state=42)
49
+ return (Xtr, ytr), (Xva, yva), (Xte, yte)
50
+
51
+
52
+ def twitter(split): # "train" or "valid"
53
+ p = hf_hub_download("zeroshot/twitter-financial-news-sentiment", f"sent_{split}.csv", repo_type="dataset", revision=TW_REV)
54
+ rows = list(csv.DictReader(open(p, newline="", encoding="utf-8")))
55
+ return [r["text"] for r in rows], [TW_MAP[r["label"]] for r in rows]
56
+
57
+
58
+ def jb(split): # "train" or "test"; text = headline (title)
59
+ f = {"train": "data/train-00000-of-00001-f6c9e78174b9882e.parquet", "test": "data/test-00000-of-00001-f8c02546a74f96bb.parquet"}[split]
60
+ rows = pq.read_table(hf_hub_download("Jean-Baptiste/financial_news_sentiment", f, repo_type="dataset", revision=JB_REV)).to_pylist()
61
+ return [r["title"] for r in rows], [JB_MAP[int(r["labels"])] for r in rows]
62
+
63
+
64
+ def phrasebank_extra(agree):
65
+ """Sentences in a lower-agreement PhraseBank file that are not in AllAgree at all (so none of the
66
+ AllAgree test or validation sentences can leak in); label = the file's majority label."""
67
+ allagree = {dnorm(t) for t in phrasebank()[0]}
68
+ X, y = phrasebank(agree)
69
+ keep = [(t, l) for t, l in zip(X, y) if dnorm(t) not in allagree]
70
+ return [t for t, _ in keep], [l for _, l in keep]
71
+
72
+
73
+ def sentfin(split="test"):
74
+ """SEntFiN headlines (tasksource/sentfin repackaging, 80/10/10 split grouped by headline). The source
75
+ labels each entity in a headline; a headline is kept only when every entity has the same label."""
76
+ rows = pq.read_table(hf_hub_download("tasksource/sentfin", f"data/{split}-00000-of-00001.parquet", repo_type="dataset", revision=SF_REV)).to_pylist()
77
+ by = {}
78
+ for r in rows:
79
+ hid = json.loads(r["metadata"])["headline_id"]
80
+ by.setdefault(hid, (r["sentence1"], set()))[1].add(r["labels"])
81
+ keep = [(t, next(iter(ls))) for t, ls in by.values() if len(ls) == 1]
82
+ return [t for t, _ in keep], [l for _, l in keep]
83
+
84
+
85
+ def nosible(n, max_words=60, seed=42):
86
+ """n random short snippets (<= max_words words) from NOSIBLE/financial-sentiment; its labels come from an
87
+ automated multi-annotator pipeline (see that dataset card), not from human annotators."""
88
+ import random
89
+ t = pq.read_table(hf_hub_download("NOSIBLE/financial-sentiment", "data.parquet", repo_type="dataset", revision=NS_REV), columns=["text", "label"]).to_pylist()
90
+ t = [r for r in t if len(r["text"].split()) <= max_words and r["label"] in L2I]
91
+ t = random.Random(seed).sample(t, min(n, len(t)))
92
+ return [r["text"] for r in t], [r["label"] for r in t]
93
+
94
+
95
+ def device():
96
+ import os
97
+ return torch.device("mps" if torch.backends.mps.is_available() and not os.environ.get("FORCE_CPU") else "cpu")
98
+
99
+
100
+ @torch.no_grad()
101
+ def predict(model, tok, texts, max_len=96, bs=64, dev=None):
102
+ dev = dev or next(model.parameters()).device
103
+ model.eval()
104
+ id2l = {int(k): v.lower() for k, v in model.config.id2label.items()}
105
+ out = []
106
+ for i in range(0, len(texts), bs):
107
+ # fixed padding buckets: each new batch shape makes the MPS allocator keep another set of buffers
108
+ enc = tok(texts[i:i + bs], padding=True, truncation=True, max_length=max_len, pad_to_multiple_of=32, return_tensors="pt").to(dev)
109
+ out += [id2l[int(j)] for j in model(**enc).logits.argmax(-1).cpu()]
110
+ if dev.type == "mps":
111
+ torch.mps.empty_cache()
112
+ return out
113
+
114
+
115
+ def report(gold, pred):
116
+ p, r, f, s = precision_recall_fscore_support(gold, pred, labels=LABELS, zero_division=0)
117
+ return {"n": len(gold), "accuracy": accuracy_score(gold, pred), "macro_f1": f1_score(gold, pred, labels=LABELS, average="macro"),
118
+ "per_class": {l: {"precision": float(p[i]), "recall": float(r[i]), "f1": float(f[i]), "support": int(s[i])} for i, l in enumerate(LABELS)}}
119
+
120
+
121
+ def heldout_sets():
122
+ _, _, (Xte, yte) = phrasebank_split()
123
+ return {"phrasebank_test": (Xte, yte), "twitter_valid": twitter("valid"), "jb_test": jb("test"), "sentfin_test": sentfin("test")}
124
+
125
+
126
+ def bootstrap(gold, pred, n=2000, seed=0):
127
+ """95% percentile intervals for macro-F1 and negative recall, resampling rows with replacement."""
128
+ from sklearn.metrics import recall_score
129
+ rng = np.random.default_rng(seed)
130
+ g, p = np.array(gold), np.array(pred)
131
+ mf, nr = [], []
132
+ for _ in range(n):
133
+ i = rng.integers(0, len(g), len(g))
134
+ mf.append(f1_score(g[i], p[i], labels=LABELS, average="macro", zero_division=0))
135
+ nr.append(recall_score(g[i], p[i], labels=["negative"], average="macro", zero_division=0))
136
+ q = lambda a: [float(np.percentile(a, 2.5)), float(np.percentile(a, 97.5))]
137
+ return {"macro_f1_ci": q(mf), "neg_recall_ci": q(nr)}
138
+
139
+
140
+ def evaluate(model, tok):
141
+ out = {}
142
+ for k, (X, y) in heldout_sets().items():
143
+ pred = predict(model, tok, X)
144
+ out[k] = {**report(y, pred), **bootstrap(y, pred), "pred": pred}
145
+ return out
146
+
147
+
148
+ def fmt(res):
149
+ lines = []
150
+ for k, v in res.items():
151
+ pc = " ".join(f"{l[:3]} P{c['precision']:.3f} R{c['recall']:.3f} (n={c['support']})" for l, c in v["per_class"].items())
152
+ ci = f" [{v['macro_f1_ci'][0]:.3f},{v['macro_f1_ci'][1]:.3f}]" if "macro_f1_ci" in v else ""
153
+ lines.append(f"{k:16s} n={v['n']:5d} acc={v['accuracy']:.4f} mF1={v['macro_f1']:.4f}{ci} negF1={v['per_class']['negative']['f1']:.3f} | {pc}")
154
+ return "\n".join(lines)
training/drive.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Light client for the private training Space (no local model work).
2
+ Usage: drive.py stage | probe <s> | train <run> <config-json> [max_calls] | eval <run> <repo> <subfolder|-> <out.npz>
3
+ Each GPU call's measured seconds are appended to GPU_LOG.md; train stops before the daily cap."""
4
+ import sys, json, time, re
5
+ from pathlib import Path
6
+ import numpy as np
7
+ from huggingface_hub import HfApi
8
+
9
+ W = Path(__file__).parent
10
+ SPACE = "9mark9/trainer-tmp"
11
+ CAP_S = 35 * 60
12
+ TOK = Path.home().joinpath(".cache/huggingface/token").read_text().strip()
13
+ LOG = W / "GPU_LOG.md"
14
+
15
+
16
+ def used_today():
17
+ """GPU seconds logged since the first logged call of the current 24 h window."""
18
+ if not LOG.exists():
19
+ return 0.0
20
+ rows = [l.split("|") for l in LOG.read_text().splitlines() if re.match(r"\| \d{4}-", l)]
21
+ rows = [(time.mktime(time.strptime(r[1].strip(), "%Y-%m-%d %H:%M:%S")), float(r[4])) for r in rows]
22
+ start = None
23
+ for t, _ in rows:
24
+ if start is None or t - start >= 86400:
25
+ start = t
26
+ # 10% + 5 s per call on top of the measured time, to cover allocation overhead the function cannot see
27
+ return sum(s * 1.1 + 5 for t, s in rows if t >= start) if start else 0.0
28
+
29
+
30
+ def log(kind, name, gpu_s, wall_s, note=""):
31
+ if not LOG.exists():
32
+ LOG.write_text("# ZeroGPU usage (9mark9/trainer-tmp)\n\nSeconds are measured inside the GPU function (load + work).\n"
33
+ "Quota window: 24 h from the first call.\n\n| time | call | name | gpu_s | client_wall_s | note |\n|---|---|---|---|---|---|\n")
34
+ with LOG.open("a") as f:
35
+ f.write(f"| {time.strftime('%Y-%m-%d %H:%M:%S')} | {kind} | {name} | {gpu_s:.1f} | {wall_s:.1f} | {note} |\n")
36
+
37
+
38
+ def client():
39
+ from gradio_client import Client
40
+ return Client(SPACE, token=TOK, verbose=False)
41
+
42
+
43
+ cmd = sys.argv[1]
44
+ if cmd == "stage":
45
+ i = HfApi(token=TOK).space_info(SPACE)
46
+ print(i.runtime.stage, i.runtime.hardware, f"used today {used_today()/60:.1f} min")
47
+ elif cmd == "probe":
48
+ t0 = time.time()
49
+ r = client().predict(float(sys.argv[2]), api_name="/probe")
50
+ log("probe", sys.argv[2], time.time() - t0, time.time() - t0, "upper bound (client wall)")
51
+ print(r)
52
+ elif cmd == "train":
53
+ run, cfg, max_calls = sys.argv[2], json.loads(sys.argv[3]), int(sys.argv[4]) if len(sys.argv) > 4 else 6
54
+ cfg["run"] = run
55
+ c = client()
56
+ for _ in range(max_calls):
57
+ if used_today() + cfg.get("gpu_seconds", 120) > CAP_S:
58
+ print(f"STOP cap: used {used_today()/60:.1f} min"); break
59
+ t0 = time.time()
60
+ r = json.loads(c.predict(json.dumps(cfg), f"9mark9/tmp-train-{run}", api_name="/train_chunk"))
61
+ log("train", run, r["gpu_wall_s"], time.time() - t0, f"step {r['step']}/{r['total']} done={r['done']} best={r['best']:.4f}")
62
+ print(json.dumps(r), flush=True)
63
+ if r["done"]:
64
+ break
65
+ elif cmd == "latency":
66
+ print(client().predict(sys.argv[2], "" if sys.argv[3] == "-" else sys.argv[3], api_name="/latency"))
67
+ elif cmd == "soup":
68
+ print(client().predict(sys.argv[2], sys.argv[3], api_name="/soup"))
69
+ elif cmd == "eval":
70
+ run, repo, sub, out = sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5]
71
+ if used_today() + 90 > CAP_S:
72
+ sys.exit(f"STOP cap: used {used_today()/60:.1f} min")
73
+ t0 = time.time()
74
+ r = json.loads(client().predict(repo, "" if sub == "-" else sub, api_name="/evaluate"))
75
+ log("eval", run, r.pop("gpu_wall_s"), time.time() - t0)
76
+ np.savez(W / out, params=np.array(r.pop("params")), **{k: np.array(v) for k, v in r.items()})
77
+ print("saved", out, {k: round(float((np.array(r[k]).argmax(1) == np.array(r[k + "_gold"])).mean()), 4) for k in r if not k.endswith("_gold")})
training/requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ torch==2.8.0
2
+ transformers>=4.51,<5
3
+ sentencepiece
4
+ protobuf
5
+ scikit-learn
6
+ pyarrow
7
+ numpy
8
+ spaces
9
+ gradio==5.50.0