Промышленные записки

Прогнозирование с использованием моделей машинного обучения

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

Автор Nixtla Team.

TL; DR: мы представляем mlforecast, фреймворк с открытым исходным кодом от Nixtla, который позволяет быстро и легко использовать модели машинного обучения в задачах прогнозирования временных рядов. Это позволяет вам сосредоточиться на модели и функциях, а не на деталях реализации. С mlforecast вы можете проводить эксперименты более простым способом, и он имеет встроенную функцию тестирования на истории, которая поможет вам найти наиболее эффективную модель.

Вы можете использовать mlforecast в своей инфраструктуре или воспользоваться нашим полностью размещенным решением. Просто отправьте нам письмо по адресу [email protected] для тестирования частной бета-версии.

Хотя этот пример содержит только один временной ряд, структура способна обрабатывать сотни тысяч из них и очень эффективна как по времени, так и по памяти.

Вступление

Мы в Nixtla стараемся сделать прогнозирование временных рядов более доступным для всех. В этом посте мы поговорим об использовании моделей машинного обучения для прогнозирования задач. Мы рассмотрим основные проблемы на примере, а затем представим mlforecast - фреймворк, который упрощает использование моделей машинного обучения в прогнозировании. mlforecast занимается разработкой функций и заботится об обновлениях за вас, пользователю нужно только предоставить регрессор, который следует за scikit-learn API (реализует соответствие и прогнозировать), и указать функции, которые он хочет использовать. . Эти функции могут быть лагами, преобразованиями на основе лагов и функциями даты. (Для дальнейшего создания функции или автоматизированного конвейера прогнозирования проверьте nixtla.)

Мотивация

В течение многих лет в области прогнозирования доминировали классические методы, такие как ARIMA и ETS. Одна из причин заключалась в том, что в большинстве случаев использовалось прогнозирование низкочастотных рядов с ежемесячной, квартальной или годовой детализацией. Кроме того, было не так много наборов данных временных рядов, поэтому подобрать одну модель для каждого из них и получить из них прогнозы было несложно.

Однако в последние годы возросла потребность в прогнозировании более крупных наборов данных с более высокой частотой. Более крупные и высокочастотные временные ряды создают проблему для классических методов прогнозирования. Эти методы не предназначены для моделирования множества временных рядов вместе, и их реализация неоптимальна и медленная (вам нужно обучить много моделей), и, кроме того, между рядами могут быть некоторые общие или общие шаблоны, которые можно изучить, моделируя их вместе. .

Чтобы решить эту проблему, были предприняты различные попытки предложить разные методы, которые могут обучать одну модель на многих временных рядах. Были разработаны интересные архитектуры глубокого обучения, которые могут точно прогнозировать многие временные ряды, такие как ESRNN, DeepAR, NBEATS и другие. (Отметьте nixtlats и Репликация результатов ESRNN для нашего WIP.)

Традиционные модели машинного обучения, такие как деревья с градиентным усилением, также использовались и показали, что они также могут достигать очень хорошей производительности. Однако использовать эти модели с функциями, основанными на задержке, не так просто, потому что вам нужно обновлять свои функции на каждом временном шаге, чтобы вычислять прогнозы. Кроме того, в зависимости от вашего горизонта прогнозирования и лагов, которые вы используете, в какой-то момент у вас заканчиваются реальные значения вашего ряда для обновления ваших характеристик, поэтому вам нужно что-то делать, чтобы заполнить эти пробелы. Один из возможных подходов - использовать ваши прогнозы в качестве значений для ряда и обновлять ваши функции с их помощью. Именно это делает для вас mlforecast.

Пример

В следующем разделе мы покажем очень простой пример с одной серией, чтобы подчеркнуть трудности использования моделей машинного обучения в задачах прогнозирования. Позже это будет мотивировать использовать mlforecast, библиотеку, которая упрощает и ускоряет весь процесс.

Библиотеки

Данные

Наши данные имеют ежедневную сезонность, и, как вы можете видеть в создании, это просто день недели + униформа ({- 1, 0, 1}).

Обучение

Допустим, нам нужны прогнозы на следующие 14 дней. Первым шагом будет решение, какую модель и функции использовать, поэтому мы создадим набор для проверки, содержащий данные за последние 14 дней.

В качестве отправной точки мы попробуем лаг 7 и лаг 14.

Мы можем видеть ожидаемую связь между лагами и целью. Например, когда lag-7 равно 2, y может быть 0, 1, 2, 3 или 4. Это потому, что каждый день недели может иметь значения [день - 1, день, день + 1], поэтому, когда мы находимся в дне недели номер 2, мы можем получить значения 1, 2 или 3. Однако значение 2 может поступать из дня недели 1, для которого минимум 0, и он может приходить с дня недели 3, максимум которого равен 4.

При вычислении значений задержки в некоторых строках остаются пустые значения.

Мы откажемся от них перед тренировкой.

Для простоты мы будем обучать линейную регрессию без перехвата. Поскольку лучшая модель будет брать среднее значение для каждого дня недели, мы ожидаем получить коэффициенты, близкие к 0,5.

Эта модель берет 0,51 * lag_7 + 0,45 * lag_14.

Прогнозирование

Большой. У нас есть обученная модель. Как мы можем рассчитать прогноз на следующие 14 дней? Машинное обучение моделирует матрицу функций X и выводит прогнозируемые значения y. Итак, нам нужно создать матрицу функций X на следующие 14 дней и передать ее нашей модели.

Если мы хотим получить lag-7 на следующий день, следуя обучающему набору, мы можем просто получить значение в 7-й позиции, начиная с конца. lag-7 через два дня после окончания обучающего набора будет значением в 6-й позиции, начиная с конца, и так далее. Аналогично для lag-14.

