FlagGAM
Documentation & guidebook: https://wlazlod.github.io/flaggam/ (available once the repository is public).
FlagGAM is a method for building interpretable generalized additive models from tabular data. It works by first running a univariate screening pass — the Univariate Flagging Algorithm (Sheth et al., 2019) — that identifies threshold and category cuts where a feature's distribution shifts meaningfully relative to the outcome. Each surviving cut becomes a binary basis function ("flag"), and the flags together form a compact, human-readable rule basis.
A linear or logistic head is then fitted on top of the rule basis, producing a model whose predictions are sums of individually interpretable flag contributions. Because every flag corresponds to a concrete data condition (e.g., "age ≥ 55"), the resulting model supports exact rule extraction and feature-level attribution without approximation.
This package is a from-scratch Python implementation of FlagGAM (Zhao & Welsch, arXiv:2605.31189)
and the Univariate Flagging Algorithm (Sheth et al., PLOS ONE 2019). It provides
sklearn-compatible FlagGAMClassifier and FlagGAMRegressor estimators that integrate
directly into standard scikit-learn pipelines.
Installation
# Editable install (development)
pip install -e .
# Or with uv
uv sync --extra dev
Quickstart
Rule discovery requires enough rows per tail (min_support). The example below
uses 600 synthetic rows with a planted signal so that export_rules() returns
non-trivial rules.
import numpy as np
import pandas as pd
from flaggam import FlagGAMClassifier
rng = np.random.default_rng(0)
n = 600
age = rng.normal(40, 10, n)
purpose = rng.choice(["car", "tv", "edu"], n)
logit = -1.5 + 2.0 * (age <= 30) + 1.5 * (purpose == "edu")
y = (rng.uniform(size=n) < 1 / (1 + np.exp(-logit))).astype(int)
X = pd.DataFrame({"age": age, "purpose": pd.Categorical(purpose)})
clf = FlagGAMClassifier(random_state=0).fit(X, y)
# Inspect the rule basis (5 rules on this seed)
rules = clf.export_rules()
print(rules[["feature", "rule", "weight"]])
# feature rule weight
# age age <= 27.4074 1.589593
# age age >= 46.7581 -0.387614
# purpose purpose == 'edu' 0.906901
# purpose purpose == 'tv' -0.418348
# purpose purpose == 'car' -0.486362
# Attribution for a young 'edu' applicant
x_young = pd.DataFrame({"age": [22.0], "purpose": pd.Categorical(["edu"])})
explanation = clf.explain(x_young)
print(explanation)
# row feature rule value contribution
# 0 age age <= 27.4074 1.0 1.589593
# 0 purpose purpose == 'edu' 1.0 0.906901
# 0 <intercept> <intercept> 1.0 -0.624096
Extensions (beyond the paper)
Three optional modules extend the paper's method; each is an original addition not present in Zhao & Welsch (2026) and lives in its own module.
PD calibration — diagnostics (reliability curve, Brier, ECE,
calibration-in-the-large) and recalibration (platt, isotonic,
base_rate) fitted on data disjoint from head fitting:
from flaggam import CalibratedFlagGAM, expected_calibration_error
cal = CalibratedFlagGAM(FlagGAMClassifier(random_state=0), method="platt", cv=5)
cal.fit(X, y)
pd_hat = cal.predict_proba(X)[:, 1]
Monotonicity constraints — regulators often require PD monotone in a feature. Because FlagGAM's numerical contributions are step/ramp bases, sign constraints give exact monotonicity:
clf_mono = FlagGAMClassifier(monotonic_constraints={"age": -1}).fit(X, y) # PD non-increasing in age
Fairness / proxy audit — group metrics for a protected attribute and a rule-level audit that ranks bases by association with it:
from flaggam import ProxyAudit, group_metrics
A = X["purpose"].astype(str) # protected attribute (illustrative)
metrics = group_metrics(y, clf.predict_proba(X)[:, 1], A)
report = ProxyAudit(clf).report(X, A) # ranked candidate proxies
clean_clf, trade = ProxyAudit(clf).drop_proxies(X, y, A, threshold=0.3)
Benchmarks
Reproducing the paper's tables requires the benchmarks optional dependency group:
uv sync --extra benchmarks
Each runner produces one paper table as a tidy results CSV:
python -m benchmarks.run_classification # Table 3 (classification AUROC)
python -m benchmarks.run_regression # Table 4 (regression RMSE/R2)
python -m benchmarks.run_robustness # Table 5 (missingness/noise robustness)
python -m benchmarks.run_ablation # Table 7 (FlagGAM ablations)
python -m benchmarks.run_sensitivity # Table 8 (hyperparameter sensitivity)
All runners default to --n-splits 1000, matching the paper, which takes hours per table.
Pass --n-splits 25 for a quick pass while developing or sanity-checking a change.
Rows are always APPENDED to --out if it already exists (this supports chunked
--seed-start resumption); delete the file first if you want a fresh run.
python -m benchmarks.render_tables benchmarks/results/classification.csv --table 3
render_tables.py compares a results CSV against the paper's reported values
(Zhao & Welsch, arXiv:2605.31189, benchmarks/paper_targets.py) and flags deltas beyond
tolerance. Results CSVs are written under benchmarks/results/ and are gitignored — they are
run artifacts, not tracked outputs.
Citation
If you use this package in research, please cite the papers it implements:
FlagGAM method:
Zhao, Z. & Welsch, R. E. (2026).
FlagGAM: Rule-Basis Generalized Additive Models for Explainable Tabular Prediction.
arXiv:2605.31189.
Univariate Flagging Algorithm:
Sheth, M., Gerovitch, A., Welsch, R. E., Markuzon, N. (2019).
The Univariate Flagging Algorithm (UFA): An interpretable approach for predictive modeling.
PLOS ONE 14(10): e0223161.
https://doi.org/10.1371/journal.pone.0223161
A machine-readable citation file is available at CITATION.cff.
Development
uv sync --extra dev
uv run pytest -q
uv run ruff check .
uv run mypy
uv run mkdocs serve # Preview documentation locally
Status
Feature-complete at 0.1.0: core estimators pass check_estimator with no exclusions; the
benchmark suite reproduces the paper's protocol (a 25-split German Credit smoke run
reproduces the paper's 0.775 AUROC to within 0.002 (gate tolerance ±0.02)); calibration,
monotonicity, fairness, and visualization
extensions are implemented and documented. See CHANGELOG.md.
License
Apache 2.0 — see LICENSE. See docs/LICENSING.md for notes
on paper copyrights and dataset licences.
Metadata
Release files for flaggam 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| flaggam-0.1.1.tar.gz | 616.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| flaggam-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 659.8 kB
Release files / flaggam-0.1.1.tar.gz
| Download URL | flaggam-0.1.1.tar.gz |
|---|---|
| Size | 616.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d37d18213d0e2b037ca1da6caba2ef30df567f0809e7d75d6ea5c1cb0b50239d
|
|
BLAKE2b-256 checksum How to use checksums |
6e9846623ee2a4a7b6b5b21549b4c81b1ebccdec9dd1d3fc0a3eb287c02b4eac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 8, 2026.
Transparency logRelease files / flaggam-0.1.1-py3-none-any.whl
| Download URL | flaggam-0.1.1-py3-none-any.whl |
|---|---|
| Size | 43.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
003ccb1ad82f66477121cce067cc17a8d656b82e03152aeae922b8b6ab7f0473
|
|
BLAKE2b-256 checksum How to use checksums |
7f1969484684709a36ddbbead9ff05ec02094ef63b4132d1c9cb23d2edf75e1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 8, 2026.
Transparency logSecurity for flaggam 0.1.1
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for flaggam-0.1.1.tar.gz
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 8, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.