peyterho commited on
Commit
2ac6b1b
·
verified ·
1 Parent(s): 91d2b9b

Fine-tuned FinBERT on 20K macro sentiment dataset (2 epochs)

Browse files
Files changed (1) hide show
  1. README.md +41 -227
README.md CHANGED
@@ -1,252 +1,66 @@
1
  ---
2
  library_name: transformers
3
- license: apache-2.0
4
  tags:
5
- - text-classification
6
- - sentiment-analysis
7
- - finance
8
- - finbert
9
- - roberta
10
- - climate
11
- - esg
12
- - macroeconomics
13
- - multilingual
14
- datasets:
15
- - nickmuchi/financial-classification
16
- - zeroshot/twitter-financial-news-sentiment
17
- - FinanceInc/auditor_sentiment
18
- - pauri32/fiqa-2018
19
- - climatebert/climate_sentiment
20
  metrics:
21
  - accuracy
22
- - f1
23
- language:
24
- - en
25
- - ar
26
- - de
27
- - es
28
- - fr
29
- - hi
30
- - it
31
- - pt
32
- pipeline_tag: text-classification
33
  model-index:
34
  - name: macro-sentiment-finbert
35
- results:
36
- - task:
37
- type: text-classification
38
- name: Financial Sentiment Analysis
39
- metrics:
40
- - name: Accuracy (RoBERTa-Large)
41
- type: accuracy
42
- value: 0.913
43
- - name: F1 Macro (RoBERTa-Large)
44
- type: f1
45
- value: 0.902
46
- - name: Accuracy (FinBERT)
47
- type: accuracy
48
- value: 0.897
49
- - name: F1 Macro (FinBERT)
50
- type: f1
51
- value: 0.881
52
  ---
53
 
54
- # 🏦 Macroeconomic Sentiment Analysis
 
55
 
56
- **What it does:** Takes any financial or economic text and tells you whether the sentiment is positive, negative, or neutral — plus whether the tone is hawkish/dovish, whether it signals a crisis, and how much it relates to climate/ESG. Now supports **multilingual text** (v0.3.0).
57
 
58
- **Who it's for:** Anyone analyzing news articles, central bank statements, earnings reports, financial tweets, or climate/ESG disclosures in English or other languages.
 
 
 
 
 
59
 
