Alpaxa FinBERT-Tone 7-Class (Custom Head)
Repo: MasSolutions/Alpaxa-FinBERT-Tone-7class
Base encoder: ProsusAI/finbert
Frozen sentiment head: yiyanghkust/finbert-tone
Task head: Custom 7-way classifier (Financial/Earnings, Operations/Business, Accidents/Safety, Labor/Layoffs, Legal/Regulatory, Fraud/Misconduct, Other/External)
π Test Results (n = 688)
| Metric | Score |
|---|---|
| Accuracy | 0.846 |
| F1-macro | 0.681 |
Per-Class Performance
| Class | Precision | Recall | F1 | Support |
|---|---|---|---|---|
| Financial/Earnings | 0.809 | 0.885 | 0.845 | 148 |
| Operations/Business | 0.805 | 0.899 | 0.849 | 197 |
| Accidents/Safety | 0.333 | 0.200 | 0.250 | 5 |
| Labor/Layoffs | 0.909 | 0.870 | 0.889 | 23 |
| Legal/Regulatory | 0.875 | 0.875 | 0.875 | 56 |
| Fraud/Misconduct | 0.333 | 0.143 | 0.200 | 7 |
| Other/External | 0.914 | 0.806 | 0.857 | 252 |
π Usage
import os, json, sys, importlib.util, torch
from typing import Dict, List
from huggingface_hub import hf_hub_download
from transformers import AutoTokenizer
REPO = "MasSolutions/Alpaxa-FinBERT-Tone-7class"
TOPIC_LABELS: List[str] = [
"Financial/Earnings", # 0
"Operations/Business", # 1
"Accidents/Safety", # 2
"Labor/Layoffs", # 3
"Legal/Regulatory", # 4
"Fraud/Misconduct", # 5
"Other/External", # 6
]
SENTIMENT_LABELS = ["Neutral", "Positive", "Negative"]
def sanitize_cfg(cfg: Dict) -> Dict:
"""Keep only keys accepted by the model constructor."""
allowed = {
"encoder_ckpt",
"sentiment_ckpt",
"num_labels",
"use_mean_pool",
"use_focal",
"focal_gamma",
}
return {k: v for k, v in cfg.items() if k in allowed}
# 1) Download the modeling file and import it dynamically
model_py = hf_hub_download(REPO, "modeling_multi_head_finbert.py")
spec = importlib.util.spec_from_file_location("modeling_multi_head_finbert", model_py)
mod = importlib.util.module_from_spec(spec)
sys.modules["modeling_multi_head_finbert"] = mod
spec.loader.exec_module(mod)
MultiHeadFinBERT = mod.MultiHeadFinBERT
# 2) Load config / weights / tokenizer
cfg_path = hf_hub_download(REPO, "config.json")
state_path = None
try:
state_path = hf_hub_download(REPO, "model.safetensors")
use_safetensors = True
except Exception:
state_path = hf_hub_download(REPO, "model_state.pth")
use_safetensors = False
with open(cfg_path) as f:
cfg_raw = json.load(f)
cfg = sanitize_cfg(cfg_raw)
tok = AutoTokenizer.from_pretrained(REPO)
# 3) Build and load model
model = MultiHeadFinBERT(**cfg)
if use_safetensors:
from safetensors.torch import load_file as load_safetensors
state = load_safetensors(state_path, device="cpu")
else:
state = torch.load(state_path, map_location="cpu")
model.load_state_dict(state, strict=True)
model.eval()
# 4) Inference
texts = ["Delta flight crashed. 198 dead 2 missing."] # Test Headline
batch = tok(texts, return_tensors="pt", truncation=True, max_length=128, padding=True)
batch.pop("token_type_ids", None)
with torch.no_grad():
out = model(**batch)
topic_probs = out["logits"].softmax(-1) # [B, 7]
senti_probs = out["sentiment_logits"].softmax(-1) # [B, 3]
# 5) Pretty print with labels
for i, text in enumerate(texts):
tp = topic_probs[i]
sp = senti_probs[i]
pred_topic_idx = int(tp.argmax().item())
pred_senti_idx = int(sp.argmax().item())
print(f"\nText: {text}")
print(f"β Topic: {TOPIC_LABELS[pred_topic_idx]} (p={tp[pred_topic_idx]:.4f})")
print(f"β Sentiment: {SENTIMENT_LABELS[pred_senti_idx]} "
f"(neg={sp[0]:.3f}, neu={sp[1]:.3f}, pos={sp[2]:.3f})")
# Top-3 topics
topk = torch.topk(tp, k=min(3, tp.numel()))
print("Top-3 topic probs:")
for idx, prob in zip(topk.indices.tolist(), topk.values.tolist()):
print(f" {TOPIC_LABELS[idx]:<20} {prob:.4f}")
- Downloads last month
- 5
Model tree for MasSolutions/Alpaxa-FinBERT-Tone-7class
Base model
ProsusAI/finbert