Text Classification
Transformers
Joblib
Safetensors
bert
sentiment-analysis
finance
macroeconomics
climate
esg
policy
ensemble
dictionary
finbert
Eval Results (legacy)
text-embeddings-inference
Instructions to use peyterho/macro-sentiment-finbert with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use peyterho/macro-sentiment-finbert with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="peyterho/macro-sentiment-finbert")# Load model directly from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("peyterho/macro-sentiment-finbert") model = AutoModelForSequenceClassification.from_pretrained("peyterho/macro-sentiment-finbert", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Add Google Colab / Kaggle getting started section with complete install steps
Browse files
README.md
CHANGED
|
@@ -156,9 +156,14 @@ The fusion weights are **crisis-adaptive**: when the crisis dictionary fires str
|
|
| 156 |
|
| 157 |
## Quick Start
|
| 158 |
|
| 159 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
|
| 161 |
```python
|
|
|
|
| 162 |
from transformers import pipeline
|
| 163 |
|
| 164 |
classifier = pipeline("text-classification", model="peyterho/macro-sentiment-finbert", top_k=None)
|
|
@@ -167,7 +172,15 @@ print(result)
|
|
| 167 |
# [[{'label': 'positive', 'score': 0.72}, {'label': 'neutral', 'score': 0.21}, {'label': 'negative', 'score': 0.07}]]
|
| 168 |
```
|
| 169 |
|
| 170 |
-
### Full Pipeline (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
|
| 172 |
```python
|
| 173 |
from macro_sentiment import MacroSentimentPipeline
|
|
@@ -194,7 +207,132 @@ result = pipe("Die EZB signalisiert Geduld bei kΓΌnftigen Zinssenkungen.")
|
|
| 194 |
print(result.summary())
|
| 195 |
```
|
| 196 |
|
| 197 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
|
| 199 |
Every call returns a `MacroSentimentResult` with these fields:
|
| 200 |
|
|
@@ -213,21 +351,7 @@ Every call returns a `MacroSentimentResult` with these fields:
|
|
| 213 |
| `henry_polarity` | [-1, +1] | Henry earnings tone score |
|
| 214 |
| `climate_exposure` | [0, 1] | Climate keyword density (Sautner-style) |
|
| 215 |
|
| 216 |
-
##
|
| 217 |
-
|
| 218 |
-
```python
|
| 219 |
-
texts = [
|
| 220 |
-
"GDP growth exceeded expectations at 3.2% annualized.",
|
| 221 |
-
"Credit markets froze as contagion fears spread across European banks.",
|
| 222 |
-
"Solar installations surged 40% year-over-year globally.",
|
| 223 |
-
]
|
| 224 |
-
results = pipe.score_batch(texts, mode="routed")
|
| 225 |
-
for text, r in zip(texts, results):
|
| 226 |
-
print(f"{r.summary()}")
|
| 227 |
-
print(f" β {text[:80]}...\n")
|
| 228 |
-
```
|
| 229 |
-
|
| 230 |
-
### Scoring Modes
|
| 231 |
|
| 232 |
```python
|
| 233 |
# "routed" (default) β topic router selects best head
|
|
|
|
| 156 |
|
| 157 |
## Quick Start
|
| 158 |
|
| 159 |
+
There are two ways to use this model β pick the one that fits your needs:
|
| 160 |
+
|
| 161 |
+
### Option A: Standalone FinBERT (classification only)
|
| 162 |
+
|
| 163 |
+
If you just need positive/negative/neutral labels, use the model directly β no repo cloning required:
|
| 164 |
|
| 165 |
```python
|
| 166 |
+
# pip install transformers torch
|
| 167 |
from transformers import pipeline
|
| 168 |
|
| 169 |
classifier = pipeline("text-classification", model="peyterho/macro-sentiment-finbert", top_k=None)
|
|
|
|
| 172 |
# [[{'label': 'positive', 'score': 0.72}, {'label': 'neutral', 'score': 0.21}, {'label': 'negative', 'score': 0.07}]]
|
| 173 |
```
|
| 174 |
|
| 175 |
+
### Option B: Full Pipeline (multi-signal analysis)
|
| 176 |
+
|
| 177 |
+
For the complete system β topic routing, policy stance, crisis signals, climate scoring, and dictionaries β you need to clone this repo since the pipeline code lives inside it:
|
| 178 |
+
|
| 179 |
+
```bash
|
| 180 |
+
git clone https://huggingface.co/peyterho/macro-sentiment-finbert
|
| 181 |
+
cd macro-sentiment-finbert
|
| 182 |
+
pip install -r requirements.txt
|
| 183 |
+
```
|
| 184 |
|
| 185 |
```python
|
| 186 |
from macro_sentiment import MacroSentimentPipeline
|
|
|
|
| 207 |
print(result.summary())
|
| 208 |
```
|
| 209 |
|
| 210 |
+
## Use in Google Colab / Kaggle
|
| 211 |
+
|
| 212 |
+
Copy-paste these cells into a notebook. Both work on Colab (free tier) and Kaggle.
|
| 213 |
+
|
| 214 |
+
### Cell 1 β Standalone FinBERT only
|
| 215 |
+
|
| 216 |
+
```python
|
| 217 |
+
!pip install -q transformers torch
|
| 218 |
+
|
| 219 |
+
from transformers import pipeline
|
| 220 |
+
|
| 221 |
+
classifier = pipeline("text-classification", model="peyterho/macro-sentiment-finbert", top_k=None)
|
| 222 |
+
|
| 223 |
+
# Try it
|
| 224 |
+
texts = [
|
| 225 |
+
"Tesla shares surged 15% after crushing earnings expectations.",
|
| 226 |
+
"The Federal Reserve raised rates by 75bps citing persistent inflation.",
|
| 227 |
+
"Markets crashed amid recession fears and massive layoffs.",
|
| 228 |
+
"The company reported quarterly results in line with analyst estimates.",
|
| 229 |
+
]
|
| 230 |
+
|
| 231 |
+
for text in texts:
|
| 232 |
+
result = classifier(text)[0]
|
| 233 |
+
top = max(result, key=lambda x: x["score"])
|
| 234 |
+
print(f'{top["label"]:>8s} ({top["score"]:.2f}) {text}')
|
| 235 |
+
```
|
| 236 |
+
|
| 237 |
+
### Cell 1 β Full Pipeline (with policy stance, crisis signals, climate scoring)
|
| 238 |
+
|
| 239 |
+
```python
|
| 240 |
+
# Install dependencies and clone the repo
|
| 241 |
+
!pip install -q transformers torch pysentiment2 scikit-learn numpy pandas datasets accelerate huggingface_hub
|
| 242 |
+
!git clone https://huggingface.co/peyterho/macro-sentiment-finbert /content/macro-sentiment-finbert
|
| 243 |
+
|
| 244 |
+
import sys
|
| 245 |
+
sys.path.insert(0, "/content/macro-sentiment-finbert")
|
| 246 |
+
```
|
| 247 |
+
|
| 248 |
+
### Cell 2 β Score any text
|
| 249 |
+
|
| 250 |
+
```python
|
| 251 |
+
from macro_sentiment import MacroSentimentPipeline
|
| 252 |
+
|
| 253 |
+
pipe = MacroSentimentPipeline(device="cpu")
|
| 254 |
+
|
| 255 |
+
texts = [
|
| 256 |
+
"Markets rallied on strong earnings, with the S&P 500 hitting record highs.",
|
| 257 |
+
"The ECB raised rates by 25 basis points, citing persistent inflation pressures.",
|
| 258 |
+
"The company committed to net-zero emissions by 2040 through renewable energy investments.",
|
| 259 |
+
"Credit markets froze as contagion fears spread across European banks.",
|
| 260 |
+
"Die EZB signalisiert Geduld bei kΓΌnftigen Zinssenkungen.",
|
| 261 |
+
]
|
| 262 |
+
|
| 263 |
+
for text in texts:
|
| 264 |
+
result = pipe(text)
|
| 265 |
+
print(result.summary())
|
| 266 |
+
print(f" β {text}\n")
|
| 267 |
+
```
|
| 268 |
+
|
| 269 |
+
### Cell 3 β Explore the full structured output
|
| 270 |
+
|
| 271 |
+
```python
|
| 272 |
+
result = pipe("Fed signals two more rate cuts before year-end, a dovish surprise that lifted equities.")
|
| 273 |
+
|
| 274 |
+
print(f"Macro sentiment: {result.macro_sentiment:+.3f}")
|
| 275 |
+
print(f"Financial sentiment:{result.financial_sentiment:+.3f}")
|
| 276 |
+
print(f"Policy stance: {result.policy_stance:+.3f} (negative=dovish, positive=hawkish)")
|
| 277 |
+
print(f"Crisis signal: {result.crisis_signal:.3f}")
|
| 278 |
+
print(f"Climate sentiment: {result.climate_sentiment:+.3f}")
|
| 279 |
+
print(f"Uncertainty: {result.uncertainty:.3f}")
|
| 280 |
+
print(f"Confidence: {result.confidence:.3f}")
|
| 281 |
+
print(f"Domain: {result.detected_domain}")
|
| 282 |
+
print(f"Head used: {result.head_used}")
|
| 283 |
+
print(f"LM polarity: {result.lm_polarity:+.3f}")
|
| 284 |
+
print(f"Henry polarity: {result.henry_polarity:+.3f}")
|
| 285 |
+
print(f"Climate exposure: {result.climate_exposure:.3f}")
|
| 286 |
+
```
|
| 287 |
+
|
| 288 |
+
### Cell 4 β Batch scoring with pandas
|
| 289 |
+
|
| 290 |
+
```python
|
| 291 |
+
import pandas as pd
|
| 292 |
+
|
| 293 |
+
headlines = [
|
| 294 |
+
"Strong jobs report pushes markets to record highs",
|
| 295 |
+
"Tech earnings mixed as AI spending soars",
|
| 296 |
+
"Fed signals patience on rate cuts, markets dip",
|
| 297 |
+
"Retail sales disappoint, recession fears resurface",
|
| 298 |
+
"Green bond issuance hit $500B as investors pivot to sustainable fixed income",
|
| 299 |
+
"Bank of Japan holds rates steady in surprise decision",
|
| 300 |
+
]
|
| 301 |
+
|
| 302 |
+
results = pipe.score_batch(headlines, mode="routed")
|
| 303 |
+
|
| 304 |
+
df = pd.DataFrame([{
|
| 305 |
+
"text": t,
|
| 306 |
+
"sentiment": r.macro_sentiment,
|
| 307 |
+
"policy": r.policy_stance,
|
| 308 |
+
"crisis": r.crisis_signal,
|
| 309 |
+
"climate": r.climate_sentiment,
|
| 310 |
+
"domain": r.detected_domain,
|
| 311 |
+
"head": r.head_used,
|
| 312 |
+
} for t, r in zip(headlines, results)])
|
| 313 |
+
|
| 314 |
+
print(df.to_string(index=False))
|
| 315 |
+
```
|
| 316 |
+
|
| 317 |
+
### Cell 5 β Dictionary-only mode (no GPU needed, instant)
|
| 318 |
+
|
| 319 |
+
```python
|
| 320 |
+
# No transformer models loaded β uses only the four dictionaries
|
| 321 |
+
result = pipe.score("The central bank cut rates amid fears of a deepening recession.", mode="dict_only")
|
| 322 |
+
print(result.summary())
|
| 323 |
+
print(f"LM polarity: {result.lm_polarity:+.3f}")
|
| 324 |
+
print(f"Henry polarity: {result.henry_polarity:+.3f}")
|
| 325 |
+
print(f"Policy stance: {result.policy_stance:+.3f}")
|
| 326 |
+
print(f"Crisis signal: {result.crisis_signal:.3f}")
|
| 327 |
+
```
|
| 328 |
+
|
| 329 |
+
> **π‘ Notes:**
|
| 330 |
+
> - The full pipeline lazy-loads transformer models on first use. First call takes 30β60 seconds to download (~800MB across 4 models). Subsequent calls are fast.
|
| 331 |
+
> - `mode="routed"` (default) loads only 1 model per call. `mode="all"` loads all 4 models (~2GB RAM).
|
| 332 |
+
> - For Colab free tier, `mode="routed"` works fine. For `mode="all"`, use a GPU runtime to avoid OOM.
|
| 333 |
+
> - On Kaggle, enable "Internet" in notebook settings (Settings β Internet β On) so models can download.
|
| 334 |
+
|
| 335 |
+
## Structured Output
|
| 336 |
|
| 337 |
Every call returns a `MacroSentimentResult` with these fields:
|
| 338 |
|
|
|
|
| 351 |
| `henry_polarity` | [-1, +1] | Henry earnings tone score |
|
| 352 |
| `climate_exposure` | [0, 1] | Climate keyword density (Sautner-style) |
|
| 353 |
|
| 354 |
+
## Scoring Modes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
|
| 356 |
```python
|
| 357 |
# "routed" (default) β topic router selects best head
|