60
- ---
61
-
62
- ## The Simple Way (3 lines of Python)
63
-
64
- ```python
65
- from transformers import pipeline
66
-
67
- classifier = pipeline("text-classification", model="peyterho/finbert-macro-sentiment")
68
-
69
- classifier("Tesla shares surged 15% after beating earnings expectations.")
70
- # → [{'label': 'positive', 'score': 0.998}]
71
-
72
- classifier("Markets crashed amid recession fears and massive layoffs.")
73
- # → [{'label': 'negative', 'score': 0.997}]
74
- ```
75
-
76
- ### Which model should I pick?
77
-
78
- | Model | Size | Speed | Accuracy | Best for |
79
- |-------|------|-------|----------|----------|
80
- | [`peyterho/finbert-macro-sentiment`](https://huggingface.co/peyterho/finbert-macro-sentiment) | 110M | Fast | 89.7% | General financial text — good default choice |
81
- | [`peyterho/financial-roberta-large-macro-sentiment`](https://huggingface.co/peyterho/financial-roberta-large-macro-sentiment) | 355M | Slower | **91.3%** | When accuracy matters most |
82
- | [`peyterho/climatebert-macro-sentiment`](https://huggingface.co/peyterho/climatebert-macro-sentiment) | 82M | Fastest | 88.9% | Climate/ESG text |
83
-
84
- ---
85
 
86
- ## Multilingual Support (v0.3.0)
87
 
88
- The pipeline now auto-detects non-English text and routes it to an XLM-RoBERTa multilingual sentiment model.
89
 
90
- **Supported languages:** English, Arabic, French, German, Hindi, Italian, Portuguese, Spanish — plus reasonable performance on many others.
91
-
92
- ```python
93
- from macro_sentiment import TransformerEnsemble
94
-
95
- ensemble = TransformerEnsemble(device="cpu")
96
-
97
- # German — auto-routed to multilingual head
98
- result = ensemble.score_routed("EZB signalisiert Geduld bei Zinssenkungen.")
99
- print(result["head_used"]) # "multilingual"
100
- print(result["detected_language"]) # "de"
101
- print(result["sentiment_score"]) # [-1, +1]
102
-
103
- # French
104
- result = ensemble.score_routed("La BCE maintient ses taux directeurs inchangés.")
105
- print(result["head_used"]) # "multilingual"
106
-
107
- # English — still routed to domain-specific heads as before
108
- result = ensemble.score_routed("Fed raised rates by 75bps.")
109
- print(result["head_used"]) # "policy" (RoBERTa-Large)
110
- ```
111
-
112
- For better language detection accuracy, install `langdetect`:
113
- ```bash
114
- pip install langdetect
115
- ```
116
-
117
- To disable multilingual routing (v0.2.0 behavior):
118
- ```python
119
- ensemble = TransformerEnsemble(multilingual_model=None)
120
- ```
121
-
122
- ---
123
 
124
- ## Fine-Tune on Your Own Data
125
 
126
- Got your own labelled financial text? Fine-tune any head in one command:
127
 
128
- ```bash
129
- python -m macro_sentiment.finetune \
130
- --data my_labels.csv \
131
- --text-column headline \
132
- --label-column sentiment \
133
- --base-model peyterho/finbert-macro-sentiment \
134
- --output my-org/my-custom-model \
135
- --push-to-hub
136
- ```
137
 
138
- **Your CSV/TSV/JSON/JSONL just needs two columns:**
139
 
140
- | headline | sentiment |
141
- |----------|-----------|
142
- | Company profits soared to record highs | positive |
143
- | Stock prices crashed amid panic selling | negative |
144
- | Revenue remained flat quarter over quarter | neutral |
 
 
 
 
 
 
145
 
146
- Labels accept: `positive`/`negative`/`neutral` (or `bullish`/`bearish`, `pos`/`neg`, `risk`/`opportunity`, or integers `0`/`1`/`2`).
147
 
148
- **Options:**
149
- ```
150
- --base-model Which model to start from (default: peyterho/finbert-macro-sentiment)
151
- --epochs Training epochs (default: 4)
152
- --lr Learning rate (default: 2e-5)
153
- --batch-size Batch size (default: 32)
154
- --max-length Max token length (default: 128)
155
- --push-to-hub Push result to Hugging Face Hub
156
- --output Local dir or Hub model ID
157
- ```
158
 
159
- The script auto-detects label remapping from the model's config, applies class weighting for imbalanced data, and selects the best checkpoint by macro F1.
160
 
161
- ---
162
-
163
- ## The Full Pipeline
164
-
165
- For hawkish/dovish stance, crisis detection, climate exposure, and uncertainty scoring:
166
-
167
- ```bash
168
- pip install transformers torch pysentiment2 scikit-learn numpy datasets huggingface_hub
169
- python -c "from huggingface_hub import snapshot_download; snapshot_download('peyterho/macro-sentiment-finbert', local_dir='macro-sentiment-finbert')"
170
- cd macro-sentiment-finbert
171
- ```
172
-
173
- ```python
174
- from macro_sentiment import MacroSentimentPipeline
175
-
176
- pipe = MacroSentimentPipeline(device="cpu")
177
-
178
- result = pipe("The Federal Reserve raised rates by 75bps citing persistent inflation.")
179
- print(result.summary())
180
- # → Sentiment: ... | Policy: Very Hawkish (+0.999) | Crisis: Normal | Domain: policy
181
-
182
- result.macro_sentiment # -1.0 to +1.0
183
- result.policy_stance # -1.0 (dovish) to +1.0 (hawkish)
184
- result.crisis_signal # 0.0 (calm) to 1.0 (crisis)
185
- result.uncertainty # 0.0 (certain) to 1.0 (uncertain)
186
- result.climate_exposure # 0.0 to 1.0
187
- ```
188
-
189
- ---
190
-
191
- ## Accuracy
192
-
193
- ### In-domain (4,333 test samples from training datasets)
194
-
195
- | Model | Accuracy | F1 Macro |
196
- |-------|----------|----------|
197
- | RoBERTa-Large (fine-tuned) | **91.3%** | **0.902** |
198
- | FinBERT (fine-tuned) | 89.7% | 0.881 |
199
- | ClimateBERT (fine-tuned) | 88.9% | 0.872 |
200
-
201
- ### Out-of-domain (datasets NOT in training)
202
-
203
- | Model | Stock News (30K) | JB PhraseBank (785) |
204
- |-------|------------------|---------------------|
205
- | RoBERTa-Large | **72.1% acc / 0.727 F1** | **94.1% acc / 0.936 F1** |
206
- | FinBERT | 67.8% / 0.677 | 92.4% / 0.913 |
207
- | ClimateBERT | 64.7% / 0.644 | 92.5% / 0.921 |
208
-
209
- The Stock News OOD dataset ([ic-fspml/stock_news_sentiment](https://huggingface.co/datasets/ic-fspml/stock_news_sentiment)) uses 5-class labels mapped to 3-class, with different annotation conventions — the 20pp accuracy drop is expected and honest. The JB PhraseBank OOD dataset ([Jean-Baptiste/financial_news_sentiment_mixte_with_phrasebank_75](https://huggingface.co/datasets/Jean-Baptiste/financial_news_sentiment_mixte_with_phrasebank_75)) is a similar domain and holds up well.
210
-
211
- ---
212
 
213
- ## All Output Fields
214
-
215
- | Field | Range | What it means |
216
- |-------|-------|---------------|
217
- | `macro_sentiment` | -1 to +1 | Overall sentiment |
218
- | `policy_stance` | -1 to +1 | Dovish ← 0 → Hawkish |
219
- | `financial_sentiment` | -1 to +1 | Raw sentiment from active head |
220
- | `climate_sentiment` | -1 to +1 | Climate risk ← 0 → opportunity |
221
- | `crisis_signal` | 0 to 1 | Crisis intensity |
222
- | `uncertainty` | 0 to 1 | Uncertainty level |
223
- | `confidence` | 0 to 1 | Model confidence |
224
- | `climate_exposure` | 0 to 1 | Climate topic density |
225
- | `detected_domain` | text | policy / climate / financial_news / social |
226
- | `head_used` | text | Which model was activated |
227
-
228
- ## File Structure
229
-
230
- ```
231
- macro_sentiment/
232
- ├── __init__.py # Package entry point (v0.3.0)
233
- ├── dictionaries.py # Four financial dictionaries
234
- ├── transformers_ensemble.py # Four AI heads + language-aware router
235
- ├── pipeline.py # Full pipeline combining everything
236
- ├── finetune.py # Custom fine-tuning CLI
237
- ├── data_prep.py # Dataset loading
238
- └── train_meta.py # Meta-classifier training
239
- eval_results.json # In-domain metrics
240
- eval_ood_results.json # Out-of-domain metrics
241
- ```
242
-
243
- ## References
244
-
245
- - Araci (2019). [FinBERT](https://arxiv.org/abs/1908.10063)
246
- - Loughran & McDonald (2011). *Journal of Finance*
247
- - Henry (2008). *Journal of Business Communication*
248
- - Sautner et al. (2023). *Review of Financial Studies*
249
- - Barbieri et al. (2022). [XLM-T: Multilingual Language Models for Twitter](https://arxiv.org/abs/2104.12250)
250
-
251
- ## License
252
- Apache 2.0
 
1
  ---
2
  library_name: transformers
3
+ base_model: ProsusAI/finbert
4
  tags:
5
+ - generated_from_trainer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  metrics:
7
  - accuracy
 
 
 
 
 
 
 
 
 
 
 
8
  model-index:
9
  - name: macro-sentiment-finbert
10
+ results: []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  ---
12
 
13
+ <!-- This model card has been generated automatically according to the information the Trainer had access to. You
14
+ should probably proofread and complete it, then remove this comment. -->
15
 
16
+ # macro-sentiment-finbert
17
 
18
+ This model is a fine-tuned version of [ProsusAI/finbert](https://huggingface.co/ProsusAI/finbert) on the None dataset.
19
+ It achieves the following results on the evaluation set:
20
+ - Loss: 0.3450
21
+ - Accuracy: 0.8486
22
+ - F1 Macro: 0.8325
23
+ - F1 Weighted: 0.8515
24
 
25
+ ## Model description
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ More information needed
28
 
29
+ ## Intended uses & limitations
30
 
31
+ More information needed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ ## Training and evaluation data
34
 
35
+ More information needed
36
 
37
+ ## Training procedure
 
 
 
 
 
 
 
 
38
 
39
+ ### Training hyperparameters
40
 
41
+ The following hyperparameters were used during training:
42
+ - learning_rate: 2e-05
43
+ - train_batch_size: 16
44
+ - eval_batch_size: 32
45
+ - seed: 42
46
+ - gradient_accumulation_steps: 4
47
+ - total_train_batch_size: 64
48
+ - optimizer: Use OptimizerNames.ADAMW_TORCH_FUSED with betas=(0.9,0.999) and epsilon=1e-08 and optimizer_args=No additional optimizer arguments
49
+ - lr_scheduler_type: cosine
50
+ - lr_scheduler_warmup_steps: 31
51
+ - num_epochs: 2
52
 
53
+ ### Training results
54
 
55
+ | Training Loss | Epoch | Step | Validation Loss | Accuracy | F1 Macro | F1 Weighted |
56
+ |:-------------:|:-----:|:----:|:---------------:|:--------:|:--------:|:-----------:|
57
+ | 1.6807 | 1.0 | 314 | 0.3761 | 0.8246 | 0.8058 | 0.8300 |
58
+ | 1.1679 | 2.0 | 628 | 0.3450 | 0.8486 | 0.8325 | 0.8515 |
 
 
 
 
 
 
59
 
 
60
 
61
+ ### Framework versions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
+ - Transformers 5.6.2
64
+ - Pytorch 2.11.0+cu130
65
+ - Datasets 4.8.4
66
+ - Tokenizers 0.22.2