Конформные интервалы в production ML при covariate shift: как держать coverage без бесполезно широких предсказаний
Split conformal хорошо работает при exchangeability: train, calibration и test приходят из одного распределения. В production это часто ломается из-за гео, девайсов, каналов, сезонности или смены acquisition mix, а типичная ошибка - просто расширить интервалы “с запасом”.
Что именно ломается
При covariate shift имеем:
но предполагаем, что
Наивное решение - увеличить correction глобально. Coverage частично вернется, но price prediction interval, ETA interval или forecast band станут настолько широкими, что downstream-система перестанет им доверять.
Базовый production-рецепт
1. Учим quantile-модель:
2. На calibration set считаем nonconformity scores:
3. Оцениваем importance weights:
4. Берем не обычный, а weighted quantile score'ов.
5. Для нового объекта строим:
Минимальный скелет:
Так calibration distribution становится ближе к production distribution без грубого раздувания всех интервалов.
Как не получить слишком широкие интервалы
Один глобальный
Практически помогают:
- CQR вместо point prediction: Conformalized Quantile Regression уже моделирует heteroscedastic uncertainty, поэтому conformal correction обычно меньше.
- Нормализованный score: например
- Локальная калибровка: отдельный
- Rolling calibration buffer: для рекомендаций, скоринга и forecasting старый calibration set быстро перестает описывать текущий traffic mix.
Главный риск - плохие веса
Density ratio model может быть шумной. Несколько объектов с огромными весами фактически “заменят” весь calibration set.
Контролируйте:
Если ESS низкий, weighted quantile нестабилен, а интервалы начинают прыгать от релиза к релизу.
Практичные меры:
- clip weights и мониторить долю clipped weights;
- сглаживать density ratio;
- объединять редкие сегменты;
- не калибровать сегмент, где мало свежих labels;
- запускать перекалибровку при падении ESS или drift по
Production-чеклист
- отдельный calibration set, не смешанный с training;
- drift detection по feature distribution;
- density ratio model между prod traffic и calibration traffic;
- weighted conformal calibration;
- мониторинг coverage, average width, coverage по slices, ESS и latency;
- алерты на рост ширины интервалов без роста ошибки;
- A/B validation, если интервалы влияют на routing, fallback или human review.
Важно не путать marginal и conditional coverage. Conformal может держать 90% coverage на потоке в среднем, но проваливаться в отдельных микросегментах. В production это надо проверять явно.
Вывод:
При covariate shift цель не в том, чтобы слепо расширить интервалы, а в том, чтобы калибровать их под текущую смесь production-объектов и контролировать надежность этой калибровки.
Split conformal хорошо работает при exchangeability: train, calibration и test приходят из одного распределения. В production это часто ломается из-за гео, девайсов, каналов, сезонности или смены acquisition mix, а типичная ошибка - просто расширить интервалы “с запасом”.
Что именно ломается
При covariate shift имеем:
p_prod(x) != p_cal(x)но предполагаем, что
p(y|x) примерно сохраняется. Если считать обычный conformal quantile на старом calibration set, coverage на текущем трафике может просесть.Наивное решение - увеличить correction глобально. Coverage частично вернется, но price prediction interval, ETA interval или forecast band станут настолько широкими, что downstream-система перестанет им доверять.
Базовый production-рецепт
1. Учим quantile-модель:
q_low(x), q_high(x)2. На calibration set считаем nonconformity scores:
s_i = max(q_low(x_i)-y_i, y_i-q_high(x_i), 0)3. Оцениваем importance weights:
w_i ~= p_prod(x_i) / p_cal(x_i)4. Берем не обычный, а weighted quantile score'ов.
5. Для нового объекта строим:
C(x) = [q_low(x)-tau, q_high(x)+tau]Минимальный скелет:
import numpy as np
def weighted_quantile(values, weights, q):
order = np.argsort(values)
v = np.asarray(values)[order]
w = np.asarray(weights)[order]
cw = np.cumsum(w)
return v[np.searchsorted(cw, q * cw[-1])]
alpha = 0.1
scores = np.maximum(q_low_cal - y_cal,
y_cal - q_high_cal,
0)
weights = ratio_model.predict_weight(X_cal)
tau = weighted_quantile(scores, weights, 1 - alpha)
low = q_low_prod - tau
high = q_high_prod + tau
Так calibration distribution становится ближе к production distribution без грубого раздувания всех интервалов.
Как не получить слишком широкие интервалы
Один глобальный
tau часто переоценивает неопределенность, если ошибка модели сильно зависит от x.Практически помогают:
- CQR вместо point prediction: Conformalized Quantile Regression уже моделирует heteroscedastic uncertainty, поэтому conformal correction обычно меньше.
- Нормализованный score: например
s_i = |y_i - y_hat_i| / sigma_hat(x_i), а интервал строится как y_hat(x) +- tau * sigma_hat(x).- Локальная калибровка: отдельный
tau по geo, device, channel, price bucket или risk bucket. Это близко к Mondrian conformal, но требует достаточного числа calibration examples в каждом сегменте.- Rolling calibration buffer: для рекомендаций, скоринга и forecasting старый calibration set быстро перестает описывать текущий traffic mix.
Главный риск - плохие веса
Density ratio model может быть шумной. Несколько объектов с огромными весами фактически “заменят” весь calibration set.
Контролируйте:
ESS = (sum w)^2 / sum(w^2)Если ESS низкий, weighted quantile нестабилен, а интервалы начинают прыгать от релиза к релизу.
Практичные меры:
- clip weights и мониторить долю clipped weights;
- сглаживать density ratio;
- объединять редкие сегменты;
- не калибровать сегмент, где мало свежих labels;
- запускать перекалибровку при падении ESS или drift по
X.Production-чеклист
- отдельный calibration set, не смешанный с training;
- drift detection по feature distribution;
- density ratio model между prod traffic и calibration traffic;
- weighted conformal calibration;
- мониторинг coverage, average width, coverage по slices, ESS и latency;
- алерты на рост ширины интервалов без роста ошибки;
- A/B validation, если интервалы влияют на routing, fallback или human review.
Важно не путать marginal и conditional coverage. Conformal может держать 90% coverage на потоке в среднем, но проваливаться в отдельных микросегментах. В production это надо проверять явно.
Вывод:
При covariate shift цель не в том, чтобы слепо расширить интервалы, а в том, чтобы калибровать их под текущую смесь production-объектов и контролировать надежность этой калибровки.
👎2