Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

drift-or-shift

CI Python License: MIT Code style: black Checked with mypy

A reproducible research pipeline for distinguishing label shift from concept drift, and for showing exactly when a training-free logit offset is sufficient — and when it is not.

The experiments reproduce and extend the analysis in SSRN 6052514: start from synthetic two-class Gaussian data, apply the Bayes-optimal offset correction without retraining, then observe which metrics are invariant (ROC AUC) and which are not (PR-AUC, effective sample size). When the class-conditionals themselves move, the offset provably cannot recover the new posterior, and retraining becomes necessary.


Installation

# From source, for development
git clone https://github.com/DiogoRibeiro7/drift-or-shift.git
cd drift-or-shift
make install          # editable install + dev extras + pre-commit hooks

Without make:

python -m pip install -e ".[dev]"
python -m pre_commit install

Runtime install only:

python -m pip install .

Requires Python 3.10+. This installs the drift_or_shift package, the drift_shift_pipeline compatibility alias, the caliblab calibration benchmarking helpers, and the eleven dos-expN console scripts.

Quickstart

# Fast end-to-end sanity check (seconds)
python scripts/smoke_exp1.py --results-dir results/smoke

# A full experiment
dos-exp1 --pi-train 0.2 --pi-tests 0.05 0.2 0.5 --results-dir results

# Aggregate every run into a reviewable dashboard
python scripts/aggregate_results.py --results-dir results \
    --output reports/dashboard.md --figure reports/best_risk.png

Each run writes tables/, figures/, and a _summary.json into results/<experiment>/<utc-timestamp>/.

Core concepts

Label shift vs. concept drift

Label shift Concept drift
What moves Class prior π only The class-conditionals p(x|y)
Posterior recoverable without retraining? Yes — additive logit offset No
Demonstrated by Exp 1, 2, 5, 8–11 Exp 4, 7

Offset correction

Logits are log-odds, so shifting the prior from π_train to π_test is a constant additive term:

offset = log( π_test · (1 − π_train) / (π_train · (1 − π_test)) )

Apply the offset before comparing against the cost-derived threshold log(c10 / c01); with default costs (c10 = c01 = 1) that threshold is zero. Because a constant offset preserves the ranking of scores, ROC AUC is invariant under label shift — while PR-AUC, which depends on prevalence, is not.

Experiments

Command What it demonstrates
dos-exp1 Synthetic label shift: offset correction vs. oracle risk
dos-exp2 ROC AUC invariance and PR-AUC prevalence dependence
dos-exp3 ESS fraction shrinking as class weight α grows
dos-exp4 Concept drift: standard vs. offset vs. retrained
dos-exp5 Breast cancer label shift replication with resampling
dos-exp6 Calibration (temperature, isotonic) vs. offset under label shift
dos-exp7 Drift-type sweep: covariance, feature, and label shift
dos-exp8 Multimodal label shift with mixture components
dos-exp9 Covertype: real, high-dimensional label shift
dos-exp10 Credit-card fraud benchmark with reweighted prevalences
dos-exp11 High-variance medical-style benchmark with nonlinear test shifts

Sources live in src/drift_or_shift/experiments/. Every script accepts --help.

Reproducibility

  • All generators take an explicit seed; summaries record seeds, sizes, costs, and prevalence grids.
  • Run-directory names and summary timestamps are UTC and timezone-aware.
  • ExperimentConfig in drift_or_shift.experiments._common (or the CLI flags) pins a run's configuration.
  • reproduce/ holds a separate calibration-benchmark replication driven by reproduce/config/default.yaml.

Tooling utilities

  • drift_or_shift.drift_variants — inject covariance/feature shifts, label noise, and density-ratio scoring without rebuilding the generators.
  • scripts/aggregate_results.py — collect every results/*/*_summary.json into a markdown dashboard; --fail-on-alerts exits non-zero when drift is detected.
  • scripts/drift_alerts.py — flag feature_max_* statistics above threshold into reports/drift_alerts.csv.
  • scripts/watch_results.py — poll results/ and refresh alerts + dashboard as new summaries land (--once for a single pass).

See docs/CLI_USAGE.md for full flag documentation.

Development

make check      # ruff + black + mypy + pytest, exactly what CI runs
make test-cov   # tests with an HTML coverage report
make build      # sdist + wheel, validated with twine
make help       # all targets

CI runs the suite on Python 3.10–3.13 on Linux, plus Windows and macOS spot checks, and verifies that the built wheel installs and runs in a clean environment.

See CONTRIBUTING.md for branching and PR conventions, and CHANGELOG.md for release history.

Project documents

File Contents
RESULTS_DIGEST.md Latest metrics and artifact paths
REPORT.md Reproduction steps and what each figure claims
notes/lessons.md Counter-intuitive findings worth revisiting
ROADMAP.md Milestones
FUTURE.md Candidate extensions
RELEASE.md Release checklist

Citation

If this code supports academic work, please cite the underlying paper (SSRN 6052514) and reference this repository:

@software{ribeiro_drift_shift_pipeline,
  author  = {Ribeiro, Diogo},
  title   = {drift-or-shift: label shift, offset correction and drift diagnostics},
  url     = {https://github.com/DiogoRibeiro7/drift-or-shift},
  version = {0.1.0}
}

License

Released under the MIT License.

Metadata

Release files for drift-or-shift 0.1.0a1

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

Source distribution (sdist)

Source distribution for drift-or-shift 0.1.0a1
File Size Uploaded
drift_or_shift-0.1.0a1.tar.gz 64.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for drift-or-shift 0.1.0a1
File Interpreter ABI Platform
drift_or_shift-0.1.0a1-py3-none-any.whl Python 3 none any Details

Total release size: 111.4 kB

Release files / drift_or_shift-0.1.0a1.tar.gz

Download URL drift_or_shift-0.1.0a1.tar.gz
Size 64.1 kB
Tags Source
SHA-256 checksum
How to use checksums
52c977cc17c8f47da874ad9bc4409a58f586083877cd4502e5a781eef5801600
BLAKE2b-256 checksum
How to use checksums
4915f84aa66668b066d7ff0b5f3f8d7d140ea572b494fecc26a116294cfd26d7
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 Sep 23, 2026.

Transparency log

Release files / drift_or_shift-0.1.0a1-py3-none-any.whl

Download URL drift_or_shift-0.1.0a1-py3-none-any.whl
Size 47.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
88c48ec8ed7c2583b9a2b7fbdd014bad0a03924428b00c44e72b1a5571531a0e
BLAKE2b-256 checksum
How to use checksums
b7fc071fa825a9feaca5a5af9ce7d638b5ae45e8cae278d230892197b868044c
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 Sep 23, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0a1 This release

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