--- language: - fr - en - ar - multilingual license: mit tags: - distilbert - ner - pii - privacy - gdpr - onnx - quantized - token-classification - tunisian pipeline_tag: token-classification model-index: - name: distilbert_pii_ner_yalen results: - task: type: token-classification metrics: - type: f1 value: 0.9042 name: F1 (test set) verified: false --- # distilbert_pii_ner_yalen — PII & NER Detector (9 classes · ONNX INT8) Fine-tuned and quantized version of [distilbert-base-multilingual-cased](https://huggingface.co/distilbert-base-multilingual-cased) for PII and Named Entity Recognition detection. Developed by [Yalen AI](https://huggingface.co/yalen-ai) as part of the Yalen Sentinel Pulse privacy protection platform. > **Model format**: ONNX INT8 quantized — 74% smaller than the original PyTorch model (139 MB vs 543 MB), with minimal accuracy loss. --- ## Model Description This model detects 9 classes of sensitive personal and financial information using BIO tagging. It supports multilingual input with strong performance on French, English, and Tunisian Arabic-Latin mixed text. ### Detected Entities | Entity | Description | Examples | |--------|-------------|---------| | PER | Person name | Ahmed Ben Salah, Marie Dupont | | ORG | Organization | TechCorp Tunisie, Banque de France | | LOC | Location | Tunis, Paris, avenue Habib Bourguiba | | MISC | Miscellaneous named entity | Visa, MasterCard | | IBAN | International Bank Account Number | TN59 1000 6035 1835 9848 3270, FR76 3000... | | CARD | Credit / Debit card number | 4532 1234 5678 9012 | | PHONE | Phone number (international formats) | +216 71 234 567, +33 1 23 45 67 89 | | EMAIL | Email address | ahmed.bensalah@techcorp.tn | | DATE | Date (any format) | 15/03/2025, 14 mars 2025, 12/2028 | --- ## Performance ### Global Scores (epoch 4 / 14,944 steps) | Precision | Recall | F1-Score | Accuracy | |-----------|--------|----------|----------| | 89.39% | 91.47% | **90.42%** | 98.87% | ### Per-Class F1 (evaluation set) | Entity | F1 | |--------|----| | PER | 100% | | ORG | 88.9% | | LOC | 80.0% | | IBAN | 100% | | CARD | 100% | | PHONE | 100% | | EMAIL | 100% | | DATE | 66.7% | --- ## Training Data | Source | Volume | Classes | |--------|--------|---------| | [Jean-Baptiste/wikiner_fr](https://huggingface.co/datasets/Jean-Baptiste/wikiner_fr) | 120,682 sentences | PER, ORG, LOC, MISC | | [ai4privacy/pii-masking-200k](https://huggingface.co/datasets/ai4privacy/pii-masking-200k) | 82,545 examples | IBAN, CARD, PHONE, EMAIL, DATE | | Faker (synthetic) | 40,000 examples (8,000 × 5 classes) | IBAN, CARD, PHONE, EMAIL, DATE | | **TOTAL** | **239,099 train · 17,538 val** | **9 classes** | --- ## Quick Start ### With Optimum (recommended for ONNX) ```python from optimum.onnxruntime import ORTModelForTokenClassification from transformers import AutoTokenizer, pipeline model = ORTModelForTokenClassification.from_pretrained( "yalen-ai/distilbert_pii_ner_yalen", file_name="model_quantized.onnx" ) tokenizer = AutoTokenizer.from_pretrained("yalen-ai/distilbert_pii_ner_yalen") ner = pipeline("token-classification", model=model, tokenizer=tokenizer, aggregation_strategy="simple") text = "Contact: ahmed.bensalah@techcorp.tn | Tel: +216 71 234 567 | IBAN: TN59 1000 6035 1835 9848 3270" results = ner(text) for entity in results: print(f"[{entity['entity_group']}] '{entity['word']}' (score: {entity['score']:.3f})") ``` Output: ``` [EMAIL] 'ahmed.bensalah@techcorp.tn' (score: 0.998) [PHONE] '+216 71 234 567' (score: 0.984) [IBAN] 'TN59 1000 6035 1835 9848 3270' (score: 0.757) ``` ### With ONNX Runtime directly ```python import onnxruntime as ort from transformers import AutoTokenizer import numpy as np import json # Load tokenizer and label map tokenizer = AutoTokenizer.from_pretrained("yalen-ai/distilbert_pii_ner_yalen") with open("config.json") as f: cfg = json.load(f) id2label = cfg["id2label"] # Load ONNX session session = ort.InferenceSession("model_quantized.onnx", providers=["CPUExecutionProvider"]) def predict(text): inputs = tokenizer(text, return_tensors="np", truncation=True, max_length=512) outputs = session.run(None, dict(inputs)) logits = outputs[0][0] token_ids = inputs["input_ids"][0] tokens = tokenizer.convert_ids_to_tokens(token_ids) labels = [id2label[str(np.argmax(l))] for l in logits] return [(tok, lbl) for tok, lbl in zip(tokens, labels) if lbl != "O" and not tok.startswith("[")] results = predict("Ahmed Ben Salah travaille chez TechCorp, IBAN: TN59 1000 6035 1835 9848 3270") for token, label in results: print(f" {token:<30} {label}") ``` --- ## Installation ```bash # For Optimum (ONNX Runtime) pip install optimum[onnxruntime] transformers # For direct ONNX Runtime usage pip install onnxruntime transformers ``` --- ## Model Architecture | Parameter | Value | |-----------|-------| | Base model | distilbert-base-multilingual-cased | | Architecture | DistilBertForTokenClassification | | Hidden size | 768 | | Attention heads | 12 | | Hidden layers | 6 | | Max tokens | 512 | | Vocab size | 119,547 | | Labels | 19 (O + 9×BIO) | | Format | ONNX INT8 (avx2 quantization) | ### Model Size Comparison | Stage | Format | Size | |-------|--------|------| | Fine-tuning | PyTorch FP32 | 543 MB | | Export | ONNX FP32 | 539 MB | | **Quantization** | **ONNX INT8 avx2** | **139 MB** | --- ## Label Map ```json { "0": "O", "1": "B-PER", "2": "I-PER", "3": "B-ORG", "4": "I-ORG", "5": "B-LOC", "6": "I-LOC", "7": "B-MISC", "8": "I-MISC", "9": "B-IBAN", "10": "I-IBAN", "11": "B-CARD", "12": "I-CARD", "13": "B-PHONE", "14": "I-PHONE", "15": "B-EMAIL", "16": "I-EMAIL", "17": "B-DATE", "18": "I-DATE" } ``` --- ## Intended Use - **Privacy compliance** (GDPR, Tunisian Data Protection Law) - **Document redaction** — anonymize sensitive documents before sharing - **Data loss prevention (DLP)** — detect accidental PII leaks in logs or messages - **Financial document processing** — extract IBAN/card numbers for validation - **Healthcare & insurance** — detect names, dates and contact information - **Edge deployment** — ONNX INT8 runs efficiently on CPU without GPU --- ## Limitations - Maximum input length: 512 tokens (long documents should be split by sentence or paragraph) - DATE detection is the weakest class (F1 ~67%) — dates in full French text ("14 mars 2025") are harder to detect than numeric formats - Card number detection works best with standard spacing (`XXXX XXXX XXXX XXXX`) - MISC class is inherited from WikiNER and may catch general named entities beyond PII --- ## About Yalen AI Yalen Sentinel Pulse is an AI-powered platform for PII detection and data privacy protection, developed by the Yalen AI team. It combines regex patterns, ML models, and NER to provide comprehensive sensitive data identification. - Platform: Yalen Sentinel Pulse - Contact: [hello@yalen.ai](mailto:hello@yalen.ai) --- ## License MIT — free for commercial and research use.