Examples · Plots

band_ladder

The ladder itself: population, bad rate and calibrated PD per band.

Code#

band_ladder.py
import matplotlib.pyplot as plt
 
from _setup import X_test, artifact, y_test
 
from compileml.runtime import decide
from compileml.viz import band_ladder
 
# The whole holdout, not a slice of it. Empirical monotonicity is a question
# about sample size as much as about the model: at ~200 accounts per band the
# standard error on a 10% rate is about 0.021, so adjacent bands routinely
# cross for no reason anyone should act on.
decisions = [decide(artifact, row.tolist(), explain=False) for row in X_test]
 
fig, ax = band_ladder(decisions, y_test)
fig.savefig("../../public/examples/band_ladder.png", dpi=144, bbox_inches="tight")
plt.close(fig)
 
counts, bad = {}, {}
for decision, outcome in zip(decisions, y_test):
band = decision["band"]
counts[band] = counts.get(band, 0) + 1
bad[band] = bad.get(band, 0) + int(outcome)
 
labels = sorted(counts)
rates = [bad[b] / counts[b] for b in labels]
 
print(f"{'band':<7}{'n':>7}{'bad rate':>11}")
for label, rate in zip(labels, rates):
print(f"{label:<7}{counts[label]:>7}{rate:>11.4f}")
 
inversions = [
(labels[i], labels[i + 1]) for i in range(len(rates) - 1) if rates[i + 1] < rates[i]
]
print()
print(f"rows scored {len(decisions)}")
print(f"empirical inversions {len(inversions)}")
 
# Monotone band edges are built to hold on the data they were fit on. Whether
# they hold out of sample is measured, not assumed — sweep_bands reports
# monotonicity_violations per candidate ladder, and band_efficiency gives a
# per-band verdict on whether a band still separates risk internally.

Output#

Captured from an actual run against compileml 0.9.0 and the UCI credit panel. If this script stops working, the build fails.

captured in CIband_ladder.py
band n bad rate
G01 722 0.0512
G02 737 0.0678
G03 735 0.0966
G04 769 0.1300
G05 773 0.1488
G06 767 0.1512
G07 763 0.2018
G08 723 0.2628
G09 739 0.3924
G10 772 0.6943
 
rows scored 7500
empirical inversions 0

Figure#

Output of the band_ladder example

Rendered by the run above, from the decision payload rather than a recomputation.

Notes#

  • A dip in the bad-rate line is the picture of a monotonicity failure.

API reference: band_ladder →