GUS-Net (GPT-2 Medium)

Token-level social-bias detector built on gpt2-medium (causal decoder). Given a sentence, it tags each token with one of four bias categories following a 7-label BIO scheme, highlighting which words carry bias.

Part of the Attention Atlas project (a master's thesis on interpretable bias detection through transformer attention). This is the larger-capacity causal variant of pinthoz/gus-net-gpt2.

Label scheme

Index Label Category
0 O none
1 B-STEREO Stereotype (span start)
2 I-STEREO Stereotype (span inside)
3 B-GEN Generalisation (span start)
4 I-GEN Generalisation (span inside)
5 B-UNFAIR Unfair language (span start)
6 I-UNFAIR Unfair language (span inside)
  • GEN — a blanket generalisation about a group.
  • UNFAIR — unfair / disparaging language toward a group.
  • STEREO — a stereotype attributed to a group.

Important: multi-label + per-label thresholds

Outputs are per-token sigmoid probabilities (multi-label), not a softmax. F1-optimised thresholds (order [O, B-STEREO, I-STEREO, B-GEN, I-GEN, B-UNFAIR, I-UNFAIR]):

[0.4912, 0.5042, 0.4213, 0.4204, 0.4000, 0.4618, 0.3848]

A flat 0.5 threshold will mis-detect bias — use the values above.

Usage

GPT-2 has no [CLS]/[SEP]; the tokenizer needs add_prefix_space=True and a pad token. The first token is an attention-sink position — be cautious reading its scores.

import torch
from transformers import AutoTokenizer, GPT2ForTokenClassification

model_id = "pinthoz/gus-net-gpt2-medium"
tok = AutoTokenizer.from_pretrained("gpt2-medium", add_prefix_space=True)
tok.pad_token = tok.eos_token
model = GPT2ForTokenClassification.from_pretrained(model_id).eval()

CATEGORY_INDICES = {"STEREO": [1, 2], "GEN": [3, 4], "UNFAIR": [5, 6]}
THRESHOLDS = [0.4912, 0.5042, 0.4213, 0.4204, 0.4000, 0.4618, 0.3848]

text = "Women are naturally worse at driving."
enc = tok(text, return_tensors="pt")
with torch.no_grad():
    probs = torch.sigmoid(model(input_ids=enc["input_ids"],
                                attention_mask=enc["attention_mask"]).logits)[0]

tokens = tok.convert_ids_to_tokens(enc["input_ids"][0])
for i, tokn in enumerate(tokens):
    fired = {cat: float(probs[i, idxs].max())
             for cat, idxs in CATEGORY_INDICES.items()
             if any(probs[i, j] > THRESHOLDS[j] for j in idxs)}
    if fired:
        print(f"{tokn:15s} -> {fired}")

Training data

Fine-tuned on the GUS-Net dataset — a token-level social-bias corpus annotated for Generalisations, Unfairness and Stereotypes (ethical-spectacle/gus-dataset-v1).

Difference from the original GUS-Net dataset and models: in the original data punctuation is fused to the preceding word rather than tokenised separately (the corpus contains no standalone punctuation token at all), so a comma or full stop falling inside a labelled span inherits that span's categories — the sentence-final mark carries a bias label in 1,942 of the 3,739 sentences, and an in-span comma in 270. The data used here splits each mark into a token of its own and labels it non-bias O, repairing the BIO sequence where the split interrupts a span, since punctuation is not a social-bias carrier. Bias spans predicted by these models therefore exclude leading/trailing punctuation.

Evaluation

StereoSet (intersentence split, 2123 examples)

Metric Score
LMS (language-modeling score, higher is better) 77.67
SS (stereotype score, 50 = ideal) 54.69
ICAT (bias-adjusted quality) 70.39

Per-category SS: gender 61.57 · race 51.74 · religion 53.85 · profession 56.23.

Token classification (GUS-Net held-out test set)

Held-out partition (747 sentences) of the stratified cross-validation fold this checkpoint was trained against — StratifiedKFold(n_splits=5, shuffle=True, random_state=42) over the cleaned corpus (see Training data), fold 4 — scored with the per-label thresholds above. Each category aggregates its B-/I- labels; the micro average covers the three bias categories and excludes the majority O class. Label alignment mirrors training (continuation subtokens labelled, with B- demoted to I-).

Category Precision Recall F1
O (non-bias) 0.959 0.965 0.962
GEN 0.817 0.926 0.868
UNFAIR 0.821 0.814 0.817
STEREO 0.891 0.900 0.895
Micro-avg 0.855 0.899 0.876

This is the strongest of the four checkpoints on every category, and the only one with usable UNFAIR detection.

Note: these thresholds were tuned on fold 0's validation set while the published checkpoint is fold 4's, so they are mildly optimistic; the F1 above inherits that.

Limitations & intended use

  • Research / auditing tool, not a content-moderation oracle. Predictions reflect a specific operationalisation of bias; subtle or context-dependent bias may be missed.
  • Causal masking means each token only sees left context, so span boundaries can differ from the BERT models.
  • English only.
  • Do not use for automated decisions about individuals.

Citation

If you use these models, please cite the GUS-Net dataset and benchmark:

@article{powers2024gusnet,
  title   = {GUS-Net: Social Bias Classification in Text with Generalizations, Unfairness, and Stereotypes},
  author  = {Powers, Maximus and Raza, Shaina and Chang, Alex and Riaz, Rehana and Mavani, Umang and Jonala, Harshitha Reddy and Tiwari, Ansh and Wei, Hua},
  journal = {arXiv preprint arXiv:2410.08388},
  year    = {2024}
}

License

Weights released under MIT (matching the gpt2-medium base model). The Attention Atlas code is MIT-licensed.

Downloads last month
42
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for pinthoz/gus-net-gpt2-medium

Finetuned
(197)
this model

Dataset used to train pinthoz/gus-net-gpt2-medium

Space using pinthoz/gus-net-gpt2-medium 1

Paper for pinthoz/gus-net-gpt2-medium