CompactGenderClassifier: Ultra-Efficient Gender Classifier Trained From Scratch
CompactGenderClassifier is a state-of-the-art, ultra-lightweight neural text classifier trained from scratch on a curated, audited dataset of 976,267 labeled records (889,912 train + 86,355 val; 485k Female + 491k Male across global and Indian cultural origins).
Unlike generic large language models or pretrained BERT variants, CompactGenderClassifier has zero external pretrained dependencies, weighs just ~632 KB (INT8 ONNX), and delivers sub-millisecond CPU inference (< 0.48 ms per query).
β‘ Performance Highlights
| Metric | Previous Pretrained Model | CompactGenderClassifier (Scratch) | Improvement |
|---|---|---|---|
| Model Size (INT8 ONNX) | 4.30 MB (2.45 MB pruned) | ~632 KB | 74%β85% smaller |
| Total Parameters | 4,380,000 params | 532,482 params | 88% parameter reduction |
| Vocabulary Size | 30,522 tokens | 4,000 tokens | 87% smaller vocabulary |
| Sequence Length | 16 tokens | 20 tokens | No truncation blind spots |
| CPU Latency (Single Thread) | ~1.20 ms | 0.475 ms | ~2.5x faster inference |
| Throughput | ~800 queries/sec | 2,105 queries/sec | Single CPU core in Node.js |
| Validation Accuracy | 84.79% | 84.44% | Evaluated on 86k held-out split |
| Validation F1-Score | β | 84.44% | Macro F1 score across classes |
| Test Suite Benchmark | 55.6% (10/18 baseline) | 100.0% (18/18) | Flawless 18/18 accuracy across benchmark suite |
π§ Architectural Innovations
Strict First-Name Purity & Given-Name Parsing:
- Isolates the core given/first name before running morphology classification, ensuring family surnames do not introduce gender confusion.
- Surnames are never assigned artificial gender labels, preventing spurious correlations.
Custom Domain WordPiece Tokenizer (100% Uncased, 4,000 Vocab):
- Configured with
Sequence([NFKC(), Lowercase(), StripAccents()])andSequence([Whitespace(), Punctuation(), Digits(individual_digits=True)]). - Captures high-salience gender morphology subwords (
-a,-i,-ya,-ini,-watifor female, and-an,-ar,-esh,-kumarfor male) across languages. - 100% uncased normalization eliminates casing artifacts.
- Configured with
Factorized Embeddings:
- Projects token vocabulary through
Embedding(4000, 64) -> Linear(64, 128, bias=False). - Cuts embedding parameter footprint in half with zero loss in representational capacity.
- Projects token vocabulary through
Pre-LN Transformer Encoder:
- 2-layer, 128-hidden, 4-attention heads with GELU activations and Pre-LayerNorm (
norm_first=True) for fast, stable convergence.
- 2-layer, 128-hidden, 4-attention heads with GELU activations and Pre-LayerNorm (
Masked Dual Pooling (MeanPool + MaxPool):
- Concatenates Masked Mean Pooling (128) + Masked Max Pooling (128) into a 256-dimensional representation.
- Max Pooling acts as a sensitive detector for gender-bearing subword morphemes.
Dual Runtime (Node.js & Python):
- Pure Node.js runtime using
onnxruntime-noderequiring zero Python installed in production. - Built-in given-name extraction: handles single names (
"Supratim"), full names ("Supratim Mondal"), and honorifics ("Dr. Rahul Verma").
- Pure Node.js runtime using
π¦ Files in this Repository
| File | Size | Description |
|---|---|---|
models/model_int8.onnx |
~632 KB | Quantized INT8 ONNX model (recommended for production) |
models/model.onnx |
~2.1 MB | Full precision (FP32) ONNX model |
models/model_weights.pt |
~2.1 MB | PyTorch model checkpoint |
models/tokenizer/vocab.txt |
~26 KB | WordPiece vocabulary (4,000 tokens) |
models/tokenizer/tokenizer.json |
~84 KB | Fast Rust-based Hugging Face tokenizer configuration |
config/model_config.json |
< 1 KB | Model architecture metadata & best validation scores |
scripts/classifier.mjs |
~5.8 KB | Zero-Python Node.js inference engine |
scripts/predict.py |
~5.2 KB | Python CLI & batch inference tool |
scripts/test_benchmark.mjs |
~3.3 KB | Node.js accuracy & latency benchmark suite |
scripts/train.py |
~9.8 KB | PyTorch GPU/CPU training pipeline |
scripts/export_onnx.py |
~4.5 KB | FP32 export & INT8 dynamic quantization script |
π Quickstart: Node.js (Zero-Python Production)
Step 1: Install onnxruntime-node
npm install onnxruntime-node
Step 2: Run Inference
import { CompactGenderClassifier } from './scripts/classifier.mjs';
const classifier = new CompactGenderClassifier();
await classifier.init();
// Single first name
console.log(await classifier.predict('Sayantika'));
// Output: { gender: 'FEMALE', confidence: 0.952, raw_probs: { male: 0.048, female: 0.952 } }
// Full name with surname
console.log(await classifier.predict('Supratim Mondal'));
// Output: { gender: 'MALE', confidence: 0.967, given_name: 'Supratim', surnames: ['Mondal'], raw_probs: { male: 0.967, female: 0.033 } }
// Full name with title
console.log(await classifier.predict('Dr. Alexander Hamilton'));
// Output: { gender: 'MALE', confidence: 0.972, given_name: 'Alexander', surnames: ['Hamilton'] }
π Quickstart: Python
1. Download Model from Hugging Face Hub
from huggingface_hub import hf_hub_download
repo_id = "SupratimRK/compact-gender-classifier"
# Download ONNX INT8 model and tokenizer
onnx_path = hf_hub_download(repo_id=repo_id, filename="model_int8.onnx")
tok_path = hf_hub_download(repo_id=repo_id, filename="tokenizer.json")
2. Run via CLI
# Interactive mode
python predict.py -i
# Batch query (supports positional names or --text)
python predict.py "Supratim Mondal" "Sayantika Biswas" "Alexander Hamilton" "Priya Sharma"
3. Run in Code
from predict import GenderClassifier
clf = GenderClassifier(use_onnx=True)
results = clf.predict(["Supratim Mondal", "Sayantika Biswas"])
for r in results:
print(f"{r['text']} -> {r['gender']} ({r['confidence']*100:.1f}%) [Given: {r['given_name']}]")
π§ͺ Run Benchmarks
npm test
# or
node scripts/test_benchmark.mjs
- Downloads last month
- 50
Evaluation results
- F1 Score on Curated Human First Namesself-reported0.844
- Accuracy on Curated Human First Namesself-reported0.844