Image

Прогнозирование временных рядов стало проще (часть 3.1): разложение STL

Разложение STL превосходно работает, когда сезонные закономерности со временем меняются.

Делиться

7d755dfbc785caa7b34166d043078208

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

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

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

Наконец, мы оценили каждую модель с помощью средней абсолютной процентной ошибки (MAPE), чтобы увидеть, насколько эффективны наши подходы.

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

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

Здесь мы обратимся к более продвинутому методу разложения, чтобы лучше понять данные: STL — сезонно-трендовая разложение с использованием LOESS.

LOESS означает локально оцененное сглаживание диаграмм рассеяния .

Чтобы лучше понять это на практике, мы воспользуемся набором данных о розничных продажах в универмагах из FRED (Федеральная резервная система экономических данных).

Вот как выглядят данные:

6bf7d838904cfb48eb8587684219a787

Набор данных, с которым мы работаем, отслеживает ежемесячные розничные продажи в универмагах США и поступает из надежного источника FRED (Федеральная резервная система экономических данных).

В нем всего два столбца:

  • Дата_наблюдения – начало каждого месяца
  • Retail_Sales – общий объем продаж за этот месяц, в миллионах долларов.

Временной ряд охватывает период с января 1992 года по март 2025 года , что дает нам для изучения данные о продажах за более чем 30 лет.

Примечание: несмотря на то, что каждая дата отмечает начало месяца (например, 01.01.1992), объем продаж представляет собой общий объем продаж за весь месяц.

Но прежде чем перейти к STL, мы запустим классический season_decompose на нашем наборе данных и посмотрим, что он нам покажет.

Код:

import pandas as pd import matplotlib.pyplot as plt from statsmodels.tsa.seasonal import season_decompose # Загрузка набора данных df = pd.read_csv(«C:/RSDSELDN.csv», parse_dates=['Observation_Date'], dayfirst=True) # Установка столбца даты в качестве индекса df.set_index('Observation_Date', inplace=True) # Установка ежемесячной частоты df = df.asfreq('MS') # MS = Начало месяца # Извлечение ряда series = df['Retail_Sales'] # Применение классической сезонной декомпозиции result = season_decompose(series, model='additive', period=12) # График с пользовательскими цветами fig, axs = plt.subplots(4, 1, figsize=(12, 8), sharex=True) axs[0].plot(result.observed, color='olive') axs[0].set_title('Наблюдаемый') axs[1].plot(result.trend, color='darkslateblue') axs[1].set_title('Тенденция') axs[2].plot(result.seasonal, color='darkcyan') axs[2].set_title('Сезонный') axs[3].plot(result.resid, color='peru') axs[3].set_title('Остаток') plt.suptitle('Классическая сезонная декомпозиция (аддитивная)', fontsize=16) plt.tight_layout() plt.show()

Сюжет:

6b027f8cbacc77a71961a2b7d5e18f58

Во второй части мы рассмотрели, как season_decompose вычисляет трендовые и сезонные компоненты в предположении фиксированной повторяющейся сезонной структуры.

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

Мы применим разложение STL к данным, чтобы увидеть, как они справляются с меняющимися тенденциями и сезонностью.

import pandas as pd import matplotlib.pyplot as plt from statsmodels.tsa.seasonal import STL # Загрузка набора данных df = pd.read_csv(«C:/RSDSELDN.csv», parse_dates=['Observation_Date'], dayfirst=True) df.set_index('Observation_Date', inplace=True) df = df.asfreq('MS') # Обеспечение ежемесячной частоты # Извлечение временного ряда series = df['Retail_Sales'] # Применение разложения STL stl = STL(series, season=13) result = stl.fit() # Построение графика и сохранение компонентов STL fig, axs = plt.subplots(4, 1, figsize=(10, 8), sharex=True) axs[0].plot(result.observed, color='sienna') axs[0].set_title('Наблюдается') axs[1].plot(result.trend, color='goldenrod') axs[1].set_title('Тенденция') axs[2].plot(result.seasonal, color='darkslategrey') axs[2].set_title('Сезонный') axs[3].plot(result.resid, color='rebeccapurple') axs[3].set_title('Остаток') plt.suptitle('STL-разложение розничных продаж', fontsize=16) plt.tight_layout() plt.show()

Сюжет:

fd29c063dc1ae4feb2a81e63108b4f96

После завершения этого шага и понимания того, что делает STL, мы углубимся в то, как он выявляет тенденции и сезонные закономерности за кулисами.

Чтобы лучше понять, как работает разложение STL, мы рассмотрим выборку из нашего набора данных, охватывающую период с января 2010 года по декабрь 2023 года.

1988e629db58590a975e7e9f943da355

Чтобы понять, как разложение STL работает с этими данными, нам сначала нужны грубые оценки тренда и сезонности.

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

Начнем с визуализации ряда розничных продаж (январь 2010 г. – декабрь 2023 г.) и применим процедуру STL Python для извлечения его трендовых, сезонных и остаточных частей.

Код:

import pandas as pd import matplotlib.pyplot as plt from statsmodels.tsa.seasonal import STL # Загрузка набора данных df = pd.read_csv(«C:/STL sample data.csv», parse_dates=['Observation_Date'], dayfirst=True) df.set_index('Observation_Date', inplace=True) df = df.asfreq('MS') # Обеспечение ежемесячной частоты # Извлечение временного ряда series = df['Retail_Sales'] # Применение разложения STL stl = STL(series, season=13) result = stl.fit() # Построение графика и сохранение компонентов STL fig, axs = plt.subplots(4, 1, figsize=(10, 8), sharex=True) axs[0].plot(result.observed, color='sienna') axs[0].set_title('Наблюдаемое') axs[1].plot(result.trend, color='goldenrod') axs[1].set_title('Тенденция') axs[2].plot(result.seasonal, color='darkslategrey') axs[2].set_title('Сезонный') axs[3].plot(result.resid, color='rebeccapurple') axs[3].set_title('Остаток') plt.suptitle('STL-разложение розничных продаж (2010-2023)', fontsize=16) plt.tight_layout() plt.show()

