Skip to main content

Fair-Seldonian

Fairness-constrained machine learning with high-confidence guarantees

PyPI Python 3.10+ Build codecov License: MIT Docs PyPI Downloads Paper


A Python framework implementing the Quasi-Seldonian Algorithm (QSA) for training ML models that provably satisfy fairness constraints. Given a behavioral constraint and a confidence level δ, the algorithm either returns a model satisfying the constraint with probability ≥ 1 − δ, or returns No Solution Found — never an unsafe model.

Built on the Seldonian algorithm framework by Thomas et al. (2019), with extensions for tighter confidence bounds through constant-aware delta allocation, union bound optimization, and decomposed candidate-safety intervals.

Quick links

Documentation parulgupta1004.github.io/fair-seldonian
Repository github.com/parulgupta1004/fair-seldonian
Example notebook examples/quickstart.ipynb
Paper Thomas et al., Science 366 (2019) — doi:10.1126/science.aag3311

Installation

git clone https://github.com/parulgupta1004/fair-seldonian.git
cd fair-seldonian
uv sync                          # core dependencies
uv sync --extra experiments      # + Ray for parallel experiments
uv sync --extra plots            # + matplotlib for visualization
uv sync --extra notebook         # + JupyterLab to run examples/quickstart.ipynb

Or with pip:

pip install fair-seldonian
pip install "fair-seldonian[notebook]"          # JupyterLab + matplotlib to run the quickstart
pip install "fair-seldonian[experiments,plots]"

Usage

from fair_seldonian.algorithms import QSA
from fair_seldonian.models import eval_ghat
from fair_seldonian.data import get_data, data_split

data = get_data(N=10000, features=5, t_ratio=0.4,
                tp0_ratio=0.4, tp1_ratio=0.6, random_seed=42)
X_te, Y_te, T_te, X_tr, Y_tr, T_tr = data_split(
    frac=0.5, all_data=data, random_state=1, m_test=0.2)

theta, theta1, passed = QSA(X_tr, Y_tr, T_tr, "opt", None, None)

if passed:
    print("Upper bound:", eval_ghat(theta, theta1, X_te, Y_te, T_te, "opt"))
else:
    print("No Solution Found")

Custom configuration:

from fair_seldonian.config import SeldonianConfig
from fair_seldonian.constraints.inequalities import Inequality

config = SeldonianConfig(delta=0.01, inequality=Inequality.T_TEST, candidate_ratio=0.5)
theta, theta1, passed = QSA(X_tr, Y_tr, T_tr, "opt", None, None, config)

Built-in fairness constraints:

Common fairness definitions ship as ready-to-use builders — no need to write the postfix constraint string by hand. Each takes a tolerance epsilon; the parity builders also take the two sensitive-attribute values to compare (default ("1", "0")):

from fair_seldonian import SeldonianConfig, demographic_parity

config = SeldonianConfig(constraint=demographic_parity(epsilon=0.1))
Builder Bounds (<= epsilon)
demographic_parity gap in predicted-positive rate (statistical parity)
equal_opportunity gap in true-positive rate
equalized_odds combined true- and false-positive-rate gaps
error_rate one group's misclassification rate
error_rate_parity gap in misclassification rate (overall accuracy equality)

See the Fairness constraints docs for definitions and references.

Examples

A runnable, end-to-end walkthrough lives in examples/quickstart.ipynb:

  • generating synthetic data with a controllable fairness gap
  • training with QSA and reading the high-confidence safety guarantee
  • contrasting fair data (model certified) with unfair data (No Solution Found)
  • decoding and customizing the postfix constraint, delta, and inequality
  • comparing the five algorithm variants side by side
  • visualizing accuracy vs. the certified fairness bound, with and without QSA, on the same dataset

Install the notebook dependencies and launch it with:

pip install "fair-seldonian[notebook]"
jupyter lab examples/quickstart.ipynb

View it rendered on nbviewer, or in the documentation's Examples section.

Prefer plain scripts? The examples/ directory has runnable .py versions — quickstart.py, fairness_guarantee.py, and custom_constraint.py — plus real_world_adult.ipynb, a notebook that applies QSA to the UCI Adult income dataset (with saved outputs so the results render on GitHub). All are described in examples/README.md:

uv run python examples/quickstart.py

Algorithm variants

Mode Description
base Standard Hoeffding bound, uniform δ-splitting
mod Decomposed candidate/safety estimation error
const Constant-aware δ allocation
bound Union bound optimization for repeated variables
opt All optimizations combined
uv run python -m fair_seldonian.experiments.runner opt
uv run python -m fair_seldonian.experiments.plots

Citation

@software{fair_seldonian,
  author = {Parul Gupta},
  title  = {Fair Seldonian Framework},
  year   = {2020}
}

This work builds on:

Thomas, P.S., da Silva, B.C., Barto, A.G., Giguere, S., Brun, Y., & Brunskill, E. (2019). "Preventing undesirable behavior of intelligent machines." Science, 366(6468), 999–1004.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines, or open an issue to get started.

Contributors

Thanks to everyone who has contributed to this project!

License

MIT


Author: Parul Gupta

Metadata

Release files for fair-seldonian 3.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fair-seldonian 3.1.0
File Size Uploaded
fair_seldonian-3.1.0.tar.gz 61.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fair-seldonian 3.1.0
File Interpreter ABI Platform
fair_seldonian-3.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 93.3 kB

Release files / fair_seldonian-3.1.0.tar.gz

Download URL fair_seldonian-3.1.0.tar.gz
Size 61.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a5f8c660087266965503efeb71e73cd4fee5431d69ed3c535dd3a46932914017
BLAKE2b-256 checksum
How to use checksums
e304e3d481ca402c17cfe85ef4593c9378958b81bcb13d4a774f3f8eff64d399
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release files / fair_seldonian-3.1.0-py3-none-any.whl

Download URL fair_seldonian-3.1.0-py3-none-any.whl
Size 31.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c111774f4809b5f777e5adb8406ce71ac5fbaa6a2b633d73fb7664b3fcb3711f
BLAKE2b-256 checksum
How to use checksums
a35f2072c5e9d8b529deaef6c3b97d12ee2bf65cc2fc411c8de8e04fa3920522
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

3.1.0 This release

2 release files

3.0.0

2 release files

2.1.1

2 release files

2.0.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page