Wilma / scripts /eval_local.py
winifred12's picture
v2 fine tune: length bias fixed, Nigerian accuracy regressed; do not deploy
7e72e1d
Raw History Blame Contribute Delete
2.98 kB
import csv, torch
from collections import defaultdict
from transformers import AutoTokenizer, AutoModelForSequenceClassification
MODELDIR = "models/distilbert_v2"
device = "mps" if torch.backends.mps.is_available() else "cpu"
tok = AutoTokenizer.from_pretrained(MODELDIR)
model = AutoModelForSequenceClassification.from_pretrained(MODELDIR).to(device).eval()
NAMES = ["legitimate", "scam"]
def predict(texts, bs=32):
out = []
for i in range(0, len(texts), bs):
enc = tok(texts[i:i+bs], truncation=True, padding=True, max_length=128, return_tensors="pt").to(device)
with torch.no_grad():
probs = torch.softmax(model(**enc).logits, dim=1)
for p in probs:
j = int(p.argmax())
out.append((NAMES[j], float(p[j])))
return out
print("=" * 70)
print("NIGERIAN SMS EVALUATION")
print("=" * 70)
rows = list(csv.DictReader(open("data/eval/nigerian_sms.csv", newline="", encoding="utf-8")))
preds = predict([r["text"] for r in rows])
tp = fp = fn = tn = 0
mistakes = []
for r, (lab, conf) in zip(rows, preds):
truth = r["label"].strip().lower()
if lab == "scam" and truth == "scam":
tp += 1
elif lab == "scam":
fp += 1
mistakes.append(("FALSE ALARM", conf, r["text"]))
elif truth == "scam":
fn += 1
mistakes.append(("MISSED SCAM", conf, r["text"]))
else:
tn += 1
prec = tp / max(1, tp + fp)
rec = tp / max(1, tp + fn)
f1 = 2 * prec * rec / max(1e-9, prec + rec)
acc = (tp + tn) / len(rows)
print("accuracy %.4f precision %.4f recall %.4f F1 %.4f" % (acc, prec, rec, f1))
print("caught %d false alarms %d missed %d correct legit %d" % (tp, fp, fn, tn))
print("")
print("BEFORE: accuracy 0.8000 precision 0.8333 recall 0.7500")
print("")
for kind, conf, text in mistakes:
print(" %s (%.3f) %s" % (kind, conf, text[:95]))
print("")
print("=" * 70)
print("LENGTH EXPERIMENT")
print("=" * 70)
rows = list(csv.DictReader(open("data/eval/length_experiment.csv", newline="", encoding="utf-8")))
preds = predict([r["text"] for r in rows])
res = defaultdict(dict)
for r, (lab, conf) in zip(rows, preds):
res[r["id"]][r["variant"]] = (lab, conf, len(r["text"]))
ORDER = ["short", "medium", "long"]
print("%-6s %-22s %-22s %-22s" % ("id", "short", "medium", "long"))
for rid in res:
cells = []
for v in ORDER:
d = res[rid].get(v)
cells.append("%s %.3f" % (d[0], d[1]) if d else "-")
print("%-6s %-22s %-22s %-22s" % (rid, cells[0], cells[1], cells[2]))
print("")
for v in ORDER:
ds = [res[r][v] for r in res if v in res[r]]
hits = sum(1 for d in ds if d[0] == "scam")
print("%-7s detected %d/%d (%3.0f%%) mean conf %.3f mean %d chars" % (
v, hits, len(ds), 100.0 * hits / len(ds),
sum(d[1] for d in ds) / len(ds), sum(d[2] for d in ds) / len(ds)))
print("")
print("BEFORE: short 0/8 (0%), medium 4/8 (50%), long 7/8 (88%)")
print("PASS CONDITION: detection flat across all three.")