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

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

Одной из отличительных особенностей моделей машинного обучения является то, что их параметры можно оценивать на потенциально большом количестве рядов; в отличие от классических методов, которые обычно оцениваются по одному ряду за раз. Хотя машинное обучение демонстрирует большой потенциал, его использование по-прежнему создает несколько практических проблем. С одной стороны, для обучения требуется достаточно данных — в некоторых случаях это вызывает проблему холодного старта, когда трудно заставить модели машинного обучения работать, когда еще не собрано много данных. С другой стороны, даже при наличии достаточного количества данных обучающие модели могут быть несколько более громоздкими. Несмотря на то, что фактический обучающий код теперь можно упростить (например, с помощью Darts), для обучения больших моделей по-прежнему может потребоваться некоторая трудоемкая фаза настройки гиперпараметров, некоторое специальное оборудование (например, графические процессоры) или некоторые изменения в инфраструктуре или процессы, связанные с управлением данными и моделями.

В этой статье мы рассмотрим трансфертное обучение, применяемое к прогнозированию временных рядов. Мы обучим модель глубокого обучения один раз на большом и разнообразном наборе данных временных рядов и увидим, что она работает конкурентоспособно при использовании для прогнозирования разных временных рядов в разных наборах данных. Это само по себе весьма интригующе, так как это означает, что временные ряды из разных областей (таких как демография, финансы или промышленность) могут иметь некоторые общие черты. В зависимости от того, что, по нашему мнению, составляет «учебную задачу», это также можно рассматривать под углом метаобучения (или «обучения обучению»), когда модели могут адаптироваться к новым задачам (например, прогнозированию нового временного ряда) в время вывода без дополнительного обучения [1].

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

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

Авиапассажиры

Начнем с загрузки набора данных, содержащего количество пассажиров для разных авиакомпаний:

Мы не показываем здесь функцию load_air(), но она возвращает два списка, каждый из которых содержит 301 ежемесячный объект TimeSeries. air_train содержит обучающую часть серии (средней продолжительностью ~137 месяцев), а air_test содержит последние 18 месяцев, которые мы оставляем в стороне в качестве проверочного набора. (Примечание: хорошей практикой было бы оставить в стороне еще один тестовый набор, который мы никогда не трогаем, пока не будет выбрана окончательная модель). Здесь мы используем горизонт прогноза 18 месяцев, поскольку он согласуется с горизонтом, используемым для месячных рядов в соревнованиях M3 и M4 (наборы данных которых мы будем использовать позже в статье). Кроме того, мы будем использовать симметричную среднюю абсолютную процентную ошибку (sMAPE) в качестве показателя ошибки для оценки качества наших прогнозов.

Давайте составим несколько обучающих серий:

Большинство сериалов выглядят совершенно по-разному, и они даже не имеют одной и той же временной оси. Например, некоторые серии начинаются в январе 2001 г., а другие — в апреле 2010 г. Вы можете видеть, что максимальное значение для каждой из этих тренировочных серий равно 1. их по их наибольшему абсолютному значению. Выполнение этого типа масштабирования не влияет на sMAPE, поэтому для простоты мы будем работать здесь только с масштабированным рядом. В реальном приложении нам пришлось бы вызывать scaler.inverse_transform() для наших прогнозов, чтобы преобразовать их обратно в исходный домен.

Прогнозирование авиапассажиров с помощью локальных моделей

Теперь мы попытаемся спрогнозировать наши 300 рядов с помощью «классического» подхода, подбирая одну модель для каждого временного ряда. Мы называем модели, обучаемые на одной серии, локальными моделями. Ниже мы сначала напишем две небольшие функции, которые впоследствии облегчат нам жизнь. Во-первых, eval_forecasts() вычисляет медианную ошибку sMAPE всех наших прогнозов (по 300 сериям тестов) и показывает распределение ошибок.

Во-вторых, eval_local_model() перебирает все серии и для каждой серии строит (локальную) модель, подгоняет ее к обучающей части серии и сохраняет прогноз. Затем он вызывает eval_forecasts() для отображения ошибок sMAPE во всех сериях. Он возвращает как список всех ошибок, так и общее прошедшее время.

Получение прогнозов

Теперь мы можем попробовать первую модель прогнозирования на этом наборе данных. В качестве первого шага обычно рекомендуется посмотреть, как работает (очень) наивная модель, слепо повторяющая последнее значение обучающей серии. Это можно сделать в Darts с помощью модели NaiveSeasonal:

Таким образом, самая наивная модель дает нам медианное значение sMAPE около 29,4. Можем ли мы добиться большего успеха с «менее наивной» моделью, использующей тот факт, что сезонность большинства месячных рядов равна 12?

Это лучше. Давайте попробуем ExponentialSmoothing (по умолчанию для месячных рядов будет использоваться сезонность 12).

