Greykite — библиотека для прогнозирования временных рядов с открытым исходным кодом, разработанная командой LinkedIn и выпущенная в 2021 году. Основу составляет алгоритм Silverkite — быстрая аддитивная модель, построенная на ridge-регрессии с богатым набором фич: тренд, сезонность, праздники, взаимодействия между компонентами.
В отличие от большинства библиотек прогнозирования, Greykite дает полный контроль над структурой модели без необходимости работать с внутренностями алгоритма напрямую. Библиотека ориентирована на production-задачи: пайплайн включает бэктестинг, диагностику, визуализацию компонент и гибкую настройку через шаблоны. Это делает ее применимой как для быстрого прототипирования, так и для развертывания в аналитических системах.
Архитектура и ключевые компоненты
Greykite организована вокруг 3-х уровней абстракции:
- Верхний уровень — класс Forecaster с методом run_forecast_config(), который принимает датафрейм и конфигурацию, возвращает объект с прогнозом, метриками и диагностикой;
- Средний уровень — шаблоны (SimpleSilverkiteTemplate, SilverkiteTemplate, ProphetTemplate), которые транслируют конфигурацию в параметры модели;
- Нижний уровень — FlexibleModel, непосредственно реализующий алгоритм Silverkite.
Ключевые компоненты конфигурации:
- MetadataParam — описание данных: столбец даты, целевой столбец, частота временного ряда;
- ModelComponentsParam — компоненты модели: тренд, сезонность, праздники, регуляризация, кастомные фичи;
- EvaluationPeriodParam — параметры бэктестинга: размер тестовой выборки, количество фолдов, горизонт прогноза;
- ForecastConfig — верхнеуровневый объект, объединяющий все параметры и передаваемый в Forecaster.
Такая иерархия позволяет работать на любом уровне детализации: от однострочного запуска с пресетом до полностью кастомизированной модели с ручным заданием признаков.
Silverkite vs PROPHET-модель внутри Greykite
Greykite поддерживает два алгоритма:
- Silverkite (основной);
- Prophet через обертку ProphetTemplate.
Выбор алгоритма задается параметром model в ForecastConfig.
Silverkite строит прогноз через ridge-регрессию на матрице фич, сгенерированных из временного ряда. Это позволяет достичь высокой скорости: модель на дневных данных за несколько лет обучается за секунды.
Prophet использует байесовскую аддитивную модель на Stan — медленнее, но с неопределенностью прогноза из коробки. Использовать ProphetTemplate внутри Greykite имеет смысл, когда нужно сравнить алгоритмы в одном пайплайне с идентичными условиями бэктестинга — интерфейс и метрики унифицированы. Для продакшена Silverkite предпочтительнее: он быстрее, лучше поддается кастомизации и не требует компиляции Stan.
Установка и настройка Greykite
Библиотека Greykite распространяется через PyPI и устанавливается стандартным способом. Библиотека имеет нетривиальное дерево зависимостей: pandas, numpy, scikit-learn, plotly, LightGBM, pystan (опционально для Prophet). При установке в conda-окружении конфликты зависимостей минимальны; в базовом pip-окружении иногда требуется ручное разрешение версий.
Установка и зависимости
Базовая установка:
pip install greykite
Для работы с ProphetTemplate дополнительно:
pip install pystan==2.19.1.1
pip install prophet
Установка библиотек:
import greykite
from greykite.framework.templates.forecaster import Forecaster
from greykite.framework.templates.model_templates import ModelTemplateEnum
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam, ModelComponentsParam, EvaluationPeriodParam
)
Совместимость: Python 3.7–3.10, pandas 1.x–2.x. При использовании pandas 2.0+ возможны предупреждения об устаревших методах внутри библиотеки — на функциональность не влияют. Но при этом важно настроить правильно окружение.
В случае если вы устанавливаете Greykite в Google Collab, то возможны ошибки из-за несовместимости версий Python и Pandas. Тогда подход к установке другой — тут либо нужно искать старые версии Kernel, либо откатиться на текущем к старым версиям сначала и создать обертку для Kernel и в нее потом оборачивать код в ячейках.
# Google Collab - Установка Python 3.10 и greykite
!apt-get update -y
!apt-get install -y python3.10 python3.10-distutils python3.10-dev
!curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10
!python3.10 -m pip install --upgrade pip
!python3.10 -m pip install numpy==1.26.0 pandas==1.5.3 holidays==0.13 holidays-ext==0.0.8 greykite
# Google Collab - Создание функции-обертки для последующих ячеек с кодом
import subprocess
import textwrap
def gk(code: str):
"""
Выполняет Python код через Python 3.10 subprocess.
Всё, что выводится в stdout, возвращается в текущую ячейку.
"""
code = textwrap.dedent(code)
result = subprocess.run(
["python3.10", "-c", code],
capture_output=True,
text=True
)
print(result.stdout)
if result.stderr:
print(result.stderr)
# Google Collab - Импорт библиотек через функцию-обертки gk (greykite на python 3.10)
gk("""import greykite
from greykite.framework.templates.forecaster import Forecaster
from greykite.framework.templates.model_templates import ModelTemplateEnum
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam, ModelComponentsParam, EvaluationPeriodParam
)
print('All libraries are imported!')
""")
All libraries are imported!
В дальнейшем все ячейки кода, представленные ниже для Collab придется оборачивать в синтаксис gk(«»» … «»»). К счастью с локальной Conda таких «танцев с бубном» делать не приходится.
Быстрый старт: минимальный рабочий пример
Минимальный пайплайн в библиотеке Greykite требует наличие датафрейма с двумя столбцами: дата и целевая переменная. Ниже пример на синтетических данных с недельной сезонностью:
import pandas as pd
import numpy as np
from greykite.framework.templates.forecaster import Forecaster
from greykite.framework.templates.model_templates import ModelTemplateEnum
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam
)
np.random.seed(42)
dates = pd.date_range(start="2022-01-01", periods=365, freq="D")
values = (
10
+ 0.02 * np.arange(365)
+ 3 * np.sin(2 * np.pi * np.arange(365) / 7)
+ np.random.normal(0, 0.5, 365)
)
df = pd.DataFrame({"date": dates, "value": values})
config = ForecastConfig(
model_template=ModelTemplateEnum.SILVERKITE.name,
forecast_horizon=30,
coverage=0.95,
metadata_param=MetadataParam(
time_col="date",
value_col="value",
freq="D"
)
)
forecaster = Forecaster()
result = forecaster.run_forecast_config(df=df, config=config)
forecast_df = result.forecast.df
time_col = forecast_df.columns[0]
cols = [time_col, "forecast"]
if "forecast_lower" in forecast_df.columns:
cols += ["forecast_lower", "forecast_upper"]
print(forecast_df[cols].tail(30))
Fitting 3 folds for each of 1 candidates, totalling 3 fits
ts forecast forecast_lower forecast_upper
365 2023-01-01 20.023034 18.738988 21.307079
366 2023-01-02 20.093147 18.570198 21.616096
367 2023-01-03 19.023206 17.546314 20.500097
368 2023-01-04 16.280607 15.177988 17.383225
369 2023-01-05 14.456036 13.426570 15.485502
370 2023-01-06 15.007097 13.795495 16.218698
371 2023-01-07 17.554038 16.703881 18.404194
372 2023-01-08 19.813449 18.865975 20.760924
373 2023-01-09 20.393763 19.283575 21.503950
374 2023-01-10 18.590435 17.505837 19.675033
375 2023-01-11 16.091606 14.993472 17.189739
376 2023-01-12 14.270478 13.236200 15.304755
377 2023-01-13 14.811891 13.583581 16.040201
378 2023-01-14 17.440300 16.579276 18.301324
379 2023-01-15 19.720877 18.757398 20.684356
380 2023-01-16 20.427656 19.301021 21.554292
381 2023-01-17 18.708125 17.619039 19.797211
382 2023-01-18 16.300514 15.201013 17.400014
383 2023-01-19 14.532079 13.506888 15.557269
384 2023-01-20 14.936239 13.361313 16.511164
385 2023-01-21 17.840243 16.735199 18.945286
386 2023-01-22 20.157648 18.920376 21.394919
387 2023-01-23 20.921299 19.462650 22.379948
388 2023-01-24 18.540246 17.094174 19.986317
389 2023-01-25 16.065397 14.627023 17.503772
390 2023-01-26 14.495541 13.175255 15.815826
391 2023-01-27 15.565867 14.332006 16.799729
392 2023-01-28 18.269831 17.406515 19.133147
393 2023-01-29 20.536058 19.582596 21.489520
394 2023-01-30 21.141656 20.024892 22.258421
Объект result содержит: forecast (датафрейм с прогнозом и доверительными интервалами), backtest (результаты backtesting), model (обученная модель). Этот минимальный пример уже включает автоматическое определение сезонности и тренда — Silverkite подбирает компоненты из пресета SILVERKITE по умолчанию.
Ключевые классы и методы
Greykite предоставляет иерархию классов, где каждый уровень добавляет контроль за счет усложнения конфигурации. Понимание этой иерархии позволяет выбирать нужный уровень абстракции под конкретную задачу: быстрый запуск через пресеты или детальная настройка каждого компонента.
Обзор классов и методов
| Класс / метод | Модуль | Назначение | Ключевые параметры |
|---|---|---|---|
| Forecaster | framework.templates.forecaster | Верхнеуровневый запуск пайплайна | — |
| run_forecast_config() | Forecaster | Запуск прогноза по конфигурации | df, config |
| ForecastConfig | framework.templates.autogen.forecast_config | Верхнеуровневая конфигурация | model_template, forecast_horizon, metadata_param, model_components_param, evaluation_period_param |
| MetadataParam | framework.templates.autogen.forecast_config | Описание структуры датафрейма | time_col, value_col, freq, train_end_date |
| ModelComponentsParam | framework.templates.autogen.forecast_config | Настройка компонент модели | seasonality, growth, events, regressors, custom |
| EvaluationPeriodParam | framework.templates.autogen.forecast_config | Параметры бэктестинга | test_horizon, periods_between_train_test, cv_max_splits, cv_min_train_periods |
| SimpleSilverkiteTemplate | framework.templates.simple_silverkite_template | Упрощенный шаблон с пресетами | SimpleSilverkiteTemplateOptions |
| SilverkiteTemplate | framework.templates.silverkite_template | Полный контроль над Silverkite | ModelComponentsParam (расширенный) |
| FlexibleModel | sklearn.estimator.silverkite_estimator | sklearn-совместимый estimator | fit_algorithm, feature_sets_enabled, extra_pred_cols |
| SilverkiteEstimator | sklearn.estimator.silverkite_estimator | Обертка Silverkite для sklearn API | time_properties, origin_for_time_vars, fs_components_df |
| ProphetTemplate | framework.templates.prophet_template | Обертка Prophet в пайплайне Greykite | ModelComponentsParam (Prophet-параметры) |
Forecaster и SimpleSilverkiteTemplate
Forecaster — единственная точка входа для запуска полного пайплайна. Метод run_forecast_config() принимает датафрейм и ForecastConfig, внутри оркестрирует: выбор шаблона, генерацию фич, обучение модели, проведение бэктестинга, построение финального прогноза.
Метод SimpleSilverkiteTemplate работает через пресеты SimpleSilverkiteTemplateOptions, которые задают частоту данных и уровень детализации модели:
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam
)
from greykite.framework.templates.simple_silverkite_template_config import (
SILVERKITE_DAILY_90
)
config = ForecastConfig(
model_template=SILVERKITE_DAILY_90,
forecast_horizon=30,
metadata_param=MetadataParam(
time_col="date",
value_col="value",
freq="D"
)
)
Доступные пресеты охватывают комбинации частот (hourly, daily, weekly) и горизонтов. SILVERKITE_DAILY_90 оптимален для дневных бизнес-метрик с горизонтом до квартала: включает дневную и недельную сезонность, праздники США, линейный тренд с changepoints.
FlexibleModel и кастомизация компонент
FlexibleModel — sklearn-совместимый estimator, дающий прямой доступ к механизму генерации фич Silverkite. Используется, когда пайплайн Forecaster избыточен: например, при интеграции в собственный sklearn Pipeline или при необходимости передать модель в GridSearchCV.
from greykite.sklearn.estimator.silverkite_estimator import SilverkiteEstimator
import pandas as pd
fs_components_df = pd.DataFrame({
"name": ["tow", "toy"],
"period": [7.0, 365.25],
"order": [3, 5],
"seas_names": ["weekly", "yearly"]
})
estimator = SilverkiteEstimator(
fit_algorithm_dict={
"fit_algorithm": "ridge",
"fit_algorithm_params": {"alpha": 0.1}
},
fs_components_df=fs_components_df,
extra_pred_cols=["ct1"]
)
print(estimator.fit_algorithm_dict)
print(estimator.extra_pred_cols)
print(estimator.fs_components_df)
{'fit_algorithm': 'ridge', 'fit_algorithm_params': {'alpha': 0.1}}
['ct1']
name period order seas_names
0 tow 7.00 3 weekly
1 toy 365.25 5 yearly
fs_components_df — ключевой параметр: задает компоненты Фурье-разложения для каждой сезонности. Столбец order контролирует количество гармоник: выше значение — сложнее форма сезонности, выше риск переобучения. Для большинства бизнес-метрик order=3–5 достаточно.
Параметры сезонности и их влияние
Сезонность в Silverkite моделируется через Фурье-разложение. Каждый сезонный компонент описывается тремя параметрами:
- period — период сезонности в единицах временного ряда (7.0 для недельной сезонности дневного ряда);
- order — количество пар sin/cos гармоник; определяет сложность формы сезонного паттерна;
- seas_names — имя компонента для интерпретации и диагностики.
Через ModelComponentsParam сезонность задается так:
model_components = ModelComponentsParam(
seasonality={
"fs_components_df": pd.DataFrame({
"name": ["tow", "toy"],
"period": [7.0, 365.25],
"order": [3, 5],
"seas_names": ["weekly", "yearly"]
})
}
)
Увеличение order с 3 до 8 для годовой сезонности улучшает качество на данных с нерегулярными пиками (например, e-commerce с несколькими пиковыми сезонами), но при коротких рядах (менее 2 полных циклов) приводит к переобучению. Практическое правило: order ≤ period/2, при этом для дневных данных weekly order=3–4, yearly order=5–8.
Обработка праздников и событий: Holiday и EventConfig
Библиотека Greykite содержит встроенные словари праздников для десятков стран через модуль greykite.common.features.holiday. Праздники добавляются как бинарные фичи с опциональным окном до и после события — это позволяет захватить эффект предпраздничного и послепраздничного поведения.
from greykite.framework.templates.autogen.forecast_config import ModelComponentsParam
from greykite.algo.forecast.silverkite.constants.silverkite_holiday import SilverkiteHoliday
model_components = ModelComponentsParam(
events={
"holidays_to_model_separately": SilverkiteHoliday.ALL_HOLIDAYS_IN_COUNTRIES,
"holiday_lookup_countries": ["US", "RU"],
"holiday_pre_num_days": 2,
"holiday_post_num_days": 2,
"holiday_pre_post_num_dict": {
"Christmas Day": {"pre_num": 5, "post_num": 3}
}
}
)
print(model_components.events)
{'holidays_to_model_separately': 'ALL_HOLIDAYS_IN_COUNTRIES', 'holiday_lookup_countries': ['US', 'RU'], 'holiday_pre_num_days': 2, 'holiday_post_num_days': 2, 'holiday_pre_post_num_dict': {'Christmas Day': {'pre_num': 5, 'post_num': 3}}}
Метод holiday_pre_post_num_dict позволяет задать индивидуальные окна для конкретных праздников. Это важно для метрик с асимметричным эффектом: например, трафик начинает падать за 5 дней до Нового года, но восстанавливается быстро. Кастомные события (акции, релизы продуктов) добавляются аналогично через параметр daily_event_df_dict.
Параметры регуляризации и переобучение
Silverkite использует ridge-регрессию как базовый fit-алгоритм, что обеспечивает встроенную L2-регуляризацию. Параметр alpha в fit_algorithm_params контролирует силу регуляризации: при alpha=0 модель вырождается в OLS, при высоких значениях — сглаживает коэффициенты к нулю.
from greykite.framework.templates.autogen.forecast_config import ModelComponentsParam
model_components = ModelComponentsParam(
custom={
"fit_algorithm_dict": {
"fit_algorithm": "ridge",
"fit_algorithm_params": {"alpha": 1.0}
},
"feature_sets_enabled": True,
"max_lag_order": 7
}
)
print(model_components.custom)
{'fit_algorithm_dict': {'fit_algorithm': 'ridge', 'fit_algorithm_params': {'alpha': 1.0}}, 'feature_sets_enabled': True, 'max_lag_order': 7}
Помимо ridge, доступны:
- lasso (L1, автоматический отбор фич),
- elastic_net (комбинация L1+L2),
- gradient_boosting (LightGBM).
LightGBM актуален для рядов с нелинейными взаимодействиями и большим количеством регрессоров, но требует больше данных и теряет интерпретируемость компонент. Метод max_lag_order добавляет авторегрессионные фичи — полезно для рядов с сильной автокорреляцией остатков.
Практические примеры
Примеры ниже построены на реальных сценариях применения: бизнес-метрики с сезонностью, аномалиями и необходимостью оценки качества модели через бэктестинг. Все примеры используют единый датафрейм с дневными данными.
Базовый пайплайн прогнозирования
Полный рабочий пайплайн с явной конфигурацией всех основных компонентов:
import pandas as pd
import numpy as np
import yfinance as yf
from greykite.framework.templates.forecaster import Forecaster
from greykite.framework.templates.model_templates import ModelTemplateEnum
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam, ModelComponentsParam, EvaluationPeriodParam
)
raw = yf.download("GC=F", start="2024-03-15", end="2026-03-15", auto_adjust=False)
if isinstance(raw.columns, pd.MultiIndex):
raw.columns = raw.columns.droplevel(1)
df = raw[["Close"]].reset_index()
df.columns = ["date", "value"]
df = df.dropna()
config = ForecastConfig(
model_template=ModelTemplateEnum.SILVERKITE.name,
forecast_horizon=60,
coverage=0.95,
metadata_param=MetadataParam(
time_col="date",
value_col="value",
freq="B"
),
model_components_param=ModelComponentsParam(
seasonality={
"weekly_seasonality": True,
"yearly_seasonality": True,
"daily_seasonality": False
},
growth={"growth_term": "linear"},
custom={
"fit_algorithm_dict": {
"fit_algorithm": "ridge",
"fit_algorithm_params": {"alphas": [0.1, 0.5, 1.0, 5.0]}
}
}
),
evaluation_period_param=EvaluationPeriodParam(
test_horizon=60,
cv_max_splits=3
)
)
forecaster = Forecaster()
result = forecaster.run_forecast_config(df=df, config=config)
forecast_df = result.forecast.df
time_col = forecast_df.columns[0]
cols = [time_col, "forecast"]
if "forecast_lower" in forecast_df.columns:
cols += ["forecast_lower", "forecast_upper"]
print(forecast_df[cols].tail(10))
print()
metrics = result.backtest.test_evaluation
metrics_df = pd.DataFrame.from_dict(metrics, orient="index", columns=["value"])
metrics_df.index.name = "metric"
metrics_df = metrics_df.dropna()
metrics_df["value"] = metrics_df["value"].round(4)
print(metrics_df.to_string())
Fitting 3 folds for each of 1 candidates, totalling 3 fits
ts forecast forecast_lower forecast_upper
571 2026-05-25 5639.802733 5428.397697 5851.207770
572 2026-05-26 5801.730005 5639.637975 5963.822034
573 2026-05-27 5769.728471 5588.202641 5951.254301
574 2026-05-28 5779.971361 5604.573362 5955.369361
575 2026-05-29 5719.376305 5556.220341 5882.532269
576 2026-06-01 5652.507480 5446.601979 5858.412981
577 2026-06-02 5808.266952 5650.315223 5966.218680
578 2026-06-03 5805.647844 5627.454178 5983.841511
579 2026-06-04 5805.060198 5630.116390 5980.004007
580 2026-06-05 5752.017052 5589.280764 5914.753341
value
metric
CORR 0.8597
R2 0.1949
MSE 72088.2887
RMSE 268.4926
MAE 220.8951
MedAE 202.4796
MAPE 4.4383
MedAPE 4.1831
sMAPE 2.2921
Q80 176.2381
Q95 209.1333
Q99 217.9054
OutsideTolerance1p 0.9286
OutsideTolerance2p 0.8393
OutsideTolerance3p 0.6429
OutsideTolerance4p 0.5536
OutsideTolerance5p 0.3214
Prediction Band Width (%) 5.1945
Prediction Band Coverage (fraction) 0.3393
Coverage: Lower Band 0.0357
Coverage: Upper Band 0.3036
Coverage Diff: Actual_Coverage - Intended_Coverage -0.6107
MIS 4684.3228
Пайплайн загружает котировки фьючерса на золото, формирует конфигурацию с недельной и годовой сезонностью в единицах бизнес-дней, запускает прогноз на 60 дней вперед с 3-фолдовым бэктестингом. Переменная result.backtest.test_evaluation содержит метрики по каждому фолду: MAPE, RMSE, покрытие доверительного интервала.
Интерпретация полученных данных кратко следующая:
- Модель показывает умеренное качество точечного прогноза: MAPE=4.4% и CORR=0.86 говорят о том, что направление движения цены модель улавливает, но R²=0.19 указывает на слабое объяснение дисперсии — фактически модель лишь немного лучше наивного прогноза средним. RMSE=268 при ценах золота в районе 5600–5800 — это ошибка около 4.7% от уровня;
- Главная проблема — доверительные интервалы. Coverage=0.34 при заданном 0.95 означает, что реальные значения попадают в интервал лишь в 34% случаев вместо 95%. Это типичная картина для финансовых рядов с гетероскедастичностью: Silverkite строит интервалы на основе остатков обучающей выборки, не учитывая кластеризацию волатильности. Для золота на горизонте 60 дней узкий интервал (Band Width=5.2%) — заведомо оптимистичная оценка неопределенности, использовать его для риск-менеджмента не стоит.
Учет праздников и аномалий
Аномалии (выбросы, периоды с аномальным поведением ряда) снижают качество обучения, если не исключить их явно. Greykite поддерживает маскировку аномальных периодов через AnomalyParam:
import pandas as pd
import numpy as np
from greykite.framework.templates.forecaster import Forecaster
from greykite.framework.templates.model_templates import ModelTemplateEnum
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam, ModelComponentsParam
)
forecaster = Forecaster()
np.random.seed(0)
dates = pd.date_range("2021-01-01", periods=730, freq="D")
values = 100 + np.sin(2 * np.pi * np.arange(730) / 365) * 10 + np.random.normal(0, 2, 730)
values[180:210] += 50
df_anom = pd.DataFrame({"date": dates, "value": values})
anomaly_df = pd.DataFrame({
"start_time": ["2021-07-01"],
"end_time": ["2021-07-31"],
"impact": [None]
})
config_anom = ForecastConfig(
model_template=ModelTemplateEnum.SILVERKITE.name,
forecast_horizon=30,
coverage=0.95,
metadata_param=MetadataParam(
time_col="date",
value_col="value",
freq="D",
anomaly_info={
"value_col": "value",
"anomaly_df": anomaly_df,
"adjustment_delta_col": None
}
),
model_components_param=ModelComponentsParam(
events={
"holiday_lookup_countries": ["US"],
"holiday_pre_num_days": 1,
"holiday_post_num_days": 1
}
)
)
result_anom = forecaster.run_forecast_config(df=df_anom, config=config_anom)
forecast_df_anom = result_anom.forecast.df
time_col = forecast_df_anom.columns[0]
cols = [time_col, "forecast"]
if "forecast_lower" in forecast_df_anom.columns:
cols += ["forecast_lower", "forecast_upper"]
print(forecast_df_anom[cols].tail(10))
Fitting 3 folds for each of 1 candidates, totalling 3 fits
ts forecast forecast_lower forecast_upper
750 2023-01-21 98.314588 87.635350 108.993826
751 2023-01-22 98.807028 89.044297 108.569758
752 2023-01-23 99.209329 88.731770 109.686888
753 2023-01-24 99.529496 89.689293 109.369699
754 2023-01-25 99.622384 86.923972 112.320796
755 2023-01-26 99.097517 87.111011 111.084023
756 2023-01-27 99.035790 88.191912 109.879668
757 2023-01-28 99.033954 88.345302 109.722606
758 2023-01-29 99.434466 89.661600 109.207331
759 2023-01-30 99.663221 89.180127 110.146315
AnomalyParam принимает датафрейм с периодами аномалий. При impact=None период полностью исключается из обучающей выборки — модель не видит искаженные данные. Альтернативно, impact можно задать как числовой сдвиг для корректировки значений без исключения.
Кастомизация компонент через ModelComponentsParam
Добавление внешних регрессоров расширяет модель за пределы временных паттернов. Регрессоры передаются как дополнительные столбцы датафрейма:
import pandas as pd
import numpy as np
from greykite.framework.templates.forecaster import Forecaster
from greykite.framework.templates.model_templates import ModelTemplateEnum
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam, ModelComponentsParam
)
forecaster = Forecaster()
np.random.seed(42)
dates = pd.date_range(start="2022-01-01", periods=365, freq="D")
values = (
10
+ 0.02 * np.arange(365)
+ 3 * np.sin(2 * np.pi * np.arange(365) / 7)
+ np.random.normal(0, 0.5, 365)
)
df = pd.DataFrame({"date": dates, "value": values})
df_reg = df.copy()
df_reg["lag_7"] = df_reg["value"].shift(7)
df_reg["lag_30"] = df_reg["value"].shift(30)
df_reg = df_reg.dropna()
config_reg = ForecastConfig(
model_template=ModelTemplateEnum.SILVERKITE.name,
forecast_horizon=30,
coverage=0.95,
metadata_param=MetadataParam(
time_col="date",
value_col="value",
freq="D"
),
model_components_param=ModelComponentsParam(
regressors={
"regressor_cols": ["lag_7", "lag_30"]
},
custom={
"fit_algorithm_dict": {
"fit_algorithm": "lasso",
"fit_algorithm_params": {"alphas": [0.01, 0.1, 1.0]}
}
}
)
)
result_reg = forecaster.run_forecast_config(df=df_reg, config=config_reg)
forecast_df_reg = result_reg.forecast.df
time_col = forecast_df_reg.columns[0]
cols = [time_col, "forecast"]
if "forecast_lower" in forecast_df_reg.columns:
cols += ["forecast_lower", "forecast_upper"]
print(forecast_df_reg[cols].tail(10))
Fitting 3 folds for each of 1 candidates, totalling 3 fits
Lasso здесь предпочтителен: при большом количестве лаговых регрессоров он обнуляет незначимые коэффициенты, автоматически отбирая информативные лаги. extra_pred_cols поддерживает синтаксис взаимодействий через двоеточие — это позволяет задавать условные эффекты без ручного создания фич.
Бэктестинг и валидация на rolling window
Метод EvaluationPeriodParam контролирует схему бэктестинга. В библиотеке Greykite реализовано расширяющееся окно (expanding window) по умолчанию, хотя через параметры можно приблизиться к rolling window:
import pandas as pd
import numpy as np
from greykite.framework.templates.forecaster import Forecaster
from greykite.framework.templates.model_templates import ModelTemplateEnum
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam, EvaluationPeriodParam
)
forecaster = Forecaster()
np.random.seed(42)
dates = pd.date_range(start="2022-01-01", periods=365, freq="D")
values = (
10
+ 0.02 * np.arange(365)
+ 3 * np.sin(2 * np.pi * np.arange(365) / 7)
+ np.random.normal(0, 0.5, 365)
)
df = pd.DataFrame({"date": dates, "value": values})
config_bt = ForecastConfig(
model_template=ModelTemplateEnum.SILVERKITE.name,
forecast_horizon=30,
coverage=0.95,
metadata_param=MetadataParam(
time_col="date",
value_col="value",
freq="D"
),
evaluation_period_param=EvaluationPeriodParam(
test_horizon=30,
periods_between_train_test=0,
cv_max_splits=5,
cv_min_train_periods=180,
cv_expanding_window=True,
cv_horizon=30
)
)
result_bt = forecaster.run_forecast_config(df=df, config=config_bt)
cv_results = result_bt.grid_search.cv_results_
cv_df = pd.DataFrame(cv_results)
metric_cols = [c for c in cv_df.columns if "MAPE" in c or "RMSE" in c]
print(cv_df[metric_cols])
Fitting 5 folds for each of 1 candidates, totalling 5 fits
split0_test_RMSE split1_test_RMSE ... mean_train_sMAPE std_train_sMAPE
0 0.638277 0.674613 ... 1.37745 0.049042
[1 rows x 45 columns]
cv_expanding_window=False переключает на rolling window с фиксированным размером обучающей выборки — актуально для рядов с концептуальным дрейфом, где ранние данные снижают качество. cv_min_train_periods защищает от фолдов с недостаточным объемом данных для обучения.
Визуализация прогноза и компонент модели
Greykite предоставляет встроенные plotly-визуализации через объект result:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from greykite.framework.templates.forecaster import Forecaster
from greykite.framework.templates.model_templates import ModelTemplateEnum
from greykite.framework.templates.autogen.forecast_config import (
ForecastConfig, MetadataParam
)
np.random.seed(42)
dates = pd.date_range(start="2022-01-01", periods=365, freq="D")
values = (
10
+ 0.02 * np.arange(365)
+ 3 * np.sin(2 * np.pi * np.arange(365) / 7)
+ np.random.normal(0, 0.5, 365)
)
df = pd.DataFrame({"date": dates, "value": values})
config = ForecastConfig(
model_template=ModelTemplateEnum.SILVERKITE.name,
forecast_horizon=30,
coverage=0.95,
metadata_param=MetadataParam(
time_col="date",
value_col="value",
freq="D"
)
)
forecaster = Forecaster()
result = forecaster.run_forecast_config(df=df, config=config)
forecast_df = result.forecast.df.copy()
time_col = forecast_df.columns[0]
forecast_df[time_col] = pd.to_datetime(forecast_df[time_col])
train_end = df["date"].max()
hist = forecast_df[forecast_df[time_col] <= train_end]
pred = forecast_df[forecast_df[time_col] > train_end]
fig, axes = plt.subplots(2, 1, figsize=(14, 8), facecolor="white")
ax1 = axes[0]
ax1.plot(hist[time_col], hist["actual"], color="#1a1a1a", linewidth=1.2, label="Факт")
ax1.plot(pred[time_col], pred["forecast"], color="#2563eb", linewidth=1.5,
linestyle="--", label="Прогноз")
if "forecast_lower" in pred.columns:
ax1.fill_between(pred[time_col], pred["forecast_lower"], pred["forecast_upper"],
alpha=0.15, color="#2563eb", label="95% интервал")
ax1.axvline(train_end, color="#6b7280", linewidth=1, linestyle=":")
ax1.set_title("Прогноз Greykite (Silverkite)", fontsize=13, pad=10)
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3)
ax1.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m"))
ax2 = axes[1]
bt_dict = result.backtest.test_evaluation
if bt_dict is not None:
bt_series = pd.Series(bt_dict)
metrics = ["MAPE", "RMSE"]
metrics = [m for m in metrics if m in bt_series.index]
ax2.bar(range(len(metrics)),
[bt_series[m] for m in metrics],
color=["#1a1a1a", "#6b7280"])
ax2.set_xticks(range(len(metrics)))
ax2.set_xticklabels(metrics)
ax2.set_title("Метрики backtesting", fontsize=13, pad=10)
ax2.grid(True, alpha=0.3, axis="y")
plt.tight_layout()
plt.savefig("greykite_forecast.png", dpi=150, bbox_inches="tight")
plt.show()

