Constant FinSense 0.5 β 140 KB Financial Sentiment Analysis
A 3,109x compressed financial sentiment classifier distilled from FinBERT. Classifies financial text as positive, negative, or neutral in 140 KB.
FinSense vs FinBERT
| Model |
Accuracy |
Size |
Latency (CPU) |
Compression |
| FinBERT (ProsusAI) |
97.9% |
420 MB |
~8ms (GPU) |
1x |
| FinSense FP32 |
84.2% |
0.47 MB |
0.12ms |
894x |
| FinSense INT8 |
84.4% |
0.14 MB |
0.58ms |
3,109x |
84% accuracy at 140 KB. Runs on microcontrollers. No GPU required.
Quick Start
import onnxruntime as ort
import numpy as np
session = ort.InferenceSession("finsense_int8.onnx")
input_name = session.get_inputs()[0].name
dummy = np.zeros((1, 128), dtype=np.int64)
logits = session.run(None, {input_name: dummy})[0]
labels = ["negative", "neutral", "positive"]
pred = labels[np.argmax(logits[0])]
print(pred)
With Tokenization
import json
import onnxruntime as ort
import numpy as np
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
with open("vocab_map.json") as f:
vmap = json.load(f)
vocab_map = {int(k): v for k, v in vmap["map"].items()}
def tokenize(text, max_length=128):
tokens = tokenizer.tokenize(text)
ids = tokenizer.convert_tokens_to_ids(tokens)
unk = vocab_map.get(tokenizer.unk_token_id, 1)
cls = vocab_map.get(tokenizer.cls_token_id, unk)
sep = vocab_map.get(tokenizer.sep_token_id, unk)
remapped = [cls] + [vocab_map.get(i, unk) for i in ids[:max_length-2]] + [sep]
remapped += [0] * (max_length - len(remapped))
return np.array([remapped], dtype=np.int64)
session = ort.InferenceSession("finsense_int8.onnx")
labels = ["negative", "neutral", "positive"]
texts = [
"Revenue increased 15% year-over-year driven by strong demand",
"The company reported a significant decline in operating margins",
"Management maintained its full-year guidance unchanged",
]
for text in texts:
ids = tokenize(text)
logits = session.run(None, {"input_ids": ids})[0]
probs = np.exp(logits) / np.exp(logits).sum(axis=1, keepdims=True)
pred = labels[np.argmax(probs[0])]
conf = float(probs[0].max())
print(f"{pred} ({conf:.0%}): {text}")
Architecture
NanoCNN β the same architecture that powers Constant Edge 0.5, adapted for 3-class financial sentiment:
- Embedding: 32-dimensional, pruned vocabulary (2,729 financial tokens)
- Convolutions: 4 parallel Conv1d banks (filter sizes 2, 3, 4, 5), 64 filters each
- Bottleneck: Linear compression (256 β 16)
- Classifier: 16 β 48 β 3 (negative / neutral / positive)
- Parameters: 121,971
- Quantization: INT8 (post-training, ONNX Runtime)
Distillation Pipeline
ProsusAI/FinBERT (97.9%, 420 MB)
β Knowledge Distillation (T=10.77, Ξ±=0.30)
β NanoCNN Student (84.4%, 0.14 MB)
- Teacher: ProsusAI/finbert, evaluated at 97.94% on Financial PhraseBank (AllAgree split)
- Distillation: Optuna-optimized (20 trials) temperature and mixing weight
- Evaluation: 5-seed mean with standard deviations
Detailed Results
5-Seed Evaluation (FP32)
| Seed |
Test Accuracy |
F1 |
| 42 |
83.53% |
0.828 |
| 123 |
85.59% |
0.850 |
| 456 |
84.71% |
0.843 |
| 789 |
84.41% |
0.841 |
| 1024 |
82.65% |
0.819 |
| Mean |
84.18% Β± 1.01% |
0.836 |
INT8 Classification Report
| Class |
Precision |
Recall |
F1 |
Support |
| Negative |
0.800 |
0.696 |
0.744 |
46 |
| Neutral |
0.886 |
0.933 |
0.909 |
209 |
| Positive |
0.750 |
0.706 |
0.727 |
85 |
| Weighted Avg |
0.841 |
0.844 |
0.841 |
340 |
Inference Benchmarks
| Model |
Mean Latency |
P95 Latency |
Throughput |
| FP32 (0.47 MB) |
0.12ms |
0.14ms |
~8,300/sec |
| INT8 (0.14 MB) |
0.58ms |
0.71ms |
~1,700/sec |
Use Cases
- Algorithmic trading β sub-millisecond sentiment scoring on financial news feeds, no GPU required
- Bloomberg/Refinitiv terminals β on-device sentiment without API calls or data leaving the terminal
- Mobile trading apps β real-time sentiment on earnings releases, SEC filings, analyst reports
- Compliance monitoring β on-premise sentiment analysis for MiFID II / SEC audit requirements
- IoT financial displays β sentiment-aware tickers on embedded hardware
Training Details
- Dataset: Financial PhraseBank (AllAgree), 2,264 sentences from financial news
- Split: 70/15/15 stratified (1,584 train / 340 val / 340 test)
- Teacher: ProsusAI/finbert (BERT-base fine-tuned on financial sentiment)
- Hardware: NVIDIA RTX 4090 Laptop GPU (16 GB)
- Optuna: 20 trials, median pruner, best Ξ±=0.30, T=10.77
- Training: 30 epochs per seed, AdamW, cosine schedule with linear warmup
Model Files
| File |
Size |
Description |
finsense_int8.onnx |
140 KB |
INT8 quantized (recommended) |
finsense_fp32.onnx |
470 KB |
FP32 full precision |
vocab_map.json |
38 KB |
Pruned vocabulary mapping |
results.json |
3 KB |
Full benchmark results |
Citation
@misc{constantone2026finsense,
title={FinSense: 3109x Compressed Financial Sentiment Analysis for Edge Deployment},
author={ConstantOne AI},
year={2026},
url={https://huggingface.co/ConstantQJ/constant-finsense-0.5}
}
License
Apache 2.0 β use freely in commercial and non-commercial projects.
Links