Это даже лучше! Теперь, я надеюсь, вы видите, насколько это просто. Давайте пока попробуем еще несколько моделей:

Так что кажется, что ARIMA побеждает. Давайте построим (медианную) ошибку, полученную каждой моделью, в зависимости от времени, необходимого для подгонки и прогнозирования:

ARIMA дает наилучшие результаты, но это также (безусловно) самая трудоемкая модель. Метод Theta обеспечивает интересный компромисс, с хорошей точностью прогнозирования и примерно в 50 раз быстрее, чем ARIMA. Можем ли мы найти лучший компромисс, рассмотрев глобальные модели, то есть модели, которые обучаются только один раз, совместно на всех временных рядах?

Прогнозирование авиапассажиров с помощью глобальных моделей

В этом разделе мы будем использовать «глобальные модели», то есть модели, которые обучаются сразу на нескольких сериях. Дартс имеет по существу два типа глобальных моделей:

  • RegressionModels, которые являются обертками вокруг моделей регрессии, подобных sklearn.
  • Модели на основе PyTorch, которые предлагают различные модели глубокого обучения.

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

Начнем с определения функции eval_global_model(), которая работает аналогично eval_local_model(), но на глобальных моделях.

Использование RegressionModel’s

RegressionModel в Darts — это модели прогнозирования, которые могут использовать любую регрессионную модель, совместимую с scikit-learn, для получения прогнозов. По сравнению с глубоким обучением они представляют собой хорошие глобальные модели, поскольку обычно не имеют большого количества гиперпараметров и их можно быстрее обучать. Кроме того, Darts также предлагает некоторые готовые регрессионные модели, такие как LinearRegressionModel и LightGBMModel.

Теперь мы воспользуемся нашей функцией eval_global_models() и попробуем несколько из этих регрессионных моделей.

Вы можете обратиться к документации по API, чтобы узнать, как использовать эти модели. Важными параметрами являются lags и output_chunk_length. Они определяют, соответственно, длину окон ретроспективного и прогнозного прогнозов, используемых моделью, и соответствуют длинам входных/выходных срезов, используемых для обучения. Например, lags=24 и output_chunk_length=12 означают, что модель будет использовать последние 24 задержки, чтобы предсказать следующие 12. В нашем случае, поскольку самая короткая серия обучения имеет длину 36, у нас должно быть lags + output_chunk_length <= 36. (Обратите внимание, что lags также может быть списком целых чисел, представляющих отдельные задержки, которые будут использоваться моделью, а не длину окна).

Давайте попробуем линейную регрессию:

ЛГБМ:

И случайный лес:

Использование глубокого обучения

Ниже мы обучим модель N-BEATS на нашем наборе данных air. Опять же, вы можете обратиться к API doc за документацией по гиперпараметрам. Следующие гиперпараметры должны стать хорошей отправной точкой:

А теперь давайте построим модель, обучим ее и получим прогнозы. Обучение занимает порядка минуты или двух на (несколько медленном) графическом процессоре Colab.

Давайте еще раз сравним наши модели:

Таким образом, похоже, что модель линейной регрессии, обученная совместно на всех сериях, теперь обеспечивает наилучший компромисс между точностью и скоростью (примерно в 85 раз быстрее, чем ARIMA для аналогичной точности). Линейная регрессия часто помогает!

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

Перенос обучения с помощью модели N-BEATS

Модели глубокого обучения часто работают лучше при обучении на больших наборах данных. Давайте попробуем загрузить все 48 000 месячных временных рядов в набор данных соревнований M4 и еще раз обучить нашу модель на этом большом наборе данных.

m4_train — это список, содержащий 47 992TimeSeries, которые уже были масштабированы, поэтому максимальное значение в обучающей серии равно 1. Мы будем использовать только обучающую часть серии M4 и не будем хранить здесь тестовую часть.

Теперь мы снова попробуем обучить модель N-BEATS, но на этом большем наборе данных.

По умолчанию количество обучающих выборок (входных, выходных), сгенерированных для обучения модели прогнозирования на основе машинного обучения из заданной последовательности рядов, пропорционально количеству рядов, умноженному на их длину. Набор данных M4 содержит 48 000 рядов со средней длиной ~216 временных шагов. Таким образом, если мы оставим параметры по умолчанию, мы получим порядка ~ 10 миллионов обучающих выборок. Чтобы несколько ограничить время, необходимое каждой эпохе, мы ограничим количество обучающих выборок, используемых в серии. Это делается при вызове fit() с параметром max_samples_per_ts. Мы добавляем новый гиперпараметр MAX_SAMPLES_PER_TS, чтобы зафиксировать это. Примечание. Если нам нужен больший контроль над тем, как генерируются обучающие примеры (ввод, вывод) для обучения модели, мы могли бы вызвать fit_from_dataset() вместо fit() и предоставить реализацию darts.utils.data.TrainingDataset по нашему выбору.

