--- license: apache-2.0 base_model: ProsusAI/finbert tags: - financial-sentiment - social-media - reddit - wallstreetbets - text-classification pipeline_tag: text-classification language: - en --- # WSB-FinBERT A FinBERT model fine-tuned on r/wallstreetbets text for three-class sentiment classification (negative / neutral / positive). Off-the-shelf financial sentiment models are trained on formal financial English — earnings calls, analyst reports, newswire. Retail social-media text is a different register: irony, slang, emoji, and self-deprecation. On the held-out set below, vanilla FinBERT scores **below the majority-class floor**, i.e. worse than ignoring the text entirely. This model is a domain-adaptation check on that gap. This is the frozen checkpoint behind the results reported in *Beyond the Volume of Attention: Domain-Adapted Sentiment and the Content of Retail Investor Discussion* (ICAIF '26) — not a retrained copy. The replication package for that paper is distributed separately; this repository is the model only. ## Labels | id | label | |---|---| | 0 | negative | | 1 | neutral | | 2 | positive | ## Usage You do not need to download anything by hand. `transformers` fetches the weights on first use and caches them under `~/.cache/huggingface/`, so the first call takes a moment (~440 MB) and every call after that is instant. ``` pip install transformers torch ``` ```python from transformers import AutoTokenizer, AutoModelForSequenceClassification import torch model_id = "AnonymousResearchICAIF/wsb-finbert" tok = AutoTokenizer.from_pretrained(model_id) model = AutoModelForSequenceClassification.from_pretrained(model_id) text = "NVDA printing again, loaded calls for next week" inputs = tok(text, return_tensors="pt", truncation=True, max_length=128) with torch.no_grad(): probs = model(**inputs).logits.softmax(-1)[0] print({model.config.id2label[i]: round(p.item(), 3) for i, p in enumerate(probs)}) ``` A continuous sentiment score in [-1, 1] is formed as `P(positive) - P(negative)`. This is the `sentiment_wsb` variable used throughout the paper — the sign gives the direction and the magnitude gives the confidence. **Use `max_length=128`**: that is what the model was trained with, and longer inputs are truncated to it. For many texts at once, batch them rather than looping: ```python texts = ["...", "...", "..."] batch = tok(texts, return_tensors="pt", truncation=True, max_length=128, padding=True) with torch.no_grad(): p = model(**batch).logits.softmax(-1) scores = (p[:, 2] - p[:, 0]).tolist() ``` ## Training data 2,503 r/wallstreetbets posts and comments mentioning a fixed universe of AI-related tickers, labelled for sentiment by an LLM teacher (Claude) and split 70/15/15 stratified by label with seed 42 — 1,752 train / 375 validation / **376 test**. The sample is stratified across tickers and balanced 50/50 between the first and second halves of the collection period. ## Training procedure | | | |---|---| | Base model | `ProsusAI/finbert` | | Max sequence length | 128 | | Learning rate | 2e-5 | | Epochs | 4 | | Train batch size | 8 | | Weight decay | 0.01 | | Warmup ratio | 0.1 | | Seed | 42 | ## Evaluation On the 376 held-out texts: | Model | Accuracy | Macro F1 | |---|---|---| | **WSB-FinBERT (this model)** | **0.524** | **0.495** | | Vanilla `ProsusAI/finbert` | 0.410 | 0.400 | | Majority-class baseline ("always positive") | 0.434 | — | Cohen's κ = 0.252. Per-class (this model): | label | precision | recall | f1 | support | |---|---|---|---|---| | negative | 0.448 | 0.312 | 0.368 | 96 | | neutral | 0.513 | 0.513 | 0.513 | 117 | | positive | 0.557 | 0.656 | 0.603 | 163 | ## Limitations - **Absolute accuracy is modest.** 52.4% on a three-class problem is only ~9 points above the majority-class floor. The gain over vanilla FinBERT (+11.4 points) is the meaningful result; the model is not a strong standalone classifier. - **Labels are LLM-generated**, not human gold standard. They inherit the teacher's biases. They do correlate with *past* five-day returns, as a text-only annotator should, and show no positive correlation with *forward* returns (no evidence of look-ahead leakage). - **Narrow domain.** Trained on r/wallstreetbets text about a small universe of AI-related tickers over a specific period. Generalisation to other subreddits, other sectors, other periods, or to formal financial text is untested and unlikely. - **Positive skew.** The forum's labels run ~1.7 to 1 positive and the model inherits this (51.1% of predictions positive vs 43.4% in truth). Use within-entity demeaning if the level matters for your application. - Not investment advice; not suitable for trading decisions on its own.