Skip to main content

trosna-weighted-regression

PyPI Python License: MIT

Исходный код: https://github.com/89605502155/trosna-weighted-regression

Взвешенная по времени линейная регрессия с защитой от «засыпания» при резких изменениях. Чистый Python (numpy + scikit-learn), эстиматор совместим со sklearn.

pip install trosna-weighted-regression

Проблема

Базовая модель (Ферубко, Казаков, Вестник РГРТУ, 2026, № 95, с. 73–84): прямая строится по 5 последним точкам, вес точки w_i ∝ |t − t_i|^(−n) (метрическое ядро) или exp(−(t − t_i)² / 2h²) (экспоненциальное), t — момент следующего мониторинга. После долгой полки или спада старые точки окна тянут наклон назад:

Сценарий (прогноз на шаг вперёд, n = 1) Истинные значения Без защиты С защитой
Ступенька 1000 → 1500 1500 1500 1500 1500 1500 1000 1541 1676 1676 1608 1000 1500 1500 1500 1500
Спад, затем рост +100/шаг 910 1010 1110 1210 1310 800 909 1048 1186 1310 800 910 1110 1210 1310
Всплеск на одну точку 1500 1000 1000 1000 1000 1000 1541 1135 1000 932 1000 1500 1000 1000 1000
Провал на одну точку 500 1000 1000 1000 1000 1000 459 865 1000 1068 1000 1000 1000 1000 1000

Первую точку скачка не предсказывает никто — дело в том, что происходит после неё.

Защита

  1. Детектор разладки. Новая точка сравнивается с прогнозом на неё. Ошибка нормируется на своё стандартное отклонение: шум точки σ, умноженный на √(1 + Σc_i²), где ŷ = Σc_i·y_i — прогноз (по двум свежим точкам он втрое шумнее одной точки, по пяти — заметно тише). σ — медиана модулей последних scale_window нормированных остатков, но не ниже min_scale (на ровной полке оценка была бы нулевой). Ошибка больше threshold — разладка.
  2. Пробуждение. При разладке точки до неё выбрасываются, окно строится заново с точки разладки. Пока у нового режима меньше 5 остатков, шум берётся из прежнего режима — детектор не слепнет и ловит второй скачок сразу за первым. Повторные разладки в это время учитываются в оценке шума, поэтому переход в более шумный режим не вызывает бесконечного каскада перестроек.
  3. Излом тренда. Пока в новом окне одна точка, прогноз — её уровень. Следующая точка, легшая на прямую от последней точки прежнего режима через точку перестройки, — продолжение разворота (долгий спад → рост), и модель сразу идёт по новому наклону. Точка, не легшая ни на уровень, ни на излом, — новая разладка: так ложное срабатывание, за которым следует настоящий скачок, не удваивает скачок в прогнозе.
  4. Асимметрия. Рост принимается сразу (confirm_up=0): недодать память опаснее, чем выдать лишнюю. Спад — только после confirm_down=1 подтверждающей точки, до этого модель держит прежний уровень.
  5. Откат всплесков. Если после немедленной перестройки следующая точка вернулась к старому режиму, старое окно и оценка шума восстанавливаются, а всплеск отбрасывается (spikes_). Неподтверждённый спад тоже отбрасывается.

guard=False — базовая модель из статьи без защиты, для сравнения.

Дополнительные механизмы

По умолчанию выключены или не меняют прогноз: базовые настройки дают модель из статьи плюс защиту выше.

  1. Адаптивное окно (ICI) — adaptive_window=True, window — наибольшая длина окна. На каждом прогнозе строятся прямые по последним 3, 5, 8, 12, … точкам режима, и берётся самое длинное окно, интервал прогноза которого (±ici_gamma·σ·√Σc²) ещё пересекается с интервалами всех более коротких. На ровном участке окно растёт и прогноз тише, на изломе короткие окна расходятся с длинными, и окно сразу укорачивается. Правило пересечения доверительных интервалов — Гольденшлюгер и Немировский, Катковник (LPA-ICI).
  2. Накопительный детектор CUSUM — cusum_h (порог, None — выключен) и cusum_k (допуск). Те же нормированные ошибки прогноза копятся по Пейджу: S⁺ = max(0, S⁺ + z − k), отдельно вниз. Ловит устойчивые сдвиги меньше threshold, на которых длинное адаптивное окно засыпало бы. При срабатывании окно строится заново с точки, с которой начала копиться сумма.
  3. Интервал прогноза — predict_interval(X) возвращает (lower, upper) с покрытием coverage. Полуширина — квантиль нормированных модулей последних interval_window ошибок прогноза на шаг вперёд, умноженный на шум прогноза в точке. Уровень квантиля подстраивается онлайн (адаптивный конформный вывод, Гиббс и Кандес): после промаха интервал расширяется, после попадания понемногу сужается. Шаг подстройки — aci_rate, текущий уровень промахов — interval_alpha_. Верхняя граница — объём ОП, который стоит зарезервировать.

Рекомендуемый набор: WakefulWLS(window=30, adaptive_window=True, cusum_h=5.0).

Проверка на шуме

Монте-Карло: полка, спад или рост длиной 200 точек, затем скачок; шум σ = 5, по 10 запусков на конфигурацию, ядра метрическое и экспоненциальное, окна 5 и 10. «Шагов» — сколько шагов после скачка прогноз ещё выходит за 4σ от истины.

Скачок Шагов: без защиты / с защитой Средняя ошибка, МБ: без / с
Вверх на 30σ (150 МБ) 5–8,4 / 1 8,2–8,5 / 3,9–5,1
Вверх на 120σ (600 МБ) 5–10 / 1 19,7–25,9 / 3,9–5,1
Вниз на 30σ и 120σ 5–10 / 2 примерно равны
Пограничный, 6σ (окно 10) 1 / 1,7–1,8 3,8–4,4 / 4,0–4,8