Поскольку тренировочные серии M4 немного длиннее, мы также можем использовать немного более длинный input_chunk_length.

Теперь мы можем снова построить и обучить нашу модель:

Теперь мы можем использовать нашу модель, обученную M4, для получения прогнозов для ряда авиапассажиров. Поскольку мы используем здесь модель для переноса обучения, мы будем синхронизировать только часть вывода (при условии, что модель была предварительно обучена заранее).

И давайте еще раз сравним все наши модели:

Хотя это не самая лучшая модель с точки зрения точности, наша модель N-BEATS, предварительно обученная на M4, достигает конкурентоспособной точности. Это весьма примечательно, поскольку эта модель не обучалась ни одному из рядов авиапассажиров, которые мы просили прогнозировать! Шаг прогнозирования с N-BEATS примерно в 350 раз быстрее, чем шаг подгонки-прогноза, который нам нужен с ARIMA, и примерно в 4 раза быстрее, чем шаг подгонки-предсказания линейной регрессии.

Ради интереса мы также можем вручную проверить, как эта модель ведет себя в другой серии — например, в серии ежемесячного производства молока, доступной в darts.datasets:

Так что кажется, что эта модель вполне способна на месячные серии. Является ли это чертой N-BEATS или мы получили бы подобное поведение, если бы обучили другие глобальные модели (например, линейную регрессию или LGBM) на M4, а затем оценили их на ряду авиапассажиров?

Попытка трансферного обучения с другими глобальными моделями

Попробуем сначала с LinearRegressionModel

И с LightGBMModel

Наконец, давайте также нанесем на график эти новые результаты:

Линейная регрессия также предлагает конкурентоспособную производительность. Это несколько медленнее, вероятно, только потому, что вывод с помощью N-BEATS эффективно распределяется по пакетам временных рядов и выполняется на графическом процессоре.

Резюме: используйте ту же модель в наборе данных M3

Итак, нам повезло с набором данных о пассажирах авиакомпаний? Давайте посмотрим, повторив весь процесс с новым набором данных :) Вы увидите, что на самом деле требуется очень мало строк кода. В качестве нового «тестового» набора данных мы будем использовать 1400 месячных рядов из конкурса прогнозов M3. Вот весь код, необходимый для запуска и тестирования всех наших моделей:

А теперь, сравнивая их все:

Здесь также предварительно обученная модель N-BEATS получает приемлемую точность, хотя и не такую ​​хорошую, как самые точные модели. Обратите внимание, что две модели из трех наиболее точных (экспоненциальное сглаживание и фильтр Калмана) не так хорошо работали при использовании в серии авиапассажиров. ARIMA работает лучше всего, но примерно в 170 раз медленнее, чем N-BEATS, который не требует никакого обучения и занимает около 15 мс на временной ряд для создания своих прогнозов. Напомним, что эта модель N-BEATS никогда не обучалась ни одному ряду, который мы просим ее прогнозировать.

Выводы

Трансферное обучение и метаобучение, безусловно, являются интересным направлением, которое в настоящее время мало изучено в прогнозировании временных рядов. Когда это удается? Когда это не удается? Может ли тонкая настройка помочь? Когда его следует использовать? Многие из этих вопросов еще предстоит изучить, но мы надеемся показать, что сделать это довольно легко с моделями Darts.

Итак, какой метод лучше всего подходит для вашего случая? Как всегда, это зависит. Если вы имеете дело в основном с изолированными рядами, имеющими достаточную историю, классические методы, такие как ARIMA, помогут вам пройти долгий путь. Даже в больших наборах данных, если вычислительная мощность не является слишком большой проблемой, они могут представлять интересные готовые варианты для одномерных рядов. С другой стороны, если вы имеете дело с большим количеством рядов или многомерных рядов, методы машинного обучения и глобальные модели часто будут подходящим вариантом. Они могут фиксировать закономерности в широком диапазоне различных временных рядов и, как правило, работают быстрее. Не стоит недооценивать модели на основе линейной регрессии в этой категории! Если у вас есть причины полагать, что вам нужно фиксировать более сложные шаблоны, или если скорость логического вывода для вас действительно важна, попробуйте методы глубокого обучения. N-BEATS доказал свою ценность для метаобучения [1], но потенциально может работать и с другими моделями.

Авторы

Жюльен Герцен, Флориан Раваси, Гийом Рэй, Гаэль Грош

Рекомендации

[1] Орешкин и др., Структура метаобучения с приложениями для нулевого прогнозирования временных рядов, 2020, https://arxiv.org/abs/2002.02887