Skip to main content

Stereotype-content analysis with fine-tuned DistilBERT models (SADCAT framework)

Project description

SADBERT

Stereotype-content Analysis with DistilBERT — a Python package for identifying and characterising stereotype-relevant dimensions in natural language text, based on the SADCAT (Stereotype-Associated Dictionary of Content and Affect with Traits) framework.

What it does

Given a word or phrase, SADBERT predicts:

Output column Description
category Stereotype-content dimension (e.g. Warmth, Competence)
probability Confidence of the category classifier
valence Direction within the category: 1 = positive, 0 = neutral, −1 = negative
valence probability Confidence of the valence prediction
interpretation Human-readable label (e.g. "Warm", "Incompetent", "Moral")

Categories detected

Major (with valence): Warmth · Competence · Sociability · Morality · Ability · Assertiveness · Status · Beliefs · health · deviance · beauty · Politics · Religion

Minor (category only, no valence): emotions · Geography · Appearance · occupation · socialgroups · inhabitant · country · relative · insults · stem · humanities · art · Lacksknowledge · fortune · clothing · bodpart · bodprop · skin · bodcov · beliefsother · Other_large · Other


Installation

pip install sadbert

Note: On first use, SADBERT automatically downloads ~2 GB of model weights from the HuggingFace Hub. These are cached locally in ~/.cache/huggingface/ and do not need to be re-downloaded on subsequent runs.

GPU / Apple Silicon

SADBERT auto-detects CUDA and Apple MPS. To use a specific device, instantiate SADBERT directly:

from sadbert import SADBERT
model = SADBERT(device="cuda")   # or "mps", "cpu"

Quick Start

import sadbert

# Single word — returns a DataFrame
df = sadbert.get_stereotype_content("honest")
print(df)

# Multiple words — stacked into one DataFrame (default)
df = sadbert.get_stereotype_content(["honest", "lazy", "senator"])
print(df)

# Multiple words — one DataFrame per word
results = sadbert.get_stereotype_content(["honest", "lazy"], stacked=False)
print(results["honest"])
print(results["lazy"])

Example output

>>> sadbert.get_stereotype_content("honest")

   category  probability  valence  valence probability interpretation
0    Warmth        0.912      1.0               0.876           Warm
1  Morality        0.843      1.0               0.791          Moral

API reference

sadbert.get_stereotype_content(text, stacked=True)

Module-level convenience function. Uses a shared, lazily-initialised SADBERT instance.

Parameter Type Description
text str or list[str] Word(s) or phrase(s) to classify
stacked bool True (default): return one combined DataFrame with a "text" column. False: return a dict[str, DataFrame]. For single string input with stacked=False, returns the DataFrame directly.

sadbert.SADBERT(device=None, batch_size=32, load_models=True)

Instantiate your own SADBERT object for full control.

from sadbert import SADBERT

model = SADBERT(
    device="cuda",     # "cuda" | "mps" | "cpu" | None (auto-detect)
    batch_size=64,     # increase for faster throughput on GPU
    load_models=True,  # set False to defer model loading to first call
)

results = model.get_stereotype_content(["nurse", "engineer", "senator"])

Model architecture

SADBERT uses a three-stage ensemble:

Input text
    │
    ▼
┌─────────────────────────────────────────────────────┐
│  Stage 1 · Master model (SADBERT_master_model)      │
│  Multi-label DistilBERT, 35 output classes          │
│  Softmax probabilities compared against per-class   │
│  Youden-J thresholds → candidate categories         │
└─────────────────────────────────────────────────────┘
    │  candidate categories
    ▼
┌─────────────────────────────────────────────────────┐
│  Stage 2 · Classifier heads (SADBERT_{cat}_classifier) │
│  One binary DistilBERT per category                 │
│  Veto gate — keeps only categories confirmed by     │
│  both master model and dedicated head               │
└─────────────────────────────────────────────────────┘
    │  confirmed categories + probabilities
    ▼
┌─────────────────────────────────────────────────────┐
│  Stage 3 · Sentiment models (SADBERT_{cat}_sentiment)  │
│  One 3-class DistilBERT per major category          │
│  Predicts negative / neutral / positive valence     │
└─────────────────────────────────────────────────────┘
    │
    ▼
  Results DataFrame

All models are hosted on HuggingFace at huggingface.co/XanderD24.


Building from source

git clone https://github.com/XanderD24/sadbert.git
cd sadbert

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

Adding ROC_dict.pkl before publishing

ROC_dict.pkl (per-category probability thresholds) is required but not included in the repository for size reasons. Copy it into the data directory before building the wheel:

cp /path/to/ROC_dict.pkl sadbert/data/ROC_dict.pkl

Then build:

python -m build        # produces dist/sadbert-0.1.0.tar.gz and .whl
twine check dist/*     # sanity-check before uploading
twine upload dist/*    # publish to PyPI

Citation

If you use SADBERT in research, please cite the underlying SADCAT framework:

@misc{sadbert2025,
  author = {Deanhardt, Xander},
  title  = {{SADBERT}: Stereotype-content Analysis with {DistilBERT}},
  year   = {2025},
  url    = {https://github.com/XanderD24/sadbert},
}

Citation of Original Work

All data used to fine-tune these models was taken from the SADCAT dictionary, published by Gandalf Nicolas, Xuecunzi Bai, and Susan T Fiske, and hosted on Github by Gandalf Nicolas. It was first published in this journal:

Nicolas, Gandalf, et al. “Comprehensive Stereotype Content Dictionaries Using a Semi‐Automated Method.” European Journal of Social Psychology, vol. 51, no. 1, Feb. 2021, pp. 178–196, https://doi.org/10.1002/ejsp.2724.

Github Link = {https://github.com/gandalfnicolas/SADCAT/tree/master}

OSF Repository = {https://osf.io/yx45f/}

License

MIT License — see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sadbert-0.1.0.tar.gz (19.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sadbert-0.1.0-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file sadbert-0.1.0.tar.gz.

File metadata

  • Download URL: sadbert-0.1.0.tar.gz
  • Upload date:
  • Size: 19.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for sadbert-0.1.0.tar.gz
Algorithm Hash digest
SHA256 15006d6ce67f6ba59305d2f4d003f87d1773a4eeedb3d97cdb653415059ffcb2
MD5 8dc39c472319a47e3c1d38b0a6cb5b90
BLAKE2b-256 cfbc11b987668a249a4c30d9bc2084770f2bc39b6d7876cc4c407363ffe0b425

See more details on using hashes here.

File details

Details for the file sadbert-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sadbert-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for sadbert-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f591efcee74fb26ce3bd88ab344cf4c7de3fd9ade0d6c49573d670c11a2c2808
MD5 d2bf1eec399088b0f89830c357d258ce
BLAKE2b-256 e827cb5be3765bb4817fffc2f625672fefb21a07d8f426296051b4f21cceaba0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page