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

# Load the INT8 model (140 KB)
session = ort.InferenceSession("finsense_int8.onnx")

# Input: token IDs as int64, shape [batch, 128]
# Use the included vocab_map.json for tokenization
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

# Load FinBERT tokenizer (shared vocabulary base)
tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")

# Load pruned vocabulary map
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)
    # Remap to pruned vocabulary
    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)

# Run inference
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

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Dataset used to train ConstantQJ/constant-finsense-0.5

Evaluation results