Как вы могли заметить, мы можем получить только 7 значений lag-7 из нашей истории, и мы можем получить все 14 значений для lag-14. С помощью этой информации мы можем прогнозировать только следующие 7 дней, поэтому мы берем только первые 7 значений lag-14.

С помощью этих функций мы можем рассчитывать прогнозы на следующие 7 дней.

Эти значения можно интерпретировать как значения нашего ряда на следующие 7 дней после даты последнего обучения. Чтобы вычислить прогнозы после этой даты, мы можем использовать эти значения, как если бы они были значениями нашего ряда, и использовать их как lag-7 для следующих периодов.

Другими словами, мы можем заполнить остальную часть нашей матрицы функций этими значениями и реальными значениями lag-14.

Как видите, мы по-прежнему используем реальные значения lag-14, а наши прогнозы использовали в качестве значений для lag-7. Теперь мы можем использовать эти функции для прогнозирования оставшихся 7 дней.

А теперь у нас есть прогнозы на ближайшие 14 дней! Это было не так больно, но и не было ни красиво, ни легко. И мы просто использовали лаги, которые являются самой простой функцией, которую мы можем иметь.

Что, если бы мы использовали lag-1? Нам пришлось бы проделать этот шаг прогнозирования-обновления 14 раз!

А что, если бы у нас были более сложные функции, такие как скользящее среднее для некоторой задержки? Как вы понимаете, это может быть довольно запутанным и подверженным ошибкам.

mlforecast

Помня об этих проблемах, мы создали mlforecast, который является фреймворком, который поможет вам прогнозировать временные ряды с использованием моделей машинного обучения. Он позаботится обо всех этих беспорядочных деталях за вас. Вам просто нужно дать ему модель и определить, какие функции вы хотите использовать, а все остальное сделает mlforecast.

mlforecast доступен как в PyPI (pip install mlforecast), так и в conda-forge (conda install -c conda-forge mlforecast).

Описанная выше проблема может быть решена с помощью mlforecast с помощью следующего кода.

Во-первых, мы должны настроить наши данные в требуемом формате.

Это требуемый формат ввода.

  • индекс с именем unique_id, который идентифицирует каждый раз серию. В этом случае у нас есть только один, но вы можете иметь столько, сколько захотите.
  • столбец ds с датами.
  • столбец y со значениями.

Теперь мы импортируем преобразователь TimeSeries, в котором мы определяем функции, которые хотим использовать. Мы также импортируем класс Forecast, который будет содержать наш преобразователь и модель и будет запускать для нас конвейер прогнозирования.

Мы инициализируем наш трансформатор, указывая лаги, которые мы хотим использовать.

Как видите, этот преобразователь будет использовать в качестве функций lag-7 и lag-14. Теперь мы определяем нашу модель.

Мы создаем объект Прогноз с моделью и преобразователем временных рядов и подгоняем его под наши данные.

А теперь мы просто вызываем прогноз с желаемым горизонтом прогноза.

Это было намного проще, и внутри мы делали то же самое, что и раньше. Давайте быстро проверим.

Убедитесь, что у нас одинаковые прогнозы:

Убедитесь, что у нас такая же модель:

Эксперименты стали проще

Наличие этой высокоуровневой абстракции позволяет нам сосредоточиться на определении лучших функций и модели вместо того, чтобы беспокоиться о деталях реализации. Например, мы можем очень легко опробовать различные задержки, написав простую функцию, которая использует mlforecast:

Бэктестинг

В предыдущих примерах мы вручную разделяли наши данные. Объект Прогноз также имеет метод бэктест, который может сделать это за нас.

Сначала мы приведем все наши данные в требуемый формат.

Теперь мы создаем экземпляр объекта Forecast, как делали раньше, и вместо этого вызываем метод backtest.

Это возвращает генератор с результатами для каждого окна.

result2 здесь то же самое, что и оценка, которую мы делали вручную.

Мы можем определить схему проверки для разных лагов, используя несколько окон.

Преобразования лагов

Мы можем указывать преобразования как для лагов, так и просто для лагов. В библиотеке window_ops есть несколько реализаций различных оконных функций. Вы также можете определить свои собственные преобразования.

Давайте попробуем сезонное скользящее среднее, это будет среднее значение за последние n сезонов, в данном случае это будет среднее значение за последние n понедельники, вторники и т. Д. Однако вычисление обновлений для этой функции, вероятно, будет немного утомительным, однако , используя этот фреймворк, мы можем просто передать его в lag_transforms. Если преобразования принимают дополнительные аргументы (в дополнение к значениям ряда), мы указываем кортеж типа (transform_function, arg1, arg2), которым в данном случае являются season_length и window_size.

help(seasonal_rolling_mean)
Help on CPUDispatcher in module window_ops.rolling:

seasonal_rolling_mean(input_array: numpy.ndarray, season_length: int, window_size: int, min_samples: Union[int, NoneType] = None) -> numpy.ndarray
    Compute the seasonal_rolling_mean over the last non-na window_size samples of the
    input array starting at min_samples.

lag_transforms принимает словарь, в котором ключи - это запаздывания, к которым мы хотим применить преобразования, а значения - это сами преобразования.

Дата особенности

Вы также можете указать функции даты для вычисления, которые являются атрибутами столбца ds и также обновляются на каждом временном шаге. В этом примере лучшая модель будет принимать среднее значение за каждый день недели, что может быть выполнено путем однократного кодирования в столбце дня недели и подбора линейной модели.

Следующие шаги

mlforecast имеет больше функций, таких как распределенное обучение и CLI. Если вам интересно, вы можете узнать больше на следующих ресурсах: