Материал подготовлен нейросетью DeepSeek.
Введение
Свойство адаптивности цепи Маркова
Механизм адаптивного забывания
Проблема
При текущих настройках:
- alpha = 0.1, interval_minute = 30 → каждые полчаса все частоты умножаются на (1 - 0.1) = 0.9.
- Через 1 неделю (336 половинок = 168 циклов забывания) вес одного наблюдения уменьшается в 0.9^168 ≈ 2.5·10⁻⁸ раз — практически обнуляется.
- Редкий инцидент (1 раз в 1–2 недели) не успевает «закрепиться» в матрице вероятностей.
Цель
Сохранить статистическую значимость редких переходов в аварийные состояния, не нарушая адаптивности модели к текущим условиям.
☑️1. Адаптивное изменение alpha в зависимости от времени, прошедшего с последнего инцидента
Идея
Динамически уменьшать alpha (скорость забывания), когда инциденты редки, и возвращать к базовому значению, когда они становятся чаще.
Реализация (модификация markov_config и apply_forgetting)
Добавить в markov_config новые параметры:
ALTER TABLE markov_config ADD COLUMN base_alpha REAL DEFAULT 0.1;
ALTER TABLE markov_config ADD COLUMN min_alpha REAL DEFAULT 0.01;
ALTER TABLE markov_config ADD COLUMN incident_half_life_days REAL DEFAULT 7.0; -- дни, за которые вес инцидента падает вдвое
ALTER TABLE markov_config ADD COLUMN last_incident_time TIMESTAMPTZ;
Создать функцию, обновляющую last_incident_time при каждом переходе в аварийное состояние.
Модифицировать apply_forgetting, чтобы она вычисляла эффективный alpha по формуле:
alpha_effective = base_alpha * (1 - decay_factor)
где decay_factor = exp(- (now() - last_incident_time) / (half_life / ln(2)) ) — но проще использовать готовую эвристику.
Упрощённый вариант:
Если с момента последнего инцидента прошло более N дней, использовать min_alpha, иначе base_alpha.
Пример кода в apply_forgetting:
DECLARE
cfg RECORD;
days_since_incident REAL;
effective_alpha REAL;
BEGIN
SELECT base_alpha, min_alpha, incident_half_life_days, last_incident_time INTO cfg
FROM markov_config LIMIT 1;
IF cfg.last_incident_time IS NULL THEN
effective_alpha := cfg.min_alpha; -- никогда не было инцидента — не забываем
ELSE
days_since_incident := EXTRACT(EPOCH FROM (now() - cfg.last_incident_time)) / 86400.0;
-- alpha уменьшается экспоненциально с периодом полураспада incident_half_life_days
effective_alpha := cfg.base_alpha * exp(-days_since_incident / cfg.incident_half_life_days);
effective_alpha := GREATEST(effective_alpha, cfg.min_alpha);
END IF;
-- Применяем забывание с effective_alpha вместо фиксированного alpha
UPDATE markov_frequencies SET frequency = frequency * (1.0 - effective_alpha);
...
END;
Результат:
Если инцидент был вчера → alpha ≈ base_alpha (быстрое забывание).
Если инцидента не было 2 недели → alpha ≈ min_alpha (почти не забываем, редкие события сохраняются).
❓2. Разделение частот на «фоновые» и «кратковременные»
Идея
Хранить две матрицы частот:
- markov_frequencies_long — с очень медленным забыванием (alpha = 0.001, период полураспада ~700 циклов или несколько месяцев).
- markov_frequencies_short — с быстрым забыванием (alpha = 0.1) для улавливания текущего тренда.
При прогнозе комбинировать вероятности, например, с весами 0.3 (долгая) + 0.7 (короткая). Редкие инциденты попадают в долгую память и не теряются.
Реализация
- Создать таблицу markov_frequencies_long (структура как у markov_frequencies).
- В log_transition_and_update обновлять обе таблицы.
- apply_forgetting применяет alpha_short к короткой, и alpha_long (маленькое) к длинной.
- При вычислении markov_probabilities использовать взвешенную сумму частот:
- frequency_combined = w * freq_long + (1-w) * freq_short, затем нормализовать.
Преимущество: редкие инциденты живут в долгой памяти месяцами, но текущие изменения учитываются быстро.
📋3. Использование «бустера» важности для редких переходов
Идея
Каждый переход в аварийное состояние получает искусственный «весовой множитель» > 1 при добавлении в markov_frequencies.
В функции update_markov_frequency добавить параметр importance_multiplier, который по умолчанию = 1, а для аварийных переходов = boost_factor (например, 10 или 20).
-- модификация вызова в log_transition_and_update для аварийного to_state
IF (SELECT correlation < 0 AND os_trend = -1 FROM state_descriptions WHERE state_id = to_id) THEN
multiplier := (SELECT incident_boost FROM markov_config); -- например, 10
ELSE
multiplier := 1;
END IF;
INSERT INTO markov_frequencies ... ON CONFLICT DO UPDATE
SET frequency = markov_frequencies.frequency + multiplier;
Важно: при забывании умножение на (1-alpha) применяется ко всем частотам одинаково, но начальный вес аварийного перехода выше, поэтому он исчезнет медленнее.
Недостаток: может исказить реальные вероятности, если бустер слишком велик. Рекомендуется boost_factor = 2..5.
4. Отключение забывания для состояний с очень низкой частотой
Идея
Если для пары (from_state, to_state) частота перехода меньше порога (например, 0.1), не применять к ней забывание — считать такие переходы «памятными» исключениями.
Реализация в apply_forgetting:
UPDATE markov_frequencies
SET frequency = frequency * (1.0 - alpha)
WHERE frequency >= 0.1 OR (to_state IN (SELECT state_id FROM state_descriptions WHERE correlation < 0 AND os_trend = -1));
-- для аварийных переходов забывание применяется всегда, но для очень редких неаварийных — не трогаем
Более чистый вариант: добавить колонку protected BOOLEAN DEFAULT false и в момент добавления аварийного перехода устанавливать protected = true. При забывании обновлять только строки с protected = false.
5. Рекомендуемые параметры для сценария «1 инцидент в 1–2 недели»
Базовый механизм (текущий):
- alpha = 0,1
- interval_minute = 30 минут
Адаптивный alpha (пункт 1 методики):
- min_alpha = 0,005 – 0,01
- incident_half_life_days = 14 дней
- (чтобы инцидент терял половину веса за 2 недели)
Бустер важности (пункт 3 методики):
- incident_boost = 3 – 5
- (в зависимости от желаемой инерции)
Долгая память (пункт 2 методики):
- alpha_long = 0,001 – 0,002
- (период полураспада ~70 дней)
- вес долгой памяти в прогнозе = 0,2 – 0,3
6. Мониторинг эффективности
После внедрения оптимизации отслеживать:
- Вес (frequency) аварийных переходов в markov_frequencies через 1, 2, 4 недели после инцидента.
- Brier Score модели в периоды без инцидентов (не должно резко ухудшаться).
- Количество срабатываний check_and_forget — не должно вырасти более чем в 2 раза из-за замедленного забывания.
📋Рекомендуется сначала внедрить адаптивный alpha (пункт 1) как наименее инвазивный и наиболее управляемый.
Если проблема сохранится, добавить бустер важности (пункт 3) или долгую память (пункт 2).