Downloads · 30 days
12
13% of all-time downloads
lakresi/toxic-comment-moderator
toxic-comment-moderator is a text classification model from lakresi. Use it when you need a label for a piece of text. It is set up for transformers. The card lists the license as apache-2.0.
A DistilBERT model fine tuned for multi label toxic comment classification across six categories. Trained on the Jigsaw Toxic Comment Classification dataset. Deployed as a production REST API.
Downloads · 30 days
12
13% of all-time downloads
All-time downloads
96
Public
Parameters
67M
268 MB on disk
Likes
1
Public
Click a slice to open those files.
.safetensors268 MB · 100%
From the Hugging Face model README
A DistilBERT model fine tuned for multi label toxic comment classification across six categories. Trained on the Jigsaw Toxic Comment Classification dataset. Deployed as a production REST API.
distilbert-base-uncased fine tuned for multi label classification of toxic content. A linear classification head maps the CLS token representation to six independent output logits, one per toxicity category. Sigmoid activation produces per label probabilities between 0 and 1. Each label is classified independently so a comment can be flagged for multiple categories simultaneously.
Trained with BCEWithLogitsLoss and per label pos_weight to handle significant class imbalance. Per label decision thresholds were tuned on the validation set post training and stored in thresholds.json.
Classifying text across six toxicity categories for content moderation pipelines. The model accepts raw English text and returns per label probabilities and binary flags based on tuned decision thresholds.
Can be used as a baseline for further fine tuning on domain specific moderation tasks. The model weights and tokenizer can be loaded directly via HuggingFace Transformers as shown in the How to Get Started section below.
The model was evaluated against a synthetic probe set of 1,400 sentences spanning 25 demographic groups across religion, race and ethnicity, gender and sexuality, and nationality.
12 of 1,400 sentences (0.9%) were flagged. All flags were on the toxic label only and concentrated entirely in three groups: Gay, Lesbian, and Transgender. No sentence from any of the other 22 groups tested was flagged in any category.
The effect is driven by a copula construction stating identity directly. "The new manager is Gay" scored 0.818 toxic probability. The structurally identical "The new manager is Muslim" scored 0.007. This is a documented artifact of the Jigsaw training corpus where constructions like "that's so gay" are disproportionately represented as insults, causing the model to associate the is/are + LGBTQ+ identity term pattern with toxicity independent of surrounding sentiment or context.
Additional limitations:
Do not use this model for automated content removal on sentences that state an LGBTQ+ identity using an is/are construction. Route these to human review instead. A post hoc calibration layer or allowlist rule for this specific construction is a reasonable short term mitigation before any automated action is taken.
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from huggingface_hub import hf_hub_download
import torch
import json
model_name = "lakresi/toxic-comment-moderator"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name)
model.eval()
file_path = hf_hub_download(repo_id=model_name, filename="thresholds.json")
with open(file_path) as f:
thresholds = json.load(f)
label_cols = ["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"]
def classify(text: str):
inputs = tokenizer(
text,
return_tensors="pt",
truncation=True,
padding="max_length",
max_length=512
)
with torch.no_grad():
logits = model(**inputs).logits
probs = torch.sigmoid(logits).squeeze().tolist()
return {
label: {
"probability": round(prob, 4),
"flagged": prob >= thresholds[label]
}
for label, prob in zip(label_cols, probs)
}
result = classify("You are absolutely worthless and should be ashamed of yourself")
print(result)
Jigsaw Toxic Comment Classification Challenge dataset. Approximately 145k training examples and 16k validation examples. Wikipedia comments labeled across six binary toxicity categories.
Class distribution is highly imbalanced: toxic appears in ~10.2% of comments, obscene in ~5.9%, insult in ~4.9%, severe_toxic in ~1.0%, identity_hate in ~0.9%, and threat in ~0.3%. Per label pos_weight was applied inversely proportional to each label's positive frequency to address this.
Text tokenized with the distilbert-base-uncased tokenizer. Maximum sequence length of 512 tokens with truncation and padding. Comments exceeding 512 tokens are truncated from the right.
16,180 held out examples from the Jigsaw Toxic Comment Classification dataset, stratified by label to preserve class distribution.
Performance disaggregated by toxicity category. Rare labels evaluated separately given their low positive frequency.
F1 score per label and overall macro F1. ROC AUC to measure discriminative capability independent of threshold. Both metrics reported because the model can have high ROC AUC (strong ranking ability) while having lower F1 macro (threshold sensitivity), which is exactly what was observed here.
Epoch by epoch training dynamics:
| Epoch | Train Loss | Eval Loss | F1 Macro | ROC AUC |
|---|---|---|---|---|
| 1 | 3.917 | 1.598 | 0.632 | 0.989 |
| 2 | 1.438 | 1.546 | 0.670 | 0.990 |
| 3 | 1.116 | 1.687 | 0.671 | 0.989 |
| 4 | 0.857 | 1.880 | 0.684 | 0.987 |
| 5 | 0.697 | 1.934 | 0.687 | 0.987 |
Per label results after threshold tuning:
| Category | Threshold | F1 Score | Class Frequency |
|---|---|---|---|
| obscene | 0.44 | 0.849 | ~5.9% |
| toxic | 0.52 | 0.840 | ~10.2% |
| insult | 0.52 | 0.765 | ~4.9% |
| identity_hate | 0.26 | 0.589 | ~0.9% |
| threat | 0.36 | 0.561 | ~0.3% |
| severe_toxic | 0.46 | 0.558 | ~1.0% |
| Overall | 0.687 macro / 0.987 ROC AUC |
Strong performance on frequent labels (toxic, obscene, insult) with F1 above 0.76. Rare labels (threat, severe_toxic, identity_hate) underperform due to data scarcity rather than modeling limitations, as evidenced by the consistently high ROC AUC of 0.987 across all labels. Per label threshold tuning meaningfully improved F1 over the default 0.5 cutoff, particularly for rare labels where lower thresholds improve recall at acceptable precision cost.
distilbert-base-uncased with a single linear classification head. Input text is tokenized and passed through 6 transformer layers. The CLS token representation from the final layer is passed through the linear head to produce 6 logits. Sigmoid activation converts logits to independent per label probabilities. Binary cross entropy loss with logits and per label positive weighting.
2x NVIDIA RTX 3090 (24GB VRAM each) via Vast.ai. Multi GPU training managed by HuggingFace Accelerate.
Full technical breakdown including training code, bias analysis methodology, API documentation, and Docker deployment instructions are available in the GitHub repository.
Lloyd Akresi