Всем привет! Я Никита, продуктовый аналитик сервиса путешествий Туту. Я работаю в команде отелей — это сервис бронирования жилья, где особенно важно учитывать сезонность. Спрос на поездки меняется резко: в майские праздники и в августе происходит всплеск количества бронирований, в ноябре или марте — провалы. При этом точность прогноза для бизнеса критична: от нее зависят маркетинговые бюджеты, работа с партнёрами и планы по продажам.
В какой-то момент мы поняли, что наши прогнозы не соответствуют реальности. Старые линейные модели ловили только общий тренд и не справлялись с сезонностью.
Мы решили исправить ситуацию и нашли инструмент, который помогает строить точные прогнозы и не требует при этом глубоких знаний в математике временных рядов. Таким инструментом стал Prophet. В статье расскажу о том, почему мы выбрали именно его, что нужно для быстрого старта, какие доработки потребовались и какие выводы мы сделали за несколько месяцев использования.

Почему именно Prophet
Перед выбором инструмента мы определились с требованиями:
простота использования — не хотелось тратить недели на внедрение;
возможность быстро учесть сезонность и тренды;
гибкость через добавление регрессоров;
лёгкая автоматизация для запуска в продакшене.
Мы пробовали разные подходы. Классические модели вроде ARIMA и SARIMA оказались слишком капризными: они дают хорошие прогнозы, но требуют долгого подбора параметров и плохо масштабируются, когда рядов сотни или тысячи. Holt-Winters прост в использовании, но работает только на относительно стабильных паттернах и не справляется со сложной сезонностью. Современные библиотеки вроде Darts или Kats дают доступ к нейросетям и state-of-the-art методам, но они перегружены для нашей задачи: запускать их в продакшн дороже и сложнее, чем хотелось бы.
На этом фоне Prophet оказался оптимальным компромиссом: он прост в настройке, учитывает сезонность и праздники, быстро даёт результат и не требует глубоких знаний в статистике или ML.
Он закрыл большинство наших задач «из коробки» и позволил быстро построить MVP. Изначально проект задумывался как небольшой внутренний инструмент для аналитиков, но со временем перерос в полноценную систему генерации прогнозов для бизнеса с интеграцией в дашборды.
MVP: быстрый старт
Для начала разберемся, за что отвечают основные параметры в Prophet:
сhangepoint_prior_scale — отвечает за чувствительность модели к изменениям тренда. Чем выше значение, тем гибче модель реагирует на изменения, но при этом растёт риск переобучения. Малые значения делают модель более «гладкой», но она может пропускать важные изменения.
seasonality_prior_scale — регулирует силу сезонных колебаний. Большие значения позволяют модели лучше подстраиваться под ярко выраженные циклы, но могут привести к «шумной» подгонке.
holidays_prior_scale — контролирует, насколько сильно праздники будут влиять на прогноз. Если значение слишком маленькое, эффект праздников почти не будет учитываться.
n_changepoints — количество потенциальных точек излома тренда. Если данных много и тренд часто меняется, полезно увеличить.
changepoint_range — доля временного ряда, в пределах которого Prophet ищет точки изменения тренда. По умолчанию 0.8 — то есть 80% первых данных. Если важны недавние тренды, нужно увеличить параметр до 0.9–0.95.
Мы начали с максимально простого варианта:
from clickhouse_driver import Client
from prophet import Prophet
import pandas as pd
# Подключение к БД (пример)
client = Client(host="...", port=9000, user="...", password="...", database="...")
# Загружаем данные
sql = """
select date_trunc('day', date) as ds,
count(id) as y
from table
"""
data = client.query_dataframe(sql)
# Обучение модели
model = Prophet()
model.fit(data)
# Создаем будущие даты
future = pd.DataFrame({'ds': pd.date_range(start="2023-01-01", end="2023-12-31", freq='D')})
forecast = model.predict(future)
# Мы получили прогноз, который сразу же можно визуализировать:
fig1 = model.plot(forecast)
fig2 = model.plot_components(forecast)

В результате получили график прогноза с MAPE ~27%. На графике заметно, что «из коробки» Prophet справляется не всегда: он сглаживает пики высокого сезона и недооценивает реальный рост, а в низкий сезон наоборот держит прогноз выше фактического уровня. Отдельные резкие всплески тоже остаются вне предсказаний — для таких случаев нужны дополнительные фичи или настройка модели.
Такого результата явно недостаточно для продакшн-использования. Но уже на этом шаге мы посмотрели, как Prophet разложил ряд на тренд и сезонность. Мы сразу увидели долгосрочный рост спроса, недельный паттерн с пиком в середине недели и провалом в воскресенье, а также ярко выраженный летний сезон с пиками в июле–августе и спадом в начале года.

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

