Token Classification
Transformers
ONNX
Safetensors
English
distilbert
pii
privacy
experimental
datafog
Instructions to use DataFog/pii-en-65m with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use DataFog/pii-en-65m with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("token-classification", model="DataFog/pii-en-65m")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForTokenClassification tokenizer = AutoTokenizer.from_pretrained("DataFog/pii-en-65m") model = AutoModelForTokenClassification.from_pretrained("DataFog/pii-en-65m", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download reproduction/scripts/probe_model.py from DataFog/pii-en-65m: direct link, hf CLI and curl.
- Browser
- Download file 5.05 kB
-
https://huggingface.co/DataFog/pii-en-65m/resolve/5683ef559df6618f563375b632fdab7352ac1628/reproduction/scripts/probe_model.py
- Command line
-
hf download hf://DataFog/pii-en-65m@5683ef559df6618f563375b632fdab7352ac1628/reproduction/scripts/probe_model.py
-
curl -L -o probe_model.py https://huggingface.co/DataFog/pii-en-65m/resolve/5683ef559df6618f563375b632fdab7352ac1628/reproduction/scripts/probe_model.py
5.05 kB
| """Prove MPS update, checkpoint reload, dynamic ONNX export before full training.""" | |
| import json | |
| import sys | |
| import time | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1])) | |
| import numpy as np | |
| import onnxruntime as ort | |
| import torch | |
| from transformers import AutoModelForTokenClassification, AutoTokenizer | |
| from pii.core import BIO, LABELS, MODEL_REVISION | |
| torch.manual_seed(42) # Transformers TrainingArguments default seed. | |
| out = Path("artifacts/probe") | |
| out.mkdir(parents=True, exist_ok=True) | |
| tokenizer = AutoTokenizer.from_pretrained("artifacts/backbone", local_files_only=True) | |
| model = AutoModelForTokenClassification.from_pretrained("artifacts/backbone", num_labels=len(BIO), id2label=dict(enumerate(BIO)), label2id={v:k for k,v in enumerate(BIO)}, attn_implementation="eager", local_files_only=True).to("mps") | |
| optimizer = torch.optim.AdamW(model.parameters(), lr=2e-5, weight_decay=0.01) | |
| report = {"model_revision": MODEL_REVISION, "parameters": sum(p.numel() for p in model.parameters()), "max_length": model.config.max_position_embeddings, "precision":"float32", "device":"mps", "benchmarks":[]} | |
| before = model.classifier.weight.detach().clone() | |
| # Official HF recipe batch=16; measure both short and maximum-length inputs. | |
| for length in (32, model.config.max_position_embeddings): | |
| x = torch.full((16, length), 100, dtype=torch.long, device="mps") | |
| x[:,0], x[:,-1] = tokenizer.cls_token_id, tokenizer.sep_token_id | |
| y = torch.zeros_like(x) | |
| y[:,0], y[:,-1] = -100, -100 | |
| y[:,1] = 1 | |
| times = [] | |
| for stage in ("warmup", "measured"): | |
| optimizer.zero_grad(set_to_none=True) | |
| torch.mps.synchronize() | |
| start = time.perf_counter() | |
| loss = model(input_ids=x, attention_mask=torch.ones_like(x), labels=y).loss | |
| loss.backward() | |
| finite = all(torch.isfinite(p.grad).all().item() for p in model.parameters() if p.grad is not None) | |
| optimizer.step() | |
| torch.mps.synchronize() | |
| times.append(time.perf_counter()-start) | |
| assert torch.isfinite(loss).item() and finite | |
| report["benchmarks"].append({"batch_size":16,"sequence_length":length,"step_seconds":times,"loss":loss.item(),"allocated_bytes":torch.mps.current_allocated_memory(),"driver_bytes":torch.mps.driver_allocated_memory()}) | |
| assert not torch.equal(before, model.classifier.weight) | |
| model.eval() | |
| sample = tokenizer("🙂 José Smith: jose@example.com", return_tensors="pt") | |
| sample = {k:v.to("mps") for k,v in sample.items() if k in ("input_ids","attention_mask")} | |
| with torch.no_grad(): | |
| reference = model(**sample).logits.cpu() | |
| start = time.perf_counter() | |
| model.save_pretrained(out / "checkpoint") | |
| torch.save({"optimizer":optimizer.state_dict(),"rng":torch.get_rng_state(),"mps_rng":torch.mps.get_rng_state()}, out / "resume.pt") | |
| report["checkpoint_seconds"] = time.perf_counter()-start | |
| del optimizer | |
| model = model.to("cpu") | |
| reloaded = AutoModelForTokenClassification.from_pretrained(out / "checkpoint", local_files_only=True, attn_implementation="eager").to("mps").eval() | |
| with torch.no_grad(): | |
| actual = reloaded(**sample).logits.cpu() | |
| report["reload_max_abs_difference"] = (actual-reference).abs().max().item() | |
| assert torch.equal(actual,reference) | |
| del reloaded | |
| torch.mps.empty_cache() | |
| tokenizer.save_pretrained(out) | |
| (out / "config.json").write_text(json.dumps({"labels":LABELS,"max_length":model.config.max_position_embeddings,"stride":0,"model_revision":MODEL_REVISION},indent=2)) | |
| class Export(torch.nn.Module): | |
| def __init__(self, model): | |
| super().__init__() | |
| self.model=model | |
| def forward(self, input_ids, attention_mask): | |
| return self.model(input_ids=input_ids,attention_mask=attention_mask).logits | |
| sample = {k:v.cpu() for k,v in sample.items()} | |
| torch.onnx.export(Export(model).eval(), (sample["input_ids"],sample["attention_mask"]), str(out / "model.onnx"), input_names=["input_ids","attention_mask"], output_names=["logits"], dynamic_axes={"input_ids":{0:"batch",1:"sequence"},"attention_mask":{0:"batch",1:"sequence"},"logits":{0:"batch",1:"sequence"}}, opset_version=17, dynamo=False) | |
| session=ort.InferenceSession(str(out / "model.onnx"),providers=["CPUExecutionProvider"]) | |
| report["export_checks"]=[] | |
| for text in ("", "Alice Smith", "🙂 José Smith: jose@example.com", "Long ticket. " * 150): | |
| encoded=tokenizer(text,return_tensors="pt",truncation=True,max_length=model.config.max_position_embeddings) | |
| encoded={k:v for k,v in encoded.items() if k in ("input_ids","attention_mask")} | |
| with torch.no_grad(): | |
| logits=model(**encoded).logits.numpy() | |
| actual=session.run(None,{k:v.numpy() for k,v in encoded.items()})[0] | |
| report["export_checks"].append({"tokens":encoded["input_ids"].shape[1],"max_abs_logit_difference":float(np.max(np.abs(logits-actual))),"argmax_identical":bool(np.array_equal(logits.argmax(-1),actual.argmax(-1)))}) | |
| assert np.array_equal(logits.argmax(-1),actual.argmax(-1)) | |
| (out / "evidence.json").write_text(json.dumps(report,indent=2)+"\n") | |
| print(json.dumps(report,indent=2),flush=True) | |