Downloads · 30 days
5
15% of all-time downloads
fabriceyhc/Bio_ClinicalBERT-DrugDetector
Bio_ClinicalBERT-DrugDetector is a text classification model from fabriceyhc. Use it when you need a label for a piece of text. The card lists the license as mit.
A multi-label classifier fine-tuned from emilyalsentzer/BioClinicalBERT to detect substance involvement in death-certificate cause-of-death text, for overdose surveillance research (ROSLA pipeline).
Downloads · 30 days
5
15% of all-time downloads
All-time downloads
33
Public
Parameters
108M
433 MB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors433 MB · 100%
From the Hugging Face model README
A multi-label classifier fine-tuned from emilyalsentzer/Bio_ClinicalBERT to detect substance involvement in death-certificate cause-of-death text, for overdose surveillance research (ROSLA pipeline).
Given free-text cause-of-death fields, it predicts 10 binary labels:
Methamphetamine, Heroin, Cocaine, Fentanyl, Alcohol, Prescription.opioids, Any Opioids, Benzodiazepines, Others, Any Drugs
Any Opioids and Any Drugs are aggregate flags (true if any opioid / any substance is implicated, even when the specific drug isn't independently confirmed elsewhere).
Macro F1 = 0.9811 on a held-out external test set (3,335 records, disjoint from training data), evaluated with per-label decision thresholds (not the default 0.5 — see best_thresholds.json).
| Label | F1 | Precision | Recall | Support |
|---|---|---|---|---|
| Methamphetamine | 0.964 | 0.930 | 1.000 | 93 |
| Heroin | 0.987 | 0.975 | 1.000 | 78 |
| Cocaine | 0.995 | 0.990 | 1.000 | 381 |
| Fentanyl | 0.999 | 0.998 | 1.000 | 615 |
| Alcohol | 0.992 | 1.000 | 0.983 | 357 |
| Prescription.opioids | 0.992 | 0.992 | 0.992 | 129 |
| Any Opioids | 0.998 | 0.997 | 1.000 | 665 |
| Benzodiazepines | 0.995 | 0.991 | 1.000 | 105 |
| Others | 0.900 | 0.960 | 0.848 | 309 |
| Any Drugs | 0.988 | 0.997 | 0.979 | 967 |
This model was trained on normalized text, and needs the same normalization at inference time or performance will silently degrade. An earlier version of this model, evaluated without matching preprocessing, dropped from ~0.98 to ~0.78 macro F1 on the exact same test set — same model, same weights, just un-normalized input text.
Apply this function to your text before tokenizing:
import re
def clean_bert_text(value) -> str:
if value is None or (isinstance(value, float) and value != value): # NaN
return ""
s = str(value)
s = s.replace("\t", " ").replace("\n", " ").replace("\r", " ")
s = re.sub(r"\bNULL\b", " ", s, flags=re.IGNORECASE)
s = s.replace(", ", " ")
s = s.upper()
return re.sub(r"\s+", " ", s).strip()
This strips literal "NULL" placeholder tokens, tabs/newlines, a "comma after every word" tokenization artifact present in some upstream data sources, and forces uppercase (the training data has no lowercase examples, so casing is not a signal the model can use — normalizing avoids an artificial train/inference mismatch).
import json
import torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer
MODEL_ID = "fabriceyhc/Bio_ClinicalBERT-DrugDetector"
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
model.eval()
# Per-label decision thresholds -- do NOT use the default 0.5, thresholds
# were individually tuned per label on a held-out validation split.
import huggingface_hub
thresholds_path = huggingface_hub.hf_hub_download(MODEL_ID, "best_thresholds.json")
thresholds = json.load(open(thresholds_path))
text = clean_bert_text("Acute intoxication due to the combined effects of fentanyl and cocaine")
inputs = tokenizer(text, return_tensors="pt", padding="max_length", truncation=True)
with torch.no_grad():
probs = torch.sigmoid(model(**inputs).logits)[0]
for i, label in model.config.id2label.items():
prob = probs[int(i)].item()
pred = prob >= thresholds[label]
print(f"{label:<25} prob={prob:.3f} pred={pred}")
Fine-tuned on de-identified coroner/medical-examiner cause-of-death text (short phrases, e.g. "COMPLICATIONS OF FENTANYL AND COCAINE TOXICITY"), label-corrected via a consistency audit that checked for term/label agreement, logical-invariant violations between specific and aggregate columns, duplicate-text label conflicts, and negation. No names, addresses, or other directly identifying fields are present in the training text.
emilyalsentzer/Bio_ClinicalBERT (BERT-base architecture, 12 layers, 768 hidden, 12 heads)problem_type="multi_label_classification"), sigmoid + independent per-label thresholds rather than softmaxOthers (F1 0.900) is the weakest label — it's a catch-all category covering a long tail of less-common substances and has the least consistent training signal.Any Opioids/Any Drugs flags, not to a specific-drug column, matching how the underlying data was labeled.