От теории к практике: узнайте о N-HiTS, новейшей современной методике прогнозирования временных рядов, и используйте Python для ее применения в реальном проекте.

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

На момент выпуска в 2020 году N-BEATS достиг самых современных результатов, используя чистую архитектуру глубокого обучения, которая не полагалась на компоненты, специфичные для временных рядов.

По состоянию на январь 2022 года была предложена новая модель, улучшающая N-BEATS: N-HiTS. Эта новая модель, предложенная Challu and Olivares et al. улучшает обработку ввода и построение вывода, что приводит к повышению точности и снижению вычислительных затрат.

В этой статье мы сначала подробно исследуем внутреннюю работу N-HiTS, чтобы понять, как этот новый метод улучшает N-BEATS. Затем мы используем Python для фактического применения N-HiTS в проекте прогнозирования.

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

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

Изучите новейшие методы анализа временных рядов с помощью моей бесплатной памятки по временным рядам на Python! Получите реализацию статистических методов и методов глубокого обучения на Python и TensorFlow!

Давайте начнем!

Изучение N-HiTS

N-HiTS расшифровывается как Neural Hиерархическая iинтерполяция для Timetime S прогнозирование событий.

Короче говоря, N-HiTS — это расширение модели N-BEATS, которое повышает точность прогнозов и снижает вычислительные затраты. Это достигается за счет того, что модель производит выборку временных рядов с разной скоростью. Таким образом, модель может изучить краткосрочные и долгосрочные эффекты в серии. Затем при создании прогнозов он будет объединять прогнозы, сделанные в разных временных масштабах, с учетом как долгосрочных, так и краткосрочных эффектов. Это называется иерархической интерполяцией.

Давайте углубимся в архитектуру, чтобы в деталях увидеть, как работает модель.

Архитектура N-HiTS

Ниже представлена ​​архитектура N-HiTS.

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

Однако есть несколько ключевых модификаций, которые позволяют N-HiTS постоянно превосходить N-BEATS.

Многоскоростная выборка сигнала

На уровне блоков мы замечаем добавление слоя MaxPool. Вот как модель достигает многоступенчатой ​​выборки.

Напомним, что maxpooling просто принимает наибольшее значение из заданного набора значений. Каждый стек имеет свой размер ядра, и размер ядра определяет скорость выборки.

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

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

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

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

Регрессия

Как только входной сигнал проходит слой MaxPool, блок использует полносвязные сети для выполнения регрессии и вывода прогноза и ретроспективного прогноза.

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

Иерархическая интерполяция

Как следует из названия, N-HiTS использует иерархическую интерполяцию для получения прогнозов. Это используется для уменьшения кардинальности прогнозов. Переведем это на повседневный язык.

Помните, что кардинальность — это просто количество элементов в заданном наборе чисел. Например, мощность [6,7,8,9] равна 4, так как в наборе четыре элемента.

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

Конечно, все это имеет смысл, но может стать проблемой, когда горизонт становится очень длинным. Что, если вместо почасовых прогнозов на следующие 24 часа нам нужны почасовые прогнозы на следующие семь дней? В этом случае выход модели имеет мощность 168 (24 * 7).

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

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

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

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

Однако в случае N-HiTS каждый стек просматривает данные в разном масштабе из-за слоя MaxPool. Следовательно, стек 1 просматривает почасовые данные и, следовательно, должен сделать 168 прогнозов. Стек 2, например, просматривает данные каждые 12 часов, поэтому ему нужно будет сделать только 14 прогнозов (поскольку 12 соответствует 14 из 168). Затем стек 3 просматривает данные каждые 24 часа, поэтому ему нужно сделать только 7 прогнозов (поскольку 24 соответствует 7 из 168).

Таким образом, мы видим, что Стек 1 имеет более высокий коэффициент выразительности, чем Стек 2, который имеет более высокий коэффициент выразительности, чем Стек 3.

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

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

С другой стороны, у N-HiTS есть стеки, работающие на разных частотах. Таким образом, стек 1 делает прогноз на каждом временном шаге, но стек 2 делает прогноз только каждые 12 часов, а стек 3 каждые 24 часа, что снижает стоимость вычислений.

Факт объединения прогнозов в разных временных масштабах определяет иерархическую интерполяцию.

Если непонятно, вот рисунок из оригинальной статьи, который также иллюстрирует иерархическую интерполяцию.

Опять же, на картинке выше мы видим, что каждый стек в N-HiTS выдает разное количество прогнозов, потому что каждый стек работает на разной частоте. Стек 1 рассматривает долгосрочные эффекты, поэтому его прогнозы более разнесены во времени. С другой стороны, Stack 4 рассматривает краткосрочные эффекты и выдает более детальные прогнозы, которые ближе по времени.

Кратко о N-HiTS

Короче говоря, N-HiTS расширяет архитектуру N-BEATS за счет слоя MaxPool, который позволяет каждому стеку рассматривать серию в разном масштабе. Один стек может специализироваться на долгосрочных эффектах, а другой — на краткосрочных. Окончательный прогноз получается путем объединения прогнозов каждого стека в процессе, называемом иерархической интерполяцией. Это делает модель легче и точнее для прогнозирования длинных горизонтов.

Теперь, когда мы подробно изучили внутреннюю работу N-HiTS, давайте применим ее в проекте прогнозирования.

Прогнозирование с помощью N-HiTS

Теперь мы готовы применить модель N-HiTS в проекте прогнозирования. Здесь мы прогнозируем почасовой объем трафика на межштатной автомагистрали 94 в западном направлении. Обратите внимание, что мы используем только образец полного набора данных, доступного в репозитории машинного обучения UCI, любезно предоставленного Министерством транспорта Миннесоты.

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

