Detect train-serving skew by computing the Population Stability Index (PSI) for each feature. Given training and serving feature distributions as dictionaries mapping feature names to lists of bin proportions, compute PSI per feature and flag which features have shifted beyond a given threshold.
A feature is flagged as skewed when its PSI ≥ threshold.
Input:
train_dist = {"age": [0.1, 0.2, 0.3, 0.25, 0.15], "income": [0.2, 0.2, 0.2, 0.2, 0.2]} serving_dist = {"age": [0.05, 0.1, 0.15, 0.35, 0.35], "income": [0.2, 0.2, 0.2, 0.2, 0.2]} threshold = 0.2
Output:
{"age": {"psi": 0.4111, "skewed": True}, "income": {"psi": 0.0, "skewed": False}}
The "age" distribution has shifted significantly (PSI ≈ 0.41 ≥ 0.2), while "income" remains identical.
Input:
train_dist = {"clicks": [0.3, 0.4, 0.2, 0.1]} serving_dist = {"clicks": [0.25, 0.35, 0.25, 0.15]} threshold = 0.2
Output:
{"clicks": {"psi": 0.0472, "skewed": False}}
A gentle shift yields PSI ≈ 0.047, well below the 0.2 threshold - no skew flagged.
A small constant added to each bin prevents log(0) and division by zero.
Each PSI term measures how much a single bin has shifted between the two distributions.
NumPy arrays and vectorized operations can replace explicit Python loops over bins.
Sign in to take notes on this problem
Accepts: any
Accepts: any
Accepts: number
Accepts: number
Detect train-serving skew by computing the Population Stability Index (PSI) for each feature. Given training and serving feature distributions as dictionaries mapping feature names to lists of bin proportions, compute PSI per feature and flag which features have shifted beyond a given threshold.
A feature is flagged as skewed when its PSI ≥ threshold.
Input:
train_dist = {"age": [0.1, 0.2, 0.3, 0.25, 0.15], "income": [0.2, 0.2, 0.2, 0.2, 0.2]} serving_dist = {"age": [0.05, 0.1, 0.15, 0.35, 0.35], "income": [0.2, 0.2, 0.2, 0.2, 0.2]} threshold = 0.2
Output:
{"age": {"psi": 0.4111, "skewed": True}, "income": {"psi": 0.0, "skewed": False}}
The "age" distribution has shifted significantly (PSI ≈ 0.41 ≥ 0.2), while "income" remains identical.
Input:
train_dist = {"clicks": [0.3, 0.4, 0.2, 0.1]} serving_dist = {"clicks": [0.25, 0.35, 0.25, 0.15]} threshold = 0.2
Output:
{"clicks": {"psi": 0.0472, "skewed": False}}
A gentle shift yields PSI ≈ 0.047, well below the 0.2 threshold - no skew flagged.
A small constant added to each bin prevents log(0) and division by zero.
Each PSI term measures how much a single bin has shifted between the two distributions.
NumPy arrays and vectorized operations can replace explicit Python loops over bins.
Sign in to take notes on this problem
Accepts: any
Accepts: any
Accepts: number
Accepts: number