Вопрос или проблема
У меня есть временной ряд значений, как показано ниже, где я рассматриваю историю продаж:
[
# Шаг 1
[ Магазин, День недели, Температура, Продажи],
# Шаг 2
[ Магазин, День недели, Температура, Продажи],
# Шаг 3
[ Магазин, День недели, Температура, Продажи],
...
] -> [Продажи с учетом Магазин, День недели, Температура]
Я хочу использовать историю этих значений, чтобы предсказать Продажи на текущую дату. Я хочу, чтобы модель улавливала такие закономерности, как более высокие продажи в выходные дни по сравнению с серединой недели, рост продаж при высокой температуре и характерные для каждого Магазина паттерны.
Каждая конкретная серия данных относится к конкретному Магазину, между последовательностями нет смешения Магазинов.
Теперь, разумеется, я заранее знаю Магазин, День недели и Температуру, так как же мне это закодировать? Должен ли я пропустить историю через LSTM, а затем добавить текущие признаки (Магазин, День недели, Температура) в конец этой последовательности? Я не совсем понимаю, что делать в данном случае.
На данный момент у меня есть нечто вроде этого:
class LSTM(nn.Module):
def __init__(
self,
input_size,
day_embedding_size: int = 4,
days: int = 7
hidden_size=64,
num_layers=2,
dropout=0.2,
):
super(LSTM, self).__init__()
self.day_embeddings= nn.Embedding(
num_embeddings=days, embedding_dim=day_embedding_size
)
self.hidden_size = hidden_size
self.num_layers = num_layers
# LSTM
self.lstm = nn.LSTM(
input_size=input_size + (day_embedding_size- 1),
hidden_size=hidden_size,
num_layers=num_layers,
batch_first=True,
dropout=dropout,
)
# Выход LSTM
combined_size = hidden_size + 1 + day_embedding_size
self.combine_layer = nn.Linear(combined_size, hidden_size)
# Выходные слои
self.fc1 = nn.Linear(hidden_size, hidden_size // 2)
self.fc2 = nn.Linear(hidden_size // 2, 1)
self.relu = nn.ReLU()
self.dropout = nn.Dropout(dropout)
def forward(self, past_sales, next_features):
batch_size = past_sales.size(0)
# Извлечение признаков временных рядов из LSTM
prev_days = past_sales[:, :, 0].long()
prev_temperatures = past_sales[:, :, 1].unsqueeze(-1)
prev_sales = past_sales[:, :, 2].unsqueeze(-1)
# Извлечение текущих признаков
next_day = next_features[:, 0].long()
next_temperature = next_features[:, 1].unsqueeze(-1)
# Получение эмбеддингов дней
past_day_emb = self.day_embeddings(prev_days )
next_day_emb = self.day_embeddings(next_day )
lstm_input = torch.cat([prev_temperatures, past_day_emb , prev_sales ], dim=2)
# Обработка прошлых данных через LSTM
h0 = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(
past_races.device
)
c0 = torch.zeros(self.num_layers, batch_size, self.hidden_size).to(
past_races.device
)
lstm_out, _ = self.lstm(lstm_input, (h0, c0))
lstm_last = lstm_out[:, -1, :]
# Объединение всех признаков
combined = torch.cat(
[lstm_last, next_day_emb , next_temperature ],
dim=1,
)
combined = self.relu(self.combine_layer(combined))
combined = self.dropout(combined)
# Финальные предсказания
out = self.relu(self.fc1(combined))
out = self.fc2(out)
return out
Как вы можете видеть ниже, я фактически просто использую предыдущую серию через LSTM, а затем соединяю признаки, известные мне на текущем временном шаге (День недели, Температура), чтобы предсказать Продажи на их основе.
Это работает не очень хорошо, и я просто не уверен, что у меня правильная структура.
Что является “стандартным” решением в этом случае?
Ответ или решение
Вопрос, который вы поставили, связан с прогнозированием временных рядов на основе данных о продажах, температуре и дне недели для каждого конкретного магазина. С помощью RNN/LSTM вы стремитесь выявить закономерности, такие как повышенные продажи в выходные или в тёплую погоду, а также учитывать уникальные паттерны различных магазинов. Обратите внимание, что RNN (Recurrent Neural Network) и LSTM (Long Short-Term Memory) широко используются именно для анализа временных рядов благодаря способности учитывать зависимость данных на разных временных интервалах.
Теория
Основная идея LSTM заключается в её способности сохранять долгосрочные зависимости благодаря структуре ячейки памяти. В то время как стандартные RNN страдают от проблемы затухания и взрывного градиента, LSTM предлагает решать эти проблемы с помощью специальных управляющих «дверей» (gates), которые контролируют информационные потоки в соответствии с текущими потребностями модели.
Ваш текущий подход согласуется с типичной схемой использования LSTM для временных рядов. Тем не менее, существуют улучшения, которые могут повысить точность моделей и сделать её более адаптивной к различным условиям.
Пример
Рассмотрим стандартный подход к такой задаче:
-
Предобработка данных: Временные ряды, такие как продажи, температура, день недели, необходимо нормализовать или стандартизовать для улучшения сходимости модели. Например, температура может быть переведена в шкалу от 0 до 1.
-
Архитектура сети: Важно правильно определить размеры скрытых слоев, количество слоев, коэффициенты убывания и т.д. В вашем примере LSTM слоям передано
hidden_size=64
, однако стоит попробовать увеличить не только этот параметр, но и количество слоев для более сложного моделирования. -
Вводной слой: Кодировка категориальных переменных, таких как магазин и день недели, с помощью эмбеддингов — это распространённый и правильный подход. Вы уже применяете векторные представления (эшелонирование) для дней недели, что является хорошей практикой.
-
Выходной слой: После обработки данных с помощью LSTM часто полезно использовать несколько полносвязных слоев, чтобы дополнительно смешивать и преобразовывать признаки перед окончательным выводом.
Применение
-
Улучшение кодировки дня недели и магазина: Вы можете задействовать более сложные эмбеддинги, например, объединить эмбеддинги дня недели и конкретного магазина, чтобы захватить уникальные паттерны для каждого магазина в разные дни.
-
Использование различных архитектур: Попробуйте использовать двухголовую сеть, где одна голова – LSTM – будет работать с временными данными, а вторая голова обработает текущие переменные. Затем можно объединить их перед окончательным линейным слоем.
-
Тюнинг гиперпараметров: Экспериментируйте с различными размерами скрытого слоя, количеством слоев, а также с различными скоростями обучения и коэффициентами убывания learning rate.
-
Добавление дополнительных признаков: Подумайте о включении других признаков, таких как праздничные дни, специальные предложения и рекламные акции, которые также могут влиять на продажи.
-
Регуляризация и dropout: Убедитесь, что dropout применяется к правильным слоям для предотвращения переобучения модели. Это может включать более агрессивное использование dropout на входном уровне и на скрытых уровнях.
-
Итеративное улучшение: Постоянно проверяйте модель на новых данных и корректируйте её параметры, чтобы обеспечить адаптацию модели к меняющимся условиям и появлению новых закономерностей.
Этот более глубокий и продуманный подход может улучшить производительность вашей LSTM модели для прогнозирования продаж, учитывая контекстные данные для каждого магазина, дня недели и температурных условий. В центре внимания должна быть не только точность модели, но и её способность обобщать закономерности и предсказывать их в различных условиях.