Text Classification
Transformers
ONNX
Safetensors
Transformers.js
modernbert
hate-speech
hate-speech-detection
content-moderation
trust-and-safety
multi-label-classification
mmbert
text-embeddings-inference
Instructions to use Horizon-Labs/multilingual-hate-speech-base with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Horizon-Labs/multilingual-hate-speech-base with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Horizon-Labs/multilingual-hate-speech-base")# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForSequenceClassification tokenizer = AutoTokenizer.from_pretrained("Horizon-Labs/multilingual-hate-speech-base") model = AutoModelForSequenceClassification.from_pretrained("Horizon-Labs/multilingual-hate-speech-base", device_map="auto") - Transformers.js
How to use Horizon-Labs/multilingual-hate-speech-base with Transformers.js:
// npm i @huggingface/transformers import { pipeline } from '@huggingface/transformers'; // Allocate pipeline const pipe = await pipeline('text-classification', 'Horizon-Labs/multilingual-hate-speech-base'); - Notebooks
- Google Colab
- Kaggle
File size: 4,761 Bytes
c1e5dc4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | """Evaluate hate-speech classifiers on hate/evals. python hate/eval_hate.py --models SPEC,SPEC --evals hate/evals --out R.json
SPEC = model[::label] picks the output used as the hate score (default: the label named hate/hateful/HATE/HATEFUL, or the
non-negative class of a binary model); model::!label uses 1 - P(label). Multi-label models (problem_type) use sigmoid, others softmax.
Per set: ROC AUC and F1 at 0.5 of the hate score; MHC also per functionality (accuracy at 0.5); MHS also target-group AUC on its
hateful comments when the model has target_<group> outputs. Summary keys: _mhc_mean_auc (11 languages), _mhc_mean_f1, _real_mean_auc
(mhs, hatexplain, kmhas), _heldout_real_mean_auc (hs18, ethos, olidbr, kmhas; the v2 gate)."""
import argparse, glob, json, os
import numpy as np, pandas as pd, torch
from transformers import AutoModelForSequenceClassification, AutoTokenizer
import sys; sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from metrics import auc, f1
ap = argparse.ArgumentParser()
ap.add_argument("--models", required=True); ap.add_argument("--evals", required=True); ap.add_argument("--out", required=True)
ap.add_argument("--bs", type=int, default=64); ap.add_argument("--max_len", type=int, default=512)
args = ap.parse_args()
POS = {"hate", "hateful", "hatespeech", "hate_speech"}
NEG = {"nothate", "not-hate", "non_hate", "not", "label_0", "neutral", "normal", "not_hate"}
HELD = ("hs18", "ethos", "olidbr", "kmhas") # v2 gate sets (hate/build_evals2.py + K-MHaS)
G = ["race", "religion", "origin", "gender", "sexuality", "age", "disability"]
EV = {os.path.basename(p)[:-8]: pd.read_parquet(p) for p in sorted(glob.glob(f"{args.evals}/*.parquet"))}
res = json.load(open(args.out)) if os.path.exists(args.out) else {}
for spec in args.models.split(","):
path, _, lab = spec.partition("::")
try:
tok = AutoTokenizer.from_pretrained(path)
m = AutoModelForSequenceClassification.from_pretrained(path, torch_dtype=torch.bfloat16).cuda().eval()
except Exception as e:
print(spec, "LOAD FAILED", repr(e)[:300], flush=True); continue
labels = [m.config.id2label[i] for i in range(m.config.num_labels)]; low = [l.lower() for l in labels]
multi = m.config.problem_type == "multi_label_classification"
neg = lab.startswith("!"); lab = lab.lstrip("!")
if lab:
col = labels.index(lab)
else:
col = next((i for i, l in enumerate(low) if l in POS), None)
if col is None and len(labels) == 2:
col = next(i for i, l in enumerate(low) if l not in NEG)
tcols = {g: labels.index(f"target_{g}") for g in G if f"target_{g}" in labels}
print(spec, "labels", labels, "multi", multi, "col", col, "neg", neg, flush=True)
@torch.no_grad()
def scores(texts):
out = np.zeros((len(texts), len(labels))); order = np.argsort([len(t) for t in texts])
for s in range(0, len(texts), args.bs):
b = order[s:s + args.bs]
e = tok([texts[i] for i in b], truncation=True, max_length=args.max_len, padding=True, return_tensors="pt")
lo = m(**{k: v.cuda() for k, v in e.items() if k in ("input_ids", "attention_mask")}).logits.float()
out[b] = (torch.sigmoid(lo) if multi else torch.softmax(lo, -1)).cpu().numpy()
return out
r = {"labels": labels, "col": labels[col], "neg": neg}
for name, df in EV.items():
S = scores(df.text.tolist()); s = 1 - S[:, col] if neg else S[:, col]; y = df.hate.values
r[name] = dict(n=len(df), auc=auc(y, s), f1_05=f1(y, s >= 0.5), fpr_05=float((s[y == 0] >= 0.5).mean()))
if name.startswith("mhc_"):
r[name]["func_acc"] = {fn: float(((s[g.index] >= 0.5) == g.hate.values.astype(bool)).mean()) for fn, g in df.groupby("functionality")}
if name == "mhs" and tcols:
h = df.hate.values == 1
r[name]["target_auc"] = {g: auc(df[f"target_{g}"].values[h], S[h, c]) for g, c in tcols.items()}
print(spec, name, {k: (round(v, 4) if isinstance(v, float) else v) for k, v in r[name].items() if k in ("auc", "f1_05", "fpr_05")}, flush=True)
mhc = [k for k in r if k.startswith("mhc_")]
if mhc:
r["_mhc_mean_auc"] = float(np.mean([r[k]["auc"] for k in mhc])); r["_mhc_mean_f1"] = float(np.mean([r[k]["f1_05"] for k in mhc]))
if all(k in r for k in ("mhs", "hatexplain", "kmhas")):
r["_real_mean_auc"] = float(np.mean([r[k]["auc"] for k in ("mhs", "hatexplain", "kmhas")]))
if all(k in r for k in HELD):
r["_heldout_real_mean_auc"] = float(np.mean([r[k]["auc"] for k in HELD]))
print(spec, {k: round(v, 4) for k, v in r.items() if k.startswith("_")}, flush=True)
res[spec] = r; json.dump(res, open(args.out, "w"), indent=1)
|