Monitors
glide.monitors.classical.ClassicalMeanMonitor
Anytime-valid drift monitor over a batched dataset of labels.
It uses the plain sample mean per batch. Unlabeled entries are passed as
np.nan and dropped per batch. To be used on accumulated non-overlapping
production batches by calling :meth:detect on the whole accumulated dataset at
any time. Data is passed oldest batch first, and every batch is monitored. The
monitor computes a sample-mean estimate per batch, builds an anytime-valid
confidence sequence on the running mean of those estimates, and raises a drift
alarm when it crosses a user-supplied threshold (the worst tolerable metric value).
Because the bounds are valid at all times simultaneously, :meth:detect may be called
after every new batch without inflating the false-alarm probability.
References
Howard, Steven R., Aaditya Ramdas, Jon McAuliffe, and Jasjeet Sekhon. "Time-uniform, nonparametric, nonasymptotic confidence sequences." The Annals of Statistics 49, no. 2 (2021): 1055-1080.
Podkopaev, Aleksandr, and Aaditya Ramdas. "Tracking the risk of a deployed model and detecting harmful distribution shifts." International Conference on Learning Representations (ICLR), 2022.
Waudby-Smith, Ian, and Aaditya Ramdas. "Estimating means of bounded random variables by betting." Journal of the Royal Statistical Society Series B: Statistical Methodology 86, no. 1 (2024): 1-27.
Examples:
>>> import numpy as np
>>> from glide.monitors import ClassicalMeanMonitor
>>> 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, 50)])
>>> batches = np.repeat(np.arange(51), 4)
>>> monitor = ClassicalMeanMonitor()
>>> result = monitor.detect(y, batches, higher_is_better=False, threshold=0.5)
>>> result.drift_detected
True
>>> result.first_alarm_index
11
Source code in glide/monitors/classical.py
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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | |
detect
detect(
y,
batches,
higher_is_better,
threshold,
metric_name="Metric",
confidence_level=0.8,
metric_lower_bound=0.0,
metric_upper_bound=1.0,
)
Detect a drift of the running mean across a batched dataset.
Splits the data by batch, computes a sample-mean estimate per batch, and
builds an anytime-valid empirical-Bernstein 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.
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). Must lie within |
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
|
metric_lower_bound
|
float
|
Known lower bound of the metric. Defaults to |
0.0
|
metric_upper_bound
|
float
|
Known upper bound of the metric. Defaults to |
1.0
|
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/classical.py
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 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | |