privacy-law-classifier / source /cross_test.py
aitrainingdatabroker's picture
Add source/cross_test.py
5145eca verified
Raw History Blame Contribute Delete
1.73 kB
"""Score the business PII detector on text from a different generator (the HIPAA test set), 2026-10-29.
Its own test set comes from the same generators as its training data, so it scores perfectly; this shows how it does
on sentences written another way. Only the types both sets share are counted.
python models/cross_test.py
"""
import json
from pathlib import Path
from transformers import pipeline
ROOT = Path(__file__).resolve().parent
SAME = {"NAME": "PERSON", "PHONE": "PHONE", "EMAIL": "EMAIL", "DATE": "DATE", "IP_ADDRESS": "IP_ADDRESS", "URL": "URL"}
tagger = pipeline("token-classification", model=str(ROOT / "business-pii-detector/out"), aggregation_strategy="simple", device=0)
rows = [json.loads(l) for l in open(ROOT / "hipaa-phi-detector/data/test.jsonl", encoding="utf-8")]
tp = fp = fn = 0
for r in rows:
gold = {(SAME[e["label"]], e["start"], e["end"]) for e in r["entities"] if e["label"] in SAME}
pred = set()
for p in tagger(r["text"]):
if p["entity_group"] in SAME.values():
s = p["start"] + (len(r["text"][p["start"]:p["end"]]) - len(r["text"][p["start"]:p["end"]].lstrip()))
pred.add((p["entity_group"], s, p["end"]))
tp += len(gold & pred)
fp += len(pred - gold)
fn += len(gold - pred)
out = {"test": "hipaa-phi-detector test set, shared types only", "rows": len(rows), "precision": round(tp / (tp + fp), 3),
"recall": round(tp / (tp + fn), 3), "f1": round(2 * tp / (2 * tp + fp + fn), 3)}
print(json.dumps(out))
s = json.loads((ROOT / "business-pii-detector/scores.json").read_text(encoding="utf-8"))
s["cross_test"] = out
(ROOT / "business-pii-detector/scores.json").write_text(json.dumps(s, indent=2) + "\n", encoding="utf-8")