Исторические данные загружаются из ClickHouse, к ним добавляются регрессоры: например, информация о праздниках. Далее данные передаются в Prophet, который обучается и строит прогноз. Полученные результаты сохраняются и архивируются со специальным тегом — это позволяет вернуться к любой версии прогноза. Для регулярной работы у нас есть задачи, которые пересчитывают прогноз раз в месяц и ежедневно обновляют факты. Всем процессом управляет один центральный скрипт.
В процессе мы столкнулись с проблемой переобучения. В какой-то момент модель стала занижать прогнозы настолько, что они уходили в отрицательные значения. Для бизнеса это выглядело странно — аналитический инструмент выдаёт данные хуже случайной догадки.
Разбор показал, что главная причина — жёстко зафиксированные гиперпараметры. Они работали на исторических данных, но ломались при изменении структуры временного ряда. Нужно было решение, которое позволило бы модели адаптироваться к новым условиям.
Оптимизируем гиперпараметры
Чтобы избежать переобучения, мы подключили Optuna. Эта библиотека автоматически подбирает гиперпараметры модели, минимизируя ошибки.
Пример работы:
import optuna
def objective(trial):
cps = trial.suggest_float("changepoint_prior_scale", 0.001, 0.5, log=True)
sps = trial.suggest_float("seasonality_prior_scale", 0.01, 10.0)
model = Prophet(
changepoint_prior_scale=cps,
seasonality_prior_scale=sps,
holidays=holidays_df
)
model.fit(data)
forecast = model.predict(future)
return mean_absolute_percentage_error(data['y'], forecast['yhat'][:len(data)])
study = optuna.create_study(direction="minimize")
study.optimize(objective, n_trials=50)
С Optuna модель стала стабильнее, а прогнозы — ближе к реальности. В пайплайне появился еще один блок — оптимизация. Из-за него нам пришлось изменить структуру хранения данных и добавить таблицу для сохранения гиперпараметров: дата, метрика, параметры, функция потерь.
В итоге мы построили более продвинутый пайплайн для автоматизации прогнозирования. Исторические данные загружаются из ClickHouse, а затем обогащаются регрессорами: например, информацией о праздниках и других внешних факторах.
Далее запускается поиск оптимальных гиперпараметров с помощью Optuna. В качестве метрики используем MAPE или любую из возможных в скрипте, а качество моделей оцениваем через встроенную кросс-валидацию Prophet. Лучшие параметры автоматически сохраняются в отдельную таблицу, чтобы в дальнейшем их можно было использовать повторно.
После этого модель Prophet обучается на исторических данных и строит прогноз. Полученные результаты проходят через несколько шагов: сохраняются в хранилище, архивируются со специальным тегом (чтобы можно было вернуться к любой версии прогноза) и загружаются в итоговые витрины.
Новый пайплайн выглядит так:

Продакшн и автоматизация
После всех обновлений модель уже крутилась автоматически. Но для перевода в продакшн и реальной помощи бизнесу нам пришлось её ещё доработать.
Вот что мы добавили.
Хранение результатов прогнозов. Все прогнозы сохраняются в отдельной таблице ClickHouse. Для каждой итерации фиксируется прогноз, дата загрузки и служебный тег. Храним все версии без перезаписи. Это позволяет сравнивать прогнозы с фактами и возвращаться к любой версии.
Сохранение гиперпараметров. В отдельную таблицу записываются параметры обучения. Сохраняем функцию потерь, метрику качества и словарь гиперпараметров от Optuna. Это позволяет воспроизводить модель и отслеживать изменения качества при разных настройках.
Мониторинг качества. Сделали дашборд для анализа прогнозов в динамике. На нём отображаются ключевые метрики: например, MAPE и RMSE. Можно сравнивать итерации, отслеживать деградацию или улучшение модели.
Теперь система работает без ручного вмешательства и поддерживает rolling forecast, а бизнес с его помощью может планировать показатели на квартал или следующий год. При этом стартовой точкой был «голый» объект Prohpet с MAPE 27%, но доработки и использование более оптимальных параметров позволили нам приблизиться к MAPE в 6%. Удалось увеличить точность в ~3.5 раза.
Prophet подходит для аналитиков, которым нужен быстрый и понятный инструмент прогнозирования. Но в продакшне «из коробки» он быстро упирается в ограничения: жёсткие гиперпараметры, игнорирование особенностей бизнеса, переобучение.
Если добавить регрессоры и автоматическую оптимизацию через Optuna, то инструмент станет надежнее. При этом важно понимать, что даже самая простая модель требует адаптации и постоянного контроля.
Самый главный вывод — нужно не бояться ошибок. MVP с MAPE 27% и отрицательными прогнозами сначала показался нам провалом, но именно через такие эксперименты рождаются рабочие решения. Сегодня у нас есть система, которая ежедневно обновляет прогнозы, хранит их историю и помогает бизнесу принимать решения.
Если интересно посмотреть полный пайплайн и код — мы выложили его на GitHub.