Сюжет:

ddc030dac8b62c69234d2c12a20900a6

Чтобы понять, как STL выводит свои компоненты, мы сначала оцениваем долгосрочную тенденцию данных, используя центрированное скользящее среднее.

Мы воспользуемся примером одного месяца, чтобы продемонстрировать, как рассчитать центрированную скользящую среднюю.

Мы рассчитаем центрированную скользящую среднюю за июль 2010 года .

fbf95429242244b6c3757ce526d3c5d1

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

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

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

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

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

Усреднение обеих оценок возвращает результат к июлю 2010 года, давая истинно центрированное скользящее среднее значение за этот месяц.

90c41fcec2a470a4b30e1ba92fa242e1
68971a36a25666455a750b5d0689154f

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

В самом начале и конце нашего ряда у нас просто нет шести месяцев с обеих сторон для усреднения, поэтому нет «естественной» центрированной скользящей средней за январь-июнь 2010 года или июль-декабрь 2023 года.

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

Таким образом, каждый месяц будет иметь базовую тенденцию, прежде чем мы перейдем к уточнениям LOESS.

Далее мы будем использовать Python для вычисления первоначального тренда для каждого месяца.

Код:

import pandas as pd # Загрузка и подготовка данных df = pd.read_csv(«C:/STL sample data for part 3.csv», parse_dates=[«Observation_Date»], dayfirst=True, index_col=»Observation_Date») df = df.asfreq(«MS») # обеспечение непрерывного ежемесячного индекса # Извлечение ряда sales = df[«Retail_Sales»] # Вычисление двух 12-месячных скользящих средних n = 12 ma1 = sales.rolling(window=n, center=False).mean().shift(-n//2 + 1) ma2 = sales.rolling(window=n, center=False).mean().shift(-n//2) # Центрирование их путем усреднения T0 = (ma1 + ma2) / 2 # Заполнение краев так, чтобы каждый месяц имел значение T0 = T0.fillna(method=»bfill»).fillna(method=»ffill») # Присоединить к DataFrame df[«Initial_Trend»] = T0

Стол:

4568afc55bb2a5df6a33f2cec8adb4e3

Мы извлекли начальный тренд с помощью центрированной скользящей средней, давайте посмотрим, как это выглядит на самом деле.

Мы отобразим ее на графике вместе с исходным временным рядом и окончательной линией тренда STL, чтобы сравнить, как каждая из них отражает общее движение данных.

Сюжет:

00db072da4d46738920c9cf8a7b591b6

Глядя на график, мы видим, что линия тренда от скользящей средней практически совпадает с трендом STL на протяжении большей части лет.

Однако в январе-феврале 2020 года скользящая средняя линия резко упала. Это падение было вызвано внезапным влиянием COVID на продажи.

STL справляется с этим лучше: он не рассматривает это как долгосрочное изменение тренда, а вместо этого отмечает это как остаточное.

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

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

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

Источник: towardsdatascience.com

Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Компания Anthropic получила от Amazon 5 миллиардов долларов и в обмен пообещала инвестировать 100 миллиардов долларов в облачные сервисы.
dummy-img
Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.
Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.
dummy-img
dummy-img
Взаимодействие человека и машины погружается под воду.
Взаимодействие человека и машины погружается под воду.
Дифференциально приватное машинное обучение в масштабе с использованием JAX-Privacy
Image Not Found
Компания Anthropic получила от Amazon 5 миллиардов долларов и в обмен пообещала инвестировать 100 миллиардов долларов в облачные сервисы.

Компания Anthropic получила от Amazon 5 миллиардов долларов и в обмен пообещала инвестировать 100 миллиардов долларов в облачные сервисы.

Вкратце Опубликовано: Изображение предоставлено: Thos Robinson/Getty Images для The New York Times (откроется в новом окне) Джули Борт Компания Anthropic получила от Amazon 5 миллиардов долларов и в обмен пообещала инвестировать 100 миллиардов долларов в облачные сервисы.…

Апр 21, 2026
dummy-img

Как почистить виниловые пластинки (2026): пылесос, ультразвук, чистящий раствор, щетка.

Эти щелчки и треск недопустимы. Приведите свою музыку в порядок с помощью этого удобного руководства. Источник: www.wired.com

Апр 21, 2026
Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.

Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.

Это сегодняшний выпуск The Download, нашей ежедневной новостной рассылки, которая предоставляет вам ежедневную порцию событий в мире технологий. Кибермошенники обходят системы безопасности банков с помощью незаконных инструментов, продаваемых в Telegram. В центре по отмыванию денег в Камбодже…

Апр 21, 2026
Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.

Загрузка: обход банковских систем кибермошенниками и проблемы с удалением углерода.

Это сегодняшний выпуск The Download, нашей ежедневной новостной рассылки, которая предоставляет вам ежедневную порцию событий в мире технологий. Кибермошенники обходят системы безопасности банков с помощью незаконных инструментов, продаваемых в Telegram. В центре по отмыванию денег в Камбодже…

Апр 21, 2026

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