Как посчитать naive forecast в SQL

Закрепи формулу naive forecast в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать naive forecast в Telegram

Зачем naive forecast

Naive — простейший прогноз: «завтра как сегодня» или «через неделю как неделю назад». Используется как baseline: если ML-модель не обыгрывает naive — она бесполезна. Звучит банально, но 30% прод-моделей реально хуже seasonal naive.

Last value naive

Y_hat_{T+h} = Y_T для всех h. В SQL — просто берём последнее значение:

WITH last_value AS (
    SELECT value, DATE
    FROM daily_metrics
    WHERE metric_name = 'dau'
    ORDER BY DATE DESC
    LIMIT 1
),
forecast AS (
    SELECT
        CURRENT_DATE + h AS forecast_date,
        lv.value AS prediction
    FROM last_value lv
    CROSS JOIN generate_series(1, 14) h
)
SELECT * FROM forecast;

Подходит для рядов без тренда и сезонности — типа стабильной error rate.

Seasonal naive

Y_hat_{T+h} = Y_{T+h−m}, где m — длина сезона. Для дневной метрики с недельной сезонностью:

WITH past_week AS (
    SELECT
        DATE,
        value,
        ROW_NUMBER() OVER (ORDER BY DATE DESC) AS days_ago
    FROM daily_metrics
    WHERE metric_name = 'dau'
      AND DATE >= CURRENT_DATE - INTERVAL '7 days'
),
forecast AS (
    SELECT
        CURRENT_DATE + h AS forecast_date,
        (SELECT value FROM past_week WHERE days_ago = 8 - h) AS prediction
    FROM generate_series(1, 7) h
)
SELECT * FROM forecast;

Для месячной сезонности — m = 12, берём значение 12 месяцев назад.

Drift method

Y_hat_{T+h} = Y_T + h × (Y_T − Y_1) / (T − 1). Linearly extrapolates от первой точки до последней:

WITH series AS (
    SELECT DATE, value
    FROM daily_metrics
    WHERE metric_name = 'dau'
      AND DATE >= CURRENT_DATE - INTERVAL '90 days'
),
endpoints AS (
    SELECT
        MIN(DATE) AS first_date,
        (SELECT value FROM series WHERE DATE = (SELECT MIN(DATE) FROM series)) AS first_value,
        MAX(DATE) AS last_date,
        (SELECT value FROM series WHERE DATE = (SELECT MAX(DATE) FROM series)) AS last_value,
        (MAX(DATE) - MIN(DATE))::INT AS span_days
    FROM series
)
SELECT
    CURRENT_DATE + h AS forecast_date,
    last_value + h * (last_value - first_value)::NUMERIC / NULLIF(span_days, 0) AS prediction
FROM endpoints
CROSS JOIN generate_series(1, 14) h;

Если ряд рос — drift продолжает рост. Не моделирует сезонность.

Закрепи формулу naive forecast в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать naive forecast в Telegram

Naive как benchmark

Сравнить production-модель с seasonal naive:

WITH backtest AS (
    SELECT
        DATE,
        actual,
        model_prediction,
        seasonal_naive_prediction
    FROM forecasts_backtest
    WHERE DATE >= CURRENT_DATE - INTERVAL '30 days'
)
SELECT
    AVG(ABS(actual - model_prediction))         AS mae_model,
    AVG(ABS(actual - seasonal_naive_prediction)) AS mae_naive,
    AVG(ABS(actual - model_prediction))
    / NULLIF(AVG(ABS(actual - seasonal_naive_prediction)), 0) AS mase_ratio
FROM backtest;

mase_ratio < 1 — модель лучше naive. > 1 — хуже, имеет смысл откатить.

Частые ошибки

Ошибка 1. Считать naive plain как «всегда хуже ML». На weekly DAU seasonal naive часто обыгрывает наивные ML-baselines (RF, простые регрессии).

Ошибка 2. Last value на сезонных данных. Прогноз для выходного по понедельнику — ошибка в 30%.

Ошибка 3. Drift на коротких рядах. Drift через 2 точки даёт прямую — переэкстраполирует на длинный horizon.

Ошибка 4. Не учитывать holidays. Если 31 декабря — аномалия, seasonal naive отнесёт аномалию в 31-12 следующего года. Нужно сезонное очищение от holidays.

Ошибка 5. Сравнивать модель и naive без CI. MAE модели 99, naive — 100 — статистически не различимы. Diebold-Mariano test.

Связанные темы

FAQ

Какой naive выбрать?

Last value для рядов без сезонности. Seasonal naive для дневных/недельных. Drift для трендов.

Когда naive обыгрывает ML?

Часто. Особенно на коротких рядах (< 200 точек) и при сильной сезонности.

Что считается «хорошим» MASE?

< 1 — модель лучше naive. 0.8–0.9 — хороший продакшен.

Naive в production?

Да, как fallback. Если ML-модель упала — naive отвечает.

Drift для коротких прогнозов?

Норм. Для длинных (> 30 точек) — слишком линейно.