Kenpache commited on
Commit
ebb03ec
·
verified ·
1 Parent(s): 8adaa46

Add files using upload-large-folder tool

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ tokenizer.json filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ - zh
5
+ - ja
6
+ - es
7
+ - de
8
+ - fr
9
+ - ar
10
+ license: apache-2.0
11
+ library_name: transformers
12
+ pipeline_tag: text-classification
13
+ base_model: FacebookAI/xlm-roberta-large
14
+ datasets:
15
+ - Kenpache/financial-sentiment-eval-7lang
16
+ metrics:
17
+ - accuracy
18
+ - f1
19
+ tags:
20
+ - finance
21
+ - financial-sentiment
22
+ - sentiment-analysis
23
+ - multilingual
24
+ - financial-news
25
+ - fintech
26
+ - trading
27
+ - market-sentiment
28
+ - text-classification
29
+ - xlm-roberta
30
+ - cross-lingual
31
+ ---
32
+
33
+ # Financial Sentiment, 7 Languages — Large
34
+
35
+ **Sentiment of financial news, in seven languages, from one model.** Feed it a headline
36
+ or a sentence in English, Chinese, Japanese, Spanish, German, French or Arabic — get
37
+ back `negative`, `neutral` or `positive`.
38
+
39
+ ```python
40
+ from transformers import pipeline
41
+
42
+ clf = pipeline("text-classification", model="Kenpache/finbert-multilingual-v2-large")
43
+
44
+ clf("The company reported record quarterly earnings, driven by strong demand.")
45
+ # [{'label': 'positive', 'score': 0.9445}]
46
+
47
+ clf("Die Aktie verlor nach der Gewinnwarnung deutlich an Wert.")
48
+ # [{'label': 'negative', 'score': 0.9435}]
49
+
50
+ clf("该公司宣布大规模裁员计划,股价应声下跌。")
51
+ # [{'label': 'negative', 'score': 0.9436}]
52
+ ```
53
+
54
+ | | |
55
+ |---|---|
56
+ | **Task** | Financial sentiment, 3 classes (negative / neutral / positive) |
57
+ | **Languages** | **7** — en · zh · ja · es · de · fr · ar |
58
+ | **Accuracy** | **88.9%** |
59
+ | **Parameters** | 560M (fp32, 2.1 GB) |
60
+ | **Backbone** | [`FacebookAI/xlm-roberta-large`](https://huggingface.co/FacebookAI/xlm-roberta-large) |
61
+
62
+ One model covers all seven languages — no per-language checkpoints, no translation step,
63
+ no language ID in front of it. Mixed-language pipelines just work.
64
+
65
+ **Smaller sibling:**
66
+ [`Kenpache/finbert-multilingual-v2`](https://huggingface.co/Kenpache/finbert-multilingual-v2)
67
+ — 307M parameters, 87.2% on the same evaluation set. Take this one for accuracy, that
68
+ one for footprint.
69
+
70
+ ---
71
+
72
+ ## Accuracy
73
+
74
+ Measured on a held-out test set of **4,993 financial news sentences** across the seven
75
+ languages, published as
76
+ [`Kenpache/financial-sentiment-eval-7lang`](https://huggingface.co/datasets/Kenpache/financial-sentiment-eval-7lang).
77
+
78
+ | Metric | Score |
79
+ |---|---|
80
+ | **Accuracy** | **0.8892** |
81
+ | **F1 (weighted)** | **0.8890** |
82
+
83
+ ### Per language
84
+
85
+ This is the table to read before adopting the model — it tells you whether *your*
86
+ language is covered properly, not just the average.
87
+
88
+ | Language | | Items | Accuracy |
89
+ |---|---|---:|---:|
90
+ | Spanish | `es` | 905 | **0.9193** |
91
+ | German | `de` | 650 | **0.9062** |
92
+ | Chinese | `zh` | 1,023 | 0.8974 |
93
+ | Arabic | `ar` | 73 | 0.8904 |
94
+ | Japanese | `ja` | 1,063 | 0.8852 |
95
+ | English | `en` | 780 | 0.8615 |
96
+ | French | `fr` | 499 | 0.8477 |
97
+
98
+ **Every one of the seven languages is above 84%**, and English is not at the top —
99
+ Spanish and German are. That matters more than it looks: most "multilingual" financial
100
+ models are English models with a multilingual tokenizer, and they collapse on CJK and
101
+ right-to-left text. This one holds its level across scripts — Latin, Chinese, Japanese
102
+ and Arabic alike.
103
+
104
+ Arabic is measured on 73 items, so treat its number as indicative rather than precise.
105
+
106
+ ### Reproducing these numbers
107
+
108
+ The evaluation set is public, and so is the protocol — `max_length=192`, fp32, raw text
109
+ with no normalisation:
110
+
111
+ ```python
112
+ import pandas as pd, torch
113
+ from datasets import load_dataset
114
+ from transformers import AutoModelForSequenceClassification, AutoTokenizer
115
+
116
+ ds = load_dataset("Kenpache/financial-sentiment-eval-7lang", split="test").to_pandas()
117
+
118
+ REPO = "Kenpache/finbert-multilingual-v2-large"
119
+ tok = AutoTokenizer.from_pretrained(REPO)
120
+ model = AutoModelForSequenceClassification.from_pretrained(REPO).eval()
121
+
122
+ preds = []
123
+ with torch.no_grad():
124
+ for i in range(0, len(ds), 64):
125
+ enc = tok(ds.sentence[i:i + 64].tolist(), return_tensors="pt",
126
+ padding=True, truncation=True, max_length=192)
127
+ preds += [model.config.id2label[j].lower()
128
+ for j in model(**enc).logits.argmax(-1).tolist()]
129
+
130
+ print((pd.Series(preds) == ds.label).mean()) # 0.8892
131
+ ```
132
+
133
+ ### Per class
134
+
135
+ | Class | Precision | Recall | F1 | Support |
136
+ |---|---:|---:|---:|---:|
137
+ | negative | 0.8820 | 0.9135 | 0.8975 | 1,260 |
138
+ | neutral | 0.9049 | 0.8508 | 0.8770 | 2,158 |
139
+ | positive | 0.8758 | 0.9225 | 0.8986 | 1,575 |
140
+
141
+ No class collapse: the three F1 scores sit within 2.2 points of each other, and `neutral`
142
+ — the majority class, and the usual dumping ground for models that learned to hedge — has
143
+ the *lowest* F1 of the three rather than the highest.
144
+
145
+ **Polarity errors are rare.** Across all 4,993 items, `negative` is called `positive` 14
146
+ times and `positive` is called `negative` 24 times — **38 cases, 0.8% of the set**.
147
+ Practically all remaining error sits on the boundary with `neutral`. The model may fail to
148
+ register a weak signal; it very seldom reverses one.
149
+
150
+ ### Comparison on the English subset
151
+
152
+ Both models were run on the **English portion — 780 items — of
153
+ [`Kenpache/financial-sentiment-eval-7lang`](https://huggingface.co/datasets/Kenpache/financial-sentiment-eval-7lang)**,
154
+ under one identical protocol: `max_length=192`, fp32, raw text, argmax over the three
155
+ classes, no tuning or threshold fitting for either model.
156
+
157
+ | Model | Accuracy | F1 (weighted) |
158
+ |---|---:|---:|
159
+ | **This model** | **0.8615** | **0.8616** |
160
+ | [`ProsusAI/finbert`](https://huggingface.co/ProsusAI/finbert) | 0.7218 | 0.7224 |
161
+
162
+ Two things belong next to those numbers. `ProsusAI/finbert` is an English-only model, so
163
+ the comparison is confined to the English subset — which is, as the table above shows,
164
+ this model's weakest language of the seven. And it was trained under a different
165
+ annotation convention: most of its errors on this set are neutral items assigned a
166
+ direction, so part of the gap reflects differing label conventions rather than capability.
167
+
168
+ **These figures describe behaviour on this evaluation set only, under the protocol stated
169
+ above. They are not a general claim about either model.**
170
+
171
+ ---
172
+
173
+ ## Usage
174
+
175
+ ```bash
176
+ pip install transformers torch
177
+ ```
178
+
179
+ ### Pipeline
180
+
181
+ ```python
182
+ from transformers import pipeline
183
+
184
+ clf = pipeline("text-classification", model="Kenpache/finbert-multilingual-v2-large")
185
+
186
+ clf("Les bénéfices du groupe ont augmenté de 15% au premier trimestre.")
187
+ # [{'label': 'positive', 'score': 0.9443}]
188
+ ```
189
+
190
+ Batch a whole list in one call:
191
+
192
+ ```python
193
+ texts = ["株価は決算発表後に急落した。",
194
+ "La compañía anunció un despido masivo y sus acciones se desplomaron.",
195
+ "Quarterly revenue beat analyst expectations by a wide margin."]
196
+
197
+ clf(texts, batch_size=32)
198
+ # [{'label': 'negative', 'score': 0.9458},
199
+ # {'label': 'negative', 'score': 0.9462},
200
+ # {'label': 'positive', 'score': 0.9467}]
201
+ ```
202
+
203
+ Add `top_k=None` to get the full probability distribution over all three classes instead
204
+ of the winner only — useful when you want to threshold on confidence rather than take
205
+ the argmax.
206
+
207
+ ### Direct loading
208
+
209
+ ```python
210
+ import torch
211
+ from transformers import AutoModelForSequenceClassification, AutoTokenizer
212
+
213
+ REPO = "Kenpache/finbert-multilingual-v2-large"
214
+ tokenizer = AutoTokenizer.from_pretrained(REPO)
215
+ model = AutoModelForSequenceClassification.from_pretrained(REPO).eval()
216
+
217
+ text = "Der Umsatz blieb im Vergleich zum Vorjahr unverändert."
218
+ enc = tokenizer(text, return_tensors="pt", truncation=True, max_length=192)
219
+
220
+ with torch.no_grad():
221
+ probs = torch.softmax(model(**enc).logits, dim=-1)[0]
222
+
223
+ for i, p in enumerate(probs):
224
+ print(f"{model.config.id2label[i]:8} {p:.4f}")
225
+
226
+ # negative 0.0234
227
+ # neutral 0.9491
228
+ # positive 0.0275
229
+ ```
230
+
231
+ ### On GPU
232
+
233
+ ```python
234
+ clf = pipeline("text-classification", model=REPO, device=0) # CUDA
235
+ clf = pipeline("text-classification", model=REPO, device="mps") # Apple Silicon
236
+ ```
237
+
238
+ CUDA, Apple Silicon and plain CPU all work. At 560M parameters inference is comfortable
239
+ on a laptop, though noticeably heavier than the 307M sibling.
240
+
241
+ **Use `max_length=192`** to reproduce the numbers above. The hard ceiling of the backbone
242
+ is 512 tokens — enough for headlines and single sentences, which is what this model is
243
+ for, but do not expect it to take long documents.
244
+
245
+ ---
246
+
247
+ ## Limitations
248
+
249
+ 1. **Sentence-level, not document-level.** The model is built for headlines and single
250
+ sentences. Feeding a full article gives you one label for the whole thing, which is
251
+ rarely what you want — split it first. The 512-token ceiling enforces this anyway.
252
+ 2. **Financial sentiment is not general sentiment.** "Shares fell 3% on the news" is
253
+ negative in a market sense with no emotional language at all. On product reviews or
254
+ social media this model is the wrong tool.
255
+ 3. **`neutral` is a convention, not a fact.** The boundary between neutral and mildly
256
+ positive/negative is where human annotators disagree most, and the model inherits that
257
+ ambiguity. If a decision hinges on that boundary, use the probabilities and a
258
+ threshold instead of the argmax.
259
+ 4. **Arabic coverage is thin** in evaluation (73 items). The other six languages are
260
+ measured on 499–1,063 items each.
261
+ 5. **Seven languages.** The backbone is pretrained on a hundred, but this classifier was
262
+ tuned for these seven. Other languages will produce output, but it is untested.
263
+ 6. **Not investment advice.** The output is a sentiment label on a text, not a signal to
264
+ trade on.
265
+
266
+ ---
267
+
268
+ ## Intended use
269
+
270
+ Good fits:
271
+
272
+ - tagging multilingual financial news feeds in real time
273
+ - market-sentiment dashboards and indices across regions
274
+ - pre-screening research corpora before human analysis
275
+ - backtesting sentiment-based features on multilingual sources
276
+
277
+ Poor fits: general-purpose sentiment, long documents, languages outside the seven,
278
+ anything where the neutral boundary carries legal or financial weight on its own.
279
+
280
+ ---
281
+
282
+ ## Files
283
+
284
+ | File | What it is |
285
+ |---|---|
286
+ | `model.safetensors` | weights, fp32, 2.1 GB |
287
+ | `config.json` | XLM-RoBERTa config with `id2label` (`negative` / `neutral` / `positive`) |
288
+ | `tokenizer.json`, `sentencepiece.bpe.model`, `tokenizer_config.json` | tokenizer |
289
+
290
+ ## License
291
+
292
+ Apache 2.0.
293
+
294
+ Built on [`FacebookAI/xlm-roberta-large`](https://huggingface.co/FacebookAI/xlm-roberta-large),
295
+ which is MIT-licensed; that attribution is preserved here.
296
+
297
+ ## Citation
298
+
299
+ ```bibtex
300
+ @misc{finbert_multilingual_v2_large,
301
+ title = {Financial Sentiment, 7 Languages — Large},
302
+ author = {Kenpache},
303
+ year = {2026},
304
+ url = {https://huggingface.co/Kenpache/finbert-multilingual-v2-large}
305
+ }
306
+ ```
config.json ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_cross_attention": false,
3
+ "architectures": [
4
+ "XLMRobertaForSequenceClassification"
5
+ ],
6
+ "attention_probs_dropout_prob": 0.1,
7
+ "bos_token_id": 0,
8
+ "classifier_dropout": null,
9
+ "dtype": "float32",
10
+ "eos_token_id": 2,
11
+ "hidden_act": "gelu",
12
+ "hidden_dropout_prob": 0.1,
13
+ "hidden_size": 1024,
14
+ "id2label": {
15
+ "0": "negative",
16
+ "1": "neutral",
17
+ "2": "positive"
18
+ },
19
+ "initializer_range": 0.02,
20
+ "intermediate_size": 4096,
21
+ "is_decoder": false,
22
+ "label2id": {
23
+ "negative": 0,
24
+ "neutral": 1,
25
+ "positive": 2
26
+ },
27
+ "layer_norm_eps": 1e-05,
28
+ "max_position_embeddings": 514,
29
+ "model_type": "xlm-roberta",
30
+ "num_attention_heads": 16,
31
+ "num_hidden_layers": 24,
32
+ "output_past": true,
33
+ "pad_token_id": 1,
34
+ "position_embedding_type": "absolute",
35
+ "tie_word_embeddings": true,
36
+ "transformers_version": "5.15.0",
37
+ "type_vocab_size": 1,
38
+ "use_cache": false,
39
+ "vocab_size": 250002
40
+ }
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d3ffaa1fc09c21e4d77835bf1ebb2c12c89d7cd2168ab5d2a0098a20221565c8
3
+ size 2239622772
sentencepiece.bpe.model ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cfc8146abe2a0488e9e2a0c56de7952f7c11ab059eca145a0a727afce0db2865
3
+ size 5069051
tokenizer.json ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:19ffc61f7cb57aa8c419fa9d2409c2af1abf4a92ba5a12c60a09cafa5a59c9b1
3
+ size 17098184
tokenizer_config.json ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": true,
3
+ "bos_token": "<s>",
4
+ "cls_token": "<s>",
5
+ "eos_token": "</s>",
6
+ "mask_token": "<mask>",
7
+ "model_max_length": 512,
8
+ "pad_token": "<pad>",
9
+ "sep_token": "</s>",
10
+ "tokenizer_class": "XLMRobertaTokenizer",
11
+ "unk_token": "<unk>"
12
+ }