Для полноты мы приводим здесь все шаги, но если вы недавно читали мою статью о N-BEATS, не стесняйтесь сразу переходить к применению N-HiTS.

Опять же, мы используем Darts, весь код написан на Python, и вы можете получить полный исходный код, а также набор данных на GitHub.

Пойдем!

Прочитать данные

Конечно, каждый проект начинается с импорта необходимых библиотек.

import pandas as pd
import numpy as np
import datetime
import matplotlib.pyplot as plt

from darts import TimeSeries

import warnings
warnings.filterwarnings('ignore')

Затем мы фактически читаем наши данные и сохраняем их в DataFrame.

df = pd.read_csv('data/daily_traffic.csv')

Поскольку мы работаем с Darts, мы перейдем от DataFrame к объекту TimeSeries, который является фундаментальным объектом в Darts. Каждая модель в Darts должна иметь объект TimeSeries в качестве входных данных, и она также выводит объект TimeSeries.

series = TimeSeries.from_dataframe(df, time_col='date_time')

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

series.plot()

Глядя на рисунок выше, мы уже определили, что у нас есть два сезонных периода: недельный и дневной. Понятно, что днем ​​на дороге больше машин, чем ночью, а в будние дни машин больше, чем в выходные.

На самом деле это можно проверить с помощью Darts. Он поставляется с функцией check_seasonality, которая может сказать нам, имеет ли сезонный период статистическую значимость.

В этом случае, поскольку у нас есть почасовые данные, дневная сезонность имеет период 24 (24 часа в день), а недельная сезонность имеет период 168 (24*7 часов в неделю).

Итак, убедимся, что оба сезонных периода значимы.

from darts.utils.statistics import check_seasonality

is_daily_seasonal, daily_period = check_seasonality(series, m=24, max_lag=400, alpha=0.05)
is_weekly_seasonal, weekly_period = check_seasonality(series, m=168, max_lag=400, alpha=0.05)

print(f'Daily seasonality: {is_daily_seasonal} - period = {daily_period}')
print(f'Weekly seasonality: {is_weekly_seasonal} - period = {weekly_period}')

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

Разделить данные

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

train, test = series[:-120], series[-120:]

train.plot(label='train')
test.plot(label='test')

Базовая модель

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

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

from darts.models.forecasting.baselines import NaiveSeasonal

naive_seasonal = NaiveSeasonal(K=168)
naive_seasonal.fit(train)

pred_naive = naive_seasonal.predict(120)

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

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

test.plot(label='test')
pred_naive.plot(label='Baseline')

Затем мы оцениваем производительность базовой линии, используя среднюю абсолютную ошибку (MAE).

from darts.metrics import mae

naive_mae = mae(test, pred_naive)

print(naive_mae)

Это дает нам MAE 249, и, таким образом, это показатель, который мы пытаемся побить, используя N-HiTS.

Применение N-HiTS

Теперь мы готовы применить N-HiTS к нашему проекту.

Darts позволяет нам очень легко использовать самые современные модели, такие как N-BEATS и N-Hits, поэтому мы начинаем с импорта модели, а также средства масштабирования данных. Всегда полезно масштабировать данные от 0 до 1 при использовании глубокого обучения, потому что это ускоряет обучение.

from darts.models import NHiTSModel
from darts.dataprocessing.transformers import Scaler

Затем мы масштабируем наши данные от 0 до 1. Обратите внимание, что мы подгоняем скейлер только к тренировочному набору, чтобы избежать передачи информации из тестового набора в модель.

train_scaler = Scaler()
scaled_train = train_scaler.fit_transform(train)

Теперь мы готовы инициализировать модель N-HiTS. Здесь мы загружаем данные за полную неделю (168 временных шагов) и обучаем модель прогнозировать следующие пять дней (120 временных шагов), поскольку это длина нашего тестового набора.

nhits = NHiTSModel(
    input_chunk_length=168, 
    output_chunk_length=120,
    random_state=42)

Затем мы просто помещаем модель в масштабированный обучающий набор.

nhits.fit(
    scaled_train,
    epochs=50)

Здесь мы действительно можем увидеть, как N-HiTS тренируется намного быстрее, чем N-BEATS. Кроме того, Darts показывает нам размер модели. В случае N-HiTS наша модель весит 8,5 МБ, тогда как N-BEATS весит 58,6 МБ. Он почти в 7 раз легче!

Мы ясно видим более низкие затраты на вычисления, но как модель работает, когда дело доходит до прогнозирования?

Затем мы генерируем прогнозы, используя метод predict. Обратите внимание, что прогнозы будут между 0 и 1, поскольку мы вписываемся в масштабированный обучающий набор, поэтому нам нужно отменить преобразование.

scaled_pred_nhits = nhits.predict(n=120)
pred_nhits = train_scaler.inverse_transform(scaled_pred_nhits)

Мы можем визуализировать прогнозы N-HiTS на рисунке ниже.

test.plot(label='Actual')
pred_nhits.plot(label='N-HiTS')

Затем мы просто распечатываем MAE.

mae_nhits = mae(test, pred_nhits)

print(mae_nhits)

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

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

Тем не менее, теперь вы знаете, как работает N-HiTS и как применять его в проекте прогнозирования!

Заключение

N-HiTS — это последняя разработка в области моделей прогнозирования временных рядов, и было показано, что она неизменно превосходит N-BEATS.

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

Это приводит к тому, что N-HiTS является более легкой моделью с более точными прогнозами на длинных горизонтах.

Надеюсь, вам понравилось читать и вы узнали что-то новое!

Привет 🍺