Рис. 1: Прогноз Greykite на дневных данных. Верхняя панель: исторический ряд (черный) и прогноз на 60 дней вперед (синий пунктир) с 95% доверительным интервалом. Вертикальная пунктирная линия — граница обучающей и тестовой выборки. Нижняя панель: агрегированные метрики бэктестинга. Ширина интервала прогноза — индикатор неопределенности модели; резкое расширение на горизонте более 30 дней сигнализирует о слабой предсказуемости ряда
Работа с библиотекой: частые ошибки и лучшие практики
Большинство проблем при работе с Greykite возникает на этапе конфигурации и подготовки данных. Ошибки конфигурации чаще всего проявляются не как исключения Python, а как деградация качества прогноза — их сложнее отловить без диагностики.
Типичные ошибки
- Неверная частота ряда. Параметр freq в MetadataParam должен точно соответствовать фактической частоте данных. Пропуски в ряду (выходные для дневных данных) требуют freq=»B» вместо «D». При несоответствии Silverkite генерирует фичи с неверными периодами сезонности, что незаметно деградирует качество;
- Утечка данных через регрессоры. При добавлении внешних регрессоров они должны быть доступны на горизонте прогноза. Лаговые регрессоры (lag_7, lag_30) безопасны только если lag ≥ forecast_horizon. Регрессоры с lag < forecast_horizon создают риск утечки данных из будущего (look-ahead bias): в результате на бэктестах метрики выглядят хорошо, а в продакшене модель показывает себя из рук вон плохо;
- Переобучение при высоком порядке (order) сезонности. order=10+ для годовой сезонности на ряду менее 2 лет гарантированно приводит к переобучению. Симптом: низкий RMSE на train, высокий на test в backtesting. Решение: cv_max_splits≥3 и контроль разницы train/test метрик;
- Игнорирование линий сломов (changepoints) тренда. По умолчанию Silverkite использует линейный тренд без изломов. Для рядов со структурными сдвигами (кризисы, редизайн продукта) нужно явно задать changepoints. Если нет желания заморачиваться, то method=»auto» автоматически определяет точки излома через регуляризованную регрессию. regularization_strength контролирует чувствительность: 0.0 — максимум точек, 1.0 — минимум.
Лучшие практики
- Всегда запускать backtesting с cv_max_splits≥3 перед деплойментом в продакшен, поскольку одиночный train/test сплит дает нестабильные оценки качества;
- Для бизнес-метрик с выраженной недельной сезонностью использовать freq=»D» с tow-компонентой, а не агрегировать до недельных данных — теряется информация о внутринедельных паттернах;
- При добавлении праздников для нескольких стран проверять пересечения дат: совпадающие праздники создают дублирующие фичи и раздувают матрицу регрессии;
- Использовать result.model[-1].named_steps[«estimator»].model_dict для доступа к коэффициентам модели — это основной инструмент диагностики того, какие компоненты реально влияют на прогноз;
- Для рядов с мультипликативной сезонностью (амплитуда сезонности растет с уровнем ряда) логарифмировать таргет перед подачей в модель — Silverkite аддитивен по природе.
Диагностика через коэффициенты модели — недооцененный инструмент. Если праздничные фичи имеют незначимые коэффициенты, их включение только усложняет модель без прироста качества. Ridge не обнуляет такие коэффициенты автоматически — это задача аналитика.
Заключение
Библиотека Greykite несомненно интересна. Она, по сути, закрывает нишу между «слишком простым» и «слишком сложным»: Prophet не дает достаточного контроля над структурой модели, а нейросетевые подходы требуют больших данных и теряют интерпретируемость.
Ядро библиотеки: Silverkite предоставляет прозрачную аддитивную модель с явными компонентами — тренд, сезонность, праздники, регрессоры — каждый из которых можно исследовать через коэффициенты.
Практическая ценность библиотеки раскрывается в понятности ее поведения в продакшене и, разумеется, универсальности: есть встроенный модуль бэктестинга, есть детектирование аномалий, есть гибкая настройка changepoints и поддержка внешних регрессоров. Все они формируют полный аналитический пайплайн без необходимости собирать его из разрозненных инструментов. Для задач прогнозирования бизнес-метрик с выраженной сезонностью и внешними событиями Greykite — один из наиболее зрелых инструментов в экосистеме Python.