Monitors
glide.monitors.asymptotic_classical.AsymptoticClassicalRM
Bases: AsymptoticRM[NDArray, None]
Anytime-valid label-only drift monitor leveraging each batch estimate's standard deviation.
It computes a per-batch sample mean of the labeled values, then tracks the
running mean of those estimates against a user-supplied threshold. The
comparison uses a Gaussian-mixture asymptotic confidence sequence whose
width scales with the standard error of each batch mean, so genuine drifts
get flagged early. The false-alarm guarantee is asymptotic: each batch
needs enough labeled samples (preferably tens) for its sample mean to be
approximately Gaussian with a consistently estimated variance.
References
Waudby-Smith, Ian, David Arbour, Ritwik Sinha, Edward H. Kennedy, and Aaditya Ramdas. "Time-uniform central limit theory and asymptotic confidence sequences." The Annals of Statistics 52, no. 6 (2024): 2613-2640.
Examples:
>>> import numpy as np
>>> from glide.monitors import AsymptoticClassicalRM
>>> pre_drift_batch = np.array([0.0, 0.2, np.nan, np.nan])
>>> post_drift_batch = np.array([0.8, 1.0, np.nan, np.nan])
>>> y = np.hstack([pre_drift_batch, np.tile(post_drift_batch, 5)])
>>> batches = np.repeat(np.arange(6), 4)
>>> monitor = AsymptoticClassicalRM()
>>> result = monitor.detect(y, batches, higher_is_better=False, threshold=0.5)
>>> result.drift_detected
True
>>> result.first_alarm_index
3
Source code in glide/monitors/asymptotic_classical.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
detect
detect(
y,
batches,
*,
higher_is_better,
threshold,
metric_name="Metric",
confidence_level=0.8,
tightest_at_batch=10,
)
Detect a drift of the running mean across a batched dataset.
Splits the data by batch, computes a sample-mean estimate and its standard
error per batch, and builds an anytime-valid asymptotic confidence sequence
on the running mean of those estimates. An alarm is raised at every batch
where the sequence crosses the user-supplied threshold.
Rows must be ordered oldest batch first and grouped into contiguous blocks;
identifier values are not compared, so any label type works. Batches must be
non-overlapping (no shared samples), and successive calls must be made on
growing histories of the same data; passing the full accumulated dataset at
every call makes the anytime-valid guarantee hold jointly over all calls.
Alternatively the data may be restricted to the most recent batches, in which
case the guarantee holds within each restriction but not across the moving
history as a whole. When the history has fewer batches than tightest_at_batch,
the tuning target is set to the last batch. Prefix-consistency only holds between
calls using the same tightest_at_batch value and with histories containing
at least tightest_at_batch batches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y
|
NDArray
|
Array of observations, shape |
required |
batches
|
NDArray
|
Array of batch identifiers, shape |
required |
higher_is_better
|
bool
|
|
required |
threshold
|
float
|
The metric value the running mean is monitored against, in metric units: the worst level the user is willing to tolerate. An alarm fires once the anytime-valid bound proves the running metric has crossed it (the running risk exceeds it for a risk, the running performance falls below it for a performance). |
required |
metric_name
|
str
|
Human-readable label for the metric. Defaults to |
'Metric'
|
confidence_level
|
float
|
How confident each alarm should be. At the default |
0.8
|
tightest_at_batch
|
int
|
The batch index (1-indexed) at which the confidence sequence is tuned to
be tightest. Defaults to |
10
|
Returns:
| Type | Description |
|---|---|
ClassicalMeanMonitoringResult
|
Per-batch estimates, running means, anytime-valid confidence bounds, alarm flags, and the alarm threshold, all in the original metric orientation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Source code in glide/monitors/asymptotic_classical.py
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
glide.monitors.asymptotic_clustered_classical.AsymptoticClusteredClassicalRM
Bases: AsymptoticRM[NDArray, None]
Anytime-valid label-only drift monitor over clustered data.
Computes a per-batch estimate by reducing each batch's labeled observations
to per-cluster means and taking the classical mean of those means, together
with its standard error, then tracks the running mean of the per-batch
estimates the same way AsymptoticClassicalRM does for independent,
unclustered samples. Samples of the same cluster are correlated, so treating
each cluster as a single sampling unit keeps the standard errors, and hence
the false-alarm guarantee, valid.
References
Waudby-Smith, Ian, David Arbour, Ritwik Sinha, Edward H. Kennedy, and Aaditya Ramdas. "Time-uniform central limit theory and asymptotic confidence sequences." The Annals of Statistics 52, no. 6 (2024): 2613-2640.
Examples:
>>> import numpy as np
>>> from glide.monitors import AsymptoticClusteredClassicalRM
>>> pre_drift_batch = np.array([0.0, 0.2, 0.1, 0.3, np.nan, np.nan])
>>> post_drift_batch = np.array([0.8, 1.0, 0.7, 0.9, np.nan, np.nan])
>>> y = np.hstack([pre_drift_batch, np.tile(post_drift_batch, 5)])
>>> clusters = np.repeat(np.arange(18), 2)
>>> batches = np.repeat(np.arange(6), 6)
>>> monitor = AsymptoticClusteredClassicalRM()
>>> result = monitor.detect(y, clusters, batches, higher_is_better=False, threshold=0.5)
>>> result.drift_detected
True
>>> result.first_alarm_index
2
Source code in glide/monitors/asymptotic_clustered_classical.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | |
detect
detect(
y,
clusters,
batches,
*,
higher_is_better,
threshold,
metric_name="Metric",
confidence_level=0.8,
tightest_at_batch=10,
)
Detect a drift of the running mean across a batched, clustered dataset.
Splits the data by batch, reduces each batch's labeled observations to
per-cluster means, computes the classical mean and its standard error on
those means, and builds an anytime-valid asymptotic confidence sequence on
the running mean of the per-batch estimates. An alarm is raised at every
batch where the sequence crosses the user-supplied threshold. See
AsymptoticClassicalRM.detect for the full explanation of batch ordering,
growing-history semantics, and tightest_at_batch, which all carry over
unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y
|
NDArray
|
Array of observations, shape |
required |
clusters
|
NDArray
|
Array of cluster identifiers, shape |
required |
batches
|
NDArray
|
Array of batch identifiers, shape |
required |
higher_is_better
|
bool
|
|
required |
threshold
|
float
|
The metric value the running mean is monitored against, in metric units: the worst level the user is willing to tolerate. An alarm fires once the anytime-valid bound proves the running metric has crossed it (the running risk exceeds it for a risk, the running performance falls below it for a performance). |
required |
metric_name
|
str
|
Human-readable label for the metric. Defaults to |
'Metric'
|
confidence_level
|
float
|
How confident each alarm should be. At the default |
0.8
|
tightest_at_batch
|
int
|
The batch index (1-indexed) at which the confidence sequence is tuned to
be tightest. Defaults to |
10
|
Returns:
| Type | Description |
|---|---|
ClassicalMeanMonitoringResult
|
Per-batch estimates, running means, anytime-valid confidence bounds,
alarm flags, and the alarm threshold, all in the original metric
orientation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Source code in glide/monitors/asymptotic_clustered_classical.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | |
glide.monitors.asymptotic_pprm.AsymptoticPPRM
Bases: AsymptoticRM[PPIDataset, float]
Anytime-valid drift monitor leveraging the variance of each batch estimate.
It computes a per-batch Prediction-Powered Inference (PPI) estimate: a small set
of true labels and a large set of proxy labels, combined with a power-tuning
parameter fitted on the batches that strictly precede it (predictable, as
required for validity), together with the standard error of that estimate. The
monitor tracks the running mean of the per-batch estimates against a
user-supplied threshold, through a Gaussian-mixture asymptotic confidence
sequence whose width scales with the standard error of each batch estimate, so
genuine drifts get flagged early. The false-alarm guarantee is asymptotic: each
batch needs enough labeled and proxy samples for its PPI estimate to be
approximately Gaussian with a consistently estimated variance.
References
Waudby-Smith, Ian, David Arbour, Ritwik Sinha, Edward H. Kennedy, and Aaditya Ramdas. "Time-uniform central limit theory and asymptotic confidence sequences." The Annals of Statistics 52, no. 6 (2024): 2613-2640.
Zhang, Guangyi, Yunlong Cai, Guanding Yu, and Osvaldo Simeone. "Prediction-powered risk monitoring of deployed models for detecting harmful distribution shifts." arXiv preprint arXiv:2602.02229 (2026).
Podkopaev, Aleksandr, and Aaditya Ramdas. "Tracking the risk of a deployed model and detecting harmful distribution shifts." International Conference on Learning Representations (ICLR), 2022.
Examples:
>>> import numpy as np
>>> from glide.monitors import AsymptoticPPRM
>>> pre_drift_y_true = np.array([0.0, 0.2, np.nan, np.nan])
>>> pre_drift_y_proxy = np.array([0.0, 0.2, 0.0, 0.2])
>>> post_drift_y_true = np.array([0.8, 1.0, np.nan, np.nan])
>>> post_drift_y_proxy = np.array([0.8, 1.0, 0.8, 1.0])
>>> y_true = np.hstack([pre_drift_y_true, np.tile(post_drift_y_true, 5)])
>>> y_proxy = np.hstack([pre_drift_y_proxy, np.tile(post_drift_y_proxy, 5)])
>>> batches = np.repeat(np.arange(6), 4)
>>> monitor = AsymptoticPPRM()
>>> result = monitor.detect(y_true, y_proxy, batches, higher_is_better=False, threshold=0.5)
>>> result.drift_detected
True
>>> result.first_alarm_index
2
Source code in glide/monitors/asymptotic_pprm.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
detect
detect(
y_true,
y_proxy,
batches,
*,
higher_is_better,
threshold,
metric_name="Metric",
confidence_level=0.8,
power_tuning=True,
tightest_at_batch=10,
)
Detect a drift of the running mean across a batched dataset.
Splits the data by batch, computes a prediction-powered estimate and its
standard error per batch, and builds an anytime-valid asymptotic confidence
sequence on the running mean of those estimates. An alarm is raised at every
batch where the sequence crosses the user-supplied threshold.
Rows must be ordered oldest batch first and grouped into contiguous blocks;
identifier values are not compared, so any label type works. Batches must be
non-overlapping (no shared samples), and successive calls must be made on
growing histories of the same data; passing the full accumulated dataset at
every call makes the anytime-valid guarantee hold jointly over all calls.
Alternatively the data may be restricted to the most recent batches, in which
case the guarantee holds within each restriction but not across the moving
history as a whole. When the history has fewer batches than tightest_at_batch,
the tuning target is set to the last batch. Prefix-consistency only holds between
calls using the same tightest_at_batch value and with histories containing
at least tightest_at_batch batches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
NDArray
|
Array of labeled observations, shape |
required |
y_proxy
|
NDArray
|
Array of proxy predictions, shape |
required |
batches
|
NDArray
|
Array of batch identifiers, shape |
required |
higher_is_better
|
bool
|
|
required |
threshold
|
float
|
The metric value the running mean is monitored against, in metric units: the worst level the user is willing to tolerate. An alarm fires once the anytime-valid bound proves the running metric has crossed it (the running risk exceeds it for a risk, the running performance falls below it for a performance). |
required |
metric_name
|
str
|
Human-readable label for the metric. Defaults to |
'Metric'
|
confidence_level
|
float
|
How confident each alarm should be. At the default |
0.8
|
power_tuning
|
bool
|
If |
True
|
tightest_at_batch
|
int
|
The batch index (1-indexed) at which the confidence sequence is tuned to
be tightest. Defaults to |
10
|
Returns:
| Type | Description |
|---|---|
PredictionPoweredMeanMonitoringResult
|
Per-batch estimates, running means, anytime-valid confidence bounds, alarm flags, and the alarm threshold, all in the original metric orientation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Source code in glide/monitors/asymptotic_pprm.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
glide.monitors.asymptotic_stratified_pprm.AsymptoticStratifiedPPRM
Bases: AsymptoticRM[StratifiedPPIDataset, StratifiedTuningParameter]
Anytime-valid drift monitor combining human and proxy labels over a stratified stream.
Computes a per-batch Stratified PPI estimate together with its standard error.
Each batch's samples are split into strata, a power-tuned PPI++ estimate is
computed independently within each stratum using a weight fitted on the batches
that strictly precede it, and the per-stratum estimates are combined with
population-proportional weights. The monitor then tracks the running mean of the
per-batch estimates the same way AsymptoticPPRM does for an unstratified
stream. The false-alarm guarantee is asymptotic: each batch needs enough labeled
and proxy samples, within each of its strata, for its Stratified PPI estimate to
be approximately Gaussian with a consistently estimated variance.
References
Waudby-Smith, Ian, David Arbour, Ritwik Sinha, Edward H. Kennedy, and Aaditya Ramdas. "Time-uniform central limit theory and asymptotic confidence sequences." The Annals of Statistics 52, no. 6 (2024): 2613-2640.
Zhang, Guangyi, Yunlong Cai, Guanding Yu, and Osvaldo Simeone. "Prediction-powered risk monitoring of deployed models for detecting harmful distribution shifts." arXiv preprint arXiv:2602.02229 (2026).
Podkopaev, Aleksandr, and Aaditya Ramdas. "Tracking the risk of a deployed model and detecting harmful distribution shifts." International Conference on Learning Representations (ICLR), 2022.
Fisch, Adam, Joshua Maynez, R. Alex Hofer, Bhuwan Dhingra, Amir Globerson, and William W. Cohen. "Stratified prediction-powered inference for effective hybrid evaluation of language models." Advances in Neural Information Processing Systems 37 (2024): 111489-111514.
Fogliato, Riccardo, Pratik Patil, Mathew Monfort, and Pietro Perona. "A framework for efficient model evaluation through stratification, sampling, and estimation." In European Conference on Computer Vision, pp. 140-158. Cham: Springer Nature Switzerland, 2024.
Examples:
>>> import numpy as np
>>> from glide.monitors import AsymptoticStratifiedPPRM
>>> pre_drift_y_true = np.array([0.0, 0.2, np.nan, np.nan, 0.1, 0.3, np.nan, np.nan])
>>> pre_drift_y_proxy = np.array([0.0, 0.2, 0.0, 0.2, 0.1, 0.3, 0.1, 0.3])
>>> post_drift_y_true = np.array([0.8, 1.0, np.nan, np.nan, 0.7, 0.9, np.nan, np.nan])
>>> post_drift_y_proxy = np.array([0.8, 1.0, 0.8, 1.0, 0.7, 0.9, 0.7, 0.9])
>>> y_true = np.hstack([pre_drift_y_true, np.tile(post_drift_y_true, 5)])
>>> y_proxy = np.hstack([pre_drift_y_proxy, np.tile(post_drift_y_proxy, 5)])
>>> groups = np.tile([0, 0, 0, 0, 1, 1, 1, 1], 6)
>>> batches = np.repeat(np.arange(6), 8)
>>> monitor = AsymptoticStratifiedPPRM()
>>> result = monitor.detect(y_true, y_proxy, groups, batches, higher_is_better=False, threshold=0.5)
>>> result.drift_detected
True
>>> result.first_alarm_index
2
Source code in glide/monitors/asymptotic_stratified_pprm.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
detect
detect(
y_true,
y_proxy,
groups,
batches,
*,
higher_is_better,
threshold,
metric_name="Metric",
confidence_level=0.8,
power_tuning=True,
tightest_at_batch=10,
)
Detect a drift of the running mean across a batched, stratified dataset.
Splits the data by batch, then by stratum within each batch, computes a
Stratified PPI estimate and its standard error per batch, and builds an
anytime-valid asymptotic confidence sequence on the running mean of those
estimates. An alarm is raised at every batch where the sequence crosses the
user-supplied threshold. See AsymptoticPPRM.detect for the full
explanation of batch ordering, growing-history semantics, and
tightest_at_batch, which all carry over unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
NDArray
|
Array of labeled observations, shape |
required |
y_proxy
|
NDArray
|
Array of proxy predictions, shape |
required |
groups
|
NDArray
|
Array of stratum identifiers, shape |
required |
batches
|
NDArray
|
Array of batch identifiers, shape |
required |
higher_is_better
|
bool
|
|
required |
threshold
|
float
|
The metric value the running mean is monitored against, in metric units. |
required |
metric_name
|
str
|
Human-readable label for the metric. Defaults to |
'Metric'
|
confidence_level
|
float
|
How confident each alarm should be. Must be in |
0.8
|
power_tuning
|
bool
|
If |
True
|
tightest_at_batch
|
int
|
The batch index (1-indexed) at which the confidence sequence is tuned to
be tightest. Defaults to |
10
|
Returns:
| Type | Description |
|---|---|
PredictionPoweredMeanMonitoringResult
|
Per-batch estimates, running means, anytime-valid confidence bounds,
alarm flags, and the alarm threshold, all in the original metric
orientation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Source code in glide/monitors/asymptotic_stratified_pprm.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
glide.monitors.asymptotic_clustered_pprm.AsymptoticClusteredPPRM
Bases: AsymptoticRM[ClusteredPPIDataset, float]
Anytime-valid drift monitor combining human and proxy labels over clustered data.
Computes a per-batch Clustered PPI estimate (each batch's observations are reduced
to per-cluster means, and a power-tuned PPI++ estimate is computed on those means
using a weight fitted on the batches that strictly precede it, predictable as
required for validity), together with its standard error, and tracks the running
mean of the per-batch estimates the same way AsymptoticPPRM does for
independent, unclustered samples.
References
Waudby-Smith, Ian, David Arbour, Ritwik Sinha, Edward H. Kennedy, and Aaditya Ramdas. "Time-uniform central limit theory and asymptotic confidence sequences." The Annals of Statistics 52, no. 6 (2024): 2613-2640.
Zhang, Guangyi, Yunlong Cai, Guanding Yu, and Osvaldo Simeone. "Prediction-powered risk monitoring of deployed models for detecting harmful distribution shifts." arXiv preprint arXiv:2602.02229 (2026).
Podkopaev, Aleksandr, and Aaditya Ramdas. "Tracking the risk of a deployed model and detecting harmful distribution shifts." International Conference on Learning Representations (ICLR), 2022.
Broska, David. "Cluster-robust PPI reference implementation." https://github.com/davidbroska/ppi_py/blob/main/ClusterPPI/mean.py
Examples:
>>> import numpy as np
>>> from glide.monitors import AsymptoticClusteredPPRM
>>> pre_drift_y_true = np.array([0.0, 0.2, np.nan, np.nan, 0.1, 0.3, np.nan, np.nan])
>>> pre_drift_y_proxy = np.array([0.0, 0.2, 0.0, 0.2, 0.1, 0.3, 0.1, 0.3])
>>> post_drift_y_true = np.array([0.8, 1.0, np.nan, np.nan, 0.7, 0.9, np.nan, np.nan])
>>> post_drift_y_proxy = np.array([0.8, 1.0, 0.8, 1.0, 0.7, 0.9, 0.7, 0.9])
>>> y_true = np.hstack([pre_drift_y_true, np.tile(post_drift_y_true, 5)])
>>> y_proxy = np.hstack([pre_drift_y_proxy, np.tile(post_drift_y_proxy, 5)])
>>> clusters = np.repeat(np.arange(24), 2)
>>> batches = np.repeat(np.arange(6), 8)
>>> monitor = AsymptoticClusteredPPRM()
>>> result = monitor.detect(y_true, y_proxy, clusters, batches, higher_is_better=False, threshold=0.5)
>>> result.drift_detected
True
>>> result.first_alarm_index
2
Source code in glide/monitors/asymptotic_clustered_pprm.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | |
detect
detect(
y_true,
y_proxy,
clusters,
batches,
*,
higher_is_better,
threshold,
metric_name="Metric",
confidence_level=0.8,
power_tuning=True,
tightest_at_batch=10,
)
Detect a drift of the running mean across a batched, clustered dataset.
Splits the data by batch, reduces each batch's observations to per-cluster
means, computes a Clustered PPI estimate and its standard error per batch, and
builds an anytime-valid asymptotic confidence sequence on the running mean of
those estimates. An alarm is raised at every batch where the sequence crosses
the user-supplied threshold. See AsymptoticPPRM.detect for the full
explanation of batch ordering, growing-history semantics, and
tightest_at_batch, which all carry over unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
NDArray
|
Array of labeled observations, shape |
required |
y_proxy
|
NDArray
|
Array of proxy predictions, shape |
required |
clusters
|
NDArray
|
Array of cluster identifiers, shape |
required |
batches
|
NDArray
|
Array of batch identifiers, shape |
required |
higher_is_better
|
bool
|
|
required |
threshold
|
float
|
The metric value the running mean is monitored against, in metric units. |
required |
metric_name
|
str
|
Human-readable label for the metric. Defaults to |
'Metric'
|
confidence_level
|
float
|
How confident each alarm should be. Must be in |
0.8
|
power_tuning
|
bool
|
If |
True
|
tightest_at_batch
|
int
|
The batch index (1-indexed) at which the confidence sequence is tuned to
be tightest. Defaults to |
10
|
Returns:
| Type | Description |
|---|---|
PredictionPoweredMeanMonitoringResult
|
Per-batch estimates, running means, anytime-valid confidence bounds,
alarm flags, and the alarm threshold, all in the original metric
orientation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Source code in glide/monitors/asymptotic_clustered_pprm.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | |
glide.monitors.asymptotic_multi_pprm.AsymptoticMultiPPRM
Bases: AsymptoticRM[MultiPPIDataset, NDArray]
Anytime-valid drift monitor combining human labels with multiple proxy predictors.
Computes a per-batch Multi-PPI estimate (a small set of true labels and several
sets of proxy labels, combined through a power-tuning weight vector fitted on the
batches that strictly precede it), together with its standard error, and tracks
the running mean of the per-batch estimates the same way AsymptoticPPRM does
for a single proxy. The false-alarm guarantee is asymptotic: each batch needs
enough labeled and proxy samples for its Multi-PPI estimate to be approximately
Gaussian with a consistently estimated variance.
References
Waudby-Smith, Ian, David Arbour, Ritwik Sinha, Edward H. Kennedy, and Aaditya Ramdas. "Time-uniform central limit theory and asymptotic confidence sequences." The Annals of Statistics 52, no. 6 (2024): 2613-2640.
Zhang, Guangyi, Yunlong Cai, Guanding Yu, and Osvaldo Simeone. "Prediction-powered risk monitoring of deployed models for detecting harmful distribution shifts." arXiv preprint arXiv:2602.02229 (2026).
Podkopaev, Aleksandr, and Aaditya Ramdas. "Tracking the risk of a deployed model and detecting harmful distribution shifts." International Conference on Learning Representations (ICLR), 2022.
Shan, Jiawei, Zhifeng Chen, Yiming Dong, Yazhen Wang, and Jiwei Zhao. "SADA: Safe and Adaptive Aggregation of Multiple Black-Box Predictions in Semi-Supervised Learning." arXiv preprint arXiv:2509.21707 (2025).
Examples:
>>> import numpy as np
>>> from glide.monitors import AsymptoticMultiPPRM
>>> pre_drift_y_true = np.array([0.0, 0.2, np.nan, np.nan])
>>> pre_drift_y_proxies = np.array([[0.0, 0.1], [0.2, 0.3], [0.05, 0.25], [0.15, 0.05]])
>>> post_drift_y_true = np.array([0.8, 1.0, np.nan, np.nan])
>>> post_drift_y_proxies = pre_drift_y_proxies + 0.8
>>> y_true = np.hstack([pre_drift_y_true, np.tile(post_drift_y_true, 5)])
>>> y_proxies = np.vstack([pre_drift_y_proxies, np.tile(post_drift_y_proxies, (5, 1))])
>>> batches = np.repeat(np.arange(6), 4)
>>> monitor = AsymptoticMultiPPRM()
>>> result = monitor.detect(y_true, y_proxies, batches, higher_is_better=False, threshold=0.5)
>>> result.drift_detected
True
>>> result.first_alarm_index
2
Source code in glide/monitors/asymptotic_multi_pprm.py
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | |
detect
detect(
y_true,
y_proxies,
batches,
*,
higher_is_better,
threshold,
metric_name="Metric",
confidence_level=0.8,
power_tuning=True,
tightest_at_batch=10,
)
Detect a drift of the running mean across a batched dataset.
Splits the data by batch, computes a Multi-PPI estimate and its standard error
per batch, and builds an anytime-valid asymptotic confidence sequence on the
running mean of those estimates. An alarm is raised at every batch where the
sequence crosses the user-supplied threshold. See AsymptoticPPRM.detect
for the full explanation of batch ordering, growing-history semantics, and
tightest_at_batch, which all carry over unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
NDArray
|
Array of labeled observations, shape |
required |
y_proxies
|
NDArray
|
2D array of proxy predictions, shape |
required |
batches
|
NDArray
|
Array of batch identifiers, shape |
required |
higher_is_better
|
bool
|
|
required |
threshold
|
float
|
The metric value the running mean is monitored against, in metric units. |
required |
metric_name
|
str
|
Human-readable label for the metric. Defaults to |
'Metric'
|
confidence_level
|
float
|
How confident each alarm should be. Must be in |
0.8
|
power_tuning
|
bool
|
If |
True
|
tightest_at_batch
|
int
|
The batch index (1-indexed) at which the confidence sequence is tuned to
be tightest. Defaults to |
10
|
Returns:
| Type | Description |
|---|---|
PredictionPoweredMeanMonitoringResult
|
Per-batch estimates, running means, anytime-valid confidence bounds,
alarm flags, and the alarm threshold, all in the original metric
orientation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Source code in glide/monitors/asymptotic_multi_pprm.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | |