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

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

Роль глубокого обучения в решении сложных задач анализа временных данных

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

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

Подготовка данных для прогнозирования

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

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

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

Преобразование данных в подходящий формат для нейронных сетей

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

Глубокие нейронные сети, такие как LSTM, работают с последовательными данными. Они "помнят" предыдущие значения и используют эту информацию для прогнозирования будущих. Для этого нужно преобразовать временной ряд в последовательность обучающих примеров, где каждый пример состоит из некоторого числа предыдущих значений и соответствующего целевого значения (то, что мы хотим предсказать).

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

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

import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split

# Загрузка данных (предположим, у нас есть столбец "value" с временными значениями)
data = pd.read_csv('time_series_data.csv')

# Обработка выбросов
data['value'] = data['value'].apply(lambda x: x if x < upper_threshold else upper_threshold)

# Заполнение пропущенных значений
data['value'].fillna(method='ffill', inplace=True)

# Преобразование данных в формат для нейронных сетей
sequence_length = 10  # Длина последовательности
sequences = []
targets = []

for i in range(len(data) - sequence_length):
    seq = data['value'].values[i:i + sequence_length]
    target = data['value'].values[i + sequence_length]
    sequences.append(seq)
    targets.append(target)

sequences = np.array(sequences)
targets = np.array(targets)

# Масштабирование данных
scaler = MinMaxScaler()
sequences_scaled = scaler.fit_transform(sequences)
targets_scaled = scaler.transform(targets.reshape(-1, 1))

# Разделение на обучающий и тестовый наборы
X_train, X_test, y_train, y_test = train_test_split(sequences_scaled, targets_scaled, test_size=0.2, random_state=42)

Приведенный код загружает временные данные из CSV файла, обрабатывает выбросы и заполняет пропущенные значения. Затем данные преобразуются в последовательности для обучения нейронной сети. Далее происходит масштабирование данных с использованием MinMaxScaler, чтобы они находились в диапазоне [0, 1]. Наконец, данные разделяются на обучающий и тестовый наборы с помощью функции train_test_split из библиотеки scikit-learn.

Архитектуры нейронных сетей для прогнозирования временных рядов

Рекуррентные нейронные сети (RNN) и их способность учитывать последовательность данных

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

import tensorflow as tf
from tensorflow.keras.layers import SimpleRNN

model = tf.keras.Sequential([
    SimpleRNN(64, activation='relu', input_shape=(sequence_length, num_features)),
    tf.keras.layers.Dense(1)
])

Долгая краткосрочная память (LSTM) и устранение проблемы затухающего градиента

Хотя RNN предоставляют механизм для учета последовательности, они страдают от проблемы затухающего градиента. При обучении на длинных последовательностях, модель может начать забывать далекие зависимости, что снижает качество прогнозов. LSTM является решением этой проблемы. Он добавляет "ворота" для контроля потока информации, что позволяет модели выбирать, https://habr.com/ru/companies/otus/articles/753482/какую информацию запомнить, а какую забыть.

from tensorflow.keras.layers import LSTM

model = tf.keras.Sequential([
    LSTM(64, activation='relu', input_shape=(sequence_length, num_features)),
    tf.keras.layers.Dense(1)
])

Сети долгой памяти с вниманием (Attention LSTM) для более точных прогнозов

Следующим шагом на нашем пути является Attention LSTM - эволюция LSTM, которая добавляет внимание к процессу. Эта архитектура позволяет сети фокусироваться на наиболее информативных частях последовательности. Подумайте о ней как о внимательном чтеце, который выделяет ключевые моменты в тексте.

from tensorflow.keras.layers import LSTM, Attention

model = tf.keras.Sequential([
    LSTM(64, activation='relu', return_sequences=True, input_shape=(sequence_length, num_features)),
    Attention(use_scale=True),
    tf.keras.layers.Dense(1)
])

Настройка модели

Разделение данных на обучающий и тестовый наборы

Первым шагом на пути создания надежной модели является разделение данных на обучающий и тестовый наборы. Обучающий набор служит для "обучения" модели, тогда как тестовый - для проверки её качества на реальных данных. Размеры этих наборов важно подбирать соответственно, чтобы избежать переобучения или недообучения модели. Типичным выбором может быть 80% данных для обучения и 20% для тестирования.

Пример разделения данных с использованием библиотеки scikit-learn в Python:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(sequences_scaled, targets_scaled, test_size=0.2, random_state=42)

Выбор функции потерь и оптимизатора для обучения нейронной сети

Как только данные разделены, модель нужно настроить для обучения. Один из ключевых аспектов - выбор функции потерь, которая измеряет, насколько близки прогнозы модели к реальным значениям. Это может быть среднеквадратическая ошибка (MSE) для регрессии или категориальная кросс-энтропия для классификации. Далее, оптимизатор - это алгоритм, который корректирует веса модели, чтобы минимизировать выбранную функцию потерь. Алгоритмы, такие как Adam, RMSProp и SGD, помогают модели "узнать" из данных и улучшить свои прогнозы.

Пример компиляции модели с определением функции потерь и оптимизатора в Python:

model.compile(loss='mean_squared_error', optimizer='adam')

Оценка качества модели: сравнение прогнозов с фактическими значениями временных рядов

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

Пример оценки качества модели и расчет метрик в Python:

predictions = model.predict(X_test)
mse = mean_squared_error(y_test, predictions)
mae = mean_absolute_error(y_test, predictions)

Пример

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

Шаг 1: Подготовка данных

Первым шагом является подготовка данных. Давайте представим, что у нас есть CSV-файл sales_data.csv, который содержит два столбца: "Дата" и "Продажи".

import pandas as pd

# Загрузка данных
data = pd.read_csv('sales_data.csv')

# Преобразование столбца "Дата" в формат datetime
data['Дата'] = pd.to_datetime(data['Дата'])

# Установка столбца "Дата" как индекс
data.set_index('Дата', inplace=True)

# Нормализация данных
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
data['Продажи'] = scaler.fit_transform(data['Продажи'].values.reshape(-1, 1))

Шаг 2: Создание последовательностей временных рядов

Для обучения модели нам необходимо создать последовательности временных рядов. Пусть мы хотим использовать последние 30 дней для прогноза продаж следующего дня.

import numpy as np

sequence_length = 30
sequences = []
targets = []

for i in range(len(data) - sequence_length):
    sequences.append(data.iloc[i:i+sequence_length].values)
    targets.append(data.iloc[i+sequence_length]['Продажи'])

sequences = np.array(sequences)
targets = np.array(targets)

Шаг 3: Разделение данных на обучающий и тестовый наборы

Теперь мы разделим данные на обучающий и тестовый наборы, например, в пропорции 80/20.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(sequences, targets, test_size=0.2, random_state=42)

Шаг 4: Создание и обучение модели LSTM

Создадим модель с архитектурой LSTM, добавив в неё слои LSTM и полносвязный слой.

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense

model = Sequential([
    LSTM(64, activation='relu', input_shape=(sequence_length, 1)),
    Dense(1)
])

model.compile(loss='mean_squared_error', optimizer='adam')
model.fit(X_train, y_train, epochs=50, batch_size=32, validation_data=(X_test, y_test))

Шаг 5: Оценка модели и создание прогнозов

После обучения модели оценим её качество на тестовых данных и создадим прогнозы для будущих дней.

from sklearn.metrics import mean_squared_error

predictions = model.predict(X_test)
mse = mean_squared_error(y_test, predictions)

# Преобразование обратно в исходный масштаб
predictions_rescaled = scaler.inverse_transform(predictions)

# Создание прогноза на будущие дни
future_sequences = np.array([data.iloc[-sequence_length:].values])
future_predictions = model.predict(future_sequences)
future_predictions_rescaled = scaler.inverse_transform(future_predictions)

Здесь мы создали полноценный пример пошагового прогнозирования временных рядов с использованием глубокого обучения на Python. Мы начали с подготовки данных, затем создали последовательности временных рядов, разделили данные, создали и обучили модель LSTM, оценили её качество и даже создали прогнозы на будущие дни. Этот пример поможет вам лучше понять, как можно использовать глубокое обучение для прогнозирования временных рядов.

Заключение

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

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

Комментарии (1)


  1. Ad_fesha
    09.08.2023 15:40
    +2

    Я ведь правильно понимаю, это просто пример для разбора?
    В реальности, если не отстал от трендов, sota все еще бустинги/ансамбли бустингов. Нейросети в прогнозировании ВР не особо применяются и в проде если и встречаются, то крайне редко

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