Спад занимает 2 шага, потому что так задано (confirm_down=1, 0 — реагировать сразу). На пограничных скачках защита чуть уступает: после перестройки прогноз строится по 2–3 свежим точкам и шумнее. Ложные срабатывания на стационарном гауссовом шуме — около 1 на 1000 точек, на шуме с тяжёлыми хвостами (t₃) — около 11; почти все они откатываются как всплески на следующей же точке.

Дополнительные механизмы

Тот же стенд, метрическое ядро. «База» — window=5, «защита» — window=5 с защитой, «ICI» — плюс window=30, adaptive_window=True, «ICI + CUSUM» — плюс cusum_h=5. Ячейки — шагов до точного прогноза / средняя ошибка, МБ.

Сценарий База Защита ICI ICI + CUSUM
Стационарный шум, ошибка, МБ 4,6 4,6 2,2 2,2
Скачок вверх на 30σ 5 / 8,2 1 / 5,1 1 / 3,4 1 / 3,4
Скачок вверх на 6σ 1,2 / 5,2 1,5 / 5,3 1 / 3,6 1 / 3,5
Скачок вниз на 6σ 1,1 / 5,2 1,5 / 5,5 1,6 / 4,1 1,6 / 4,0
Новый наклон 1σ/шаг после полки 0 / 4,9 0 / 4,9 0–1 / 5,2 0 / 3,9
Новый наклон 3σ/шаг после полки 0,6–0,8 / 5,1–5,2 0,6–0,9 / 5,2–5,3 2,8–5,2 / 5,5–6,5 1,8–2,2 / 4,2
Новый наклон 10σ/шаг после полки 3 / 6,6 2 / 6,2 2 / 4,6 2 / 4,6

Адаптивное окно вдвое снижает ошибку на спокойных участках и после скачков. Слабое место — излом наклона порядка 3σ за шаг: без CUSUM длинное окно выходит на новый наклон на 2–4 шага позже короткого. CUSUM сокращает отставание до 1–1,5 шага, а средняя ошибка с ним ниже, чем у окна из 5 точек. С окном из 5 точек CUSUM почти ничего не даёт: короткое окно и так догоняет за несколько шагов. Экспоненциальное ядро (h = 3) само почти не смотрит дальше 6–8 точек, поэтому выигрыш от ICI у него скромнее: около 20 % на шуме.

Интервал на 95 % (6 запусков по 1500 точек):

Ряд Покрытие, без подстройки / с ней Покрытие 10 шагов после скачка
Гауссов шум 0,951 / 0,949 —
Шум t₃ с тяжёлыми хвостами 0,950 / 0,950 —
Скачки каждые 150 точек, шум вырос втрое 0,937 / 0,949 0,87 / 0,91

С адаптивным окном интервал на 25–30 % уже при том же покрытии.

Использование

import numpy as np
from trosna_weighted_regression import WakefulWLS

t = np.arange(len(mem), dtype=float)[:, None]  # одна колонка времени
model = WakefulWLS(window=5, kernel="metric", power=1, min_scale=10).fit(t, mem)  # mem в МБ
model.predict([[t[-1, 0] + 1]])  # прогноз на следующий мониторинг
model.change_points_, model.spikes_  # где модель «проснулась» и какие всплески отбросила

# Поток: дообучение по мере поступления точек, эквивалентно fit на всём ряде
model.partial_fit([[t_new]], [mem_new])

# Адаптивное окно + CUSUM; верхняя граница 95 % интервала — сколько памяти зарезервировать
model = WakefulWLS(window=30, adaptive_window=True, cusum_h=5.0, min_scale=10).fit(t, mem)
lower, upper = model.predict_interval([[t[-1, 0] + 1]])

Работает в GridSearchCV (с TimeSeriesSplit), Pipeline, clone. X — ровно одна колонка времени, поэтому стандартные проверки sklearn, подающие несколько признаков, помечены в тестах как ожидаемые падения; остальные проходят.

Разработка

git clone https://github.com/89605502155/trosna-weighted-regression.git
cd trosna-weighted-regression
uv sync
uv run pytest
uv run ruff check . && uv run ruff format --check .

Лицензия

MIT, см. LICENSE.

Metadata

Release files for trosna-weighted-regression 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trosna-weighted-regression 0.1.0
File Size Uploaded
trosna_weighted_regression-0.1.0.tar.gz 17.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trosna-weighted-regression 0.1.0
File Interpreter ABI Platform
trosna_weighted_regression-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 35.7 kB

Release files / trosna_weighted_regression-0.1.0.tar.gz

Download URL trosna_weighted_regression-0.1.0.tar.gz
Size 17.3 kB
Tags Source
SHA-256 checksum
How to use checksums
79c0ae7e63a415ca39c019572e9184c15f32b445358d329370f653e9f0caa257
BLAKE2b-256 checksum
How to use checksums
83304bc3f21661cdab6bfe4fd2a665de887970620e1a611e3675bbbff30f03a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.9 {"installer":{"name":"uv","version":"0.11.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / trosna_weighted_regression-0.1.0-py3-none-any.whl

Download URL trosna_weighted_regression-0.1.0-py3-none-any.whl
Size 18.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
62594c959e2e369aec815a90fc3fcac341d15e449d738e029aeeae44315494ee
BLAKE2b-256 checksum
How to use checksums
f1ab62496ab82ac7078c83f24dd4b494666c58fa9b3302380d7ca29c89d66ee3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.9 {"installer":{"name":"uv","version":"0.11.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page