Почему линейная регрессия хорошо работает с временными рядами?

Вопрос или проблема

Я следовал от этого вопроса.


У меня есть следующая задача: у меня есть данные временных рядов. Обучение по последовательно 3 дням для предсказания каждого 4-го дня. Каждый день данных представляет собой один CSV файл, который имеет размерность 24×25. Каждый пункт данных в каждом CSV файле является пикселем.

Теперь мне нужно сделать следующее: предсказать день 4 (то есть 4-й день), используя обучающие данные дня 1, дня 2, дня 3 (то есть три последовательных дня), а затем рассчитать mse между предсказанными данными дня 4 и оригинальными данными дня 4. Назовем это mse1.

Аналогично, мне нужно предсказать день 5 (то есть 5-й день), используя обучающие данные дня 2, дня 3, дня 4, а затем рассчитать mse2 (mse между предсказанными данными дня 5 и оригинальными данными дня 5).

Мне нужно предсказать день 6 (то есть 6-й день), используя обучающие данные дня 3, дня 4, дня 5, а затем рассчитать mse3 (mse между предсказанными данными дня 6 и оригинальными данными дня 6).

……….

И наконец, я хочу предсказать день 93, используя обучающие данные дня 90, дня 91, дня 92, рассчитать mse90 (mse между предсказанными данными дня 93 и оригинальными данными дня 93).

Я хочу использовать в этом случае линейную регрессию, и у нас есть 90 mse для этой модели.

import os
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt

# Пути
data_folder = r'C:\Users\alokj\OneDrive\Desktop\jupyter_proj\All_data'
output_folder = r'C:\Users\alokj\OneDrive\Desktop\jupyter_proj\90_days_merged'

# Убедитесь, что папка для вывода существует
os.makedirs(output_folder, exist_ok=True)

# Список всех CSV файлов в папке
csv_files = [f for f in os.listdir(data_folder) if f.endswith('.csv')]

# Сортировка файлов на основе числовой части, извлеченной из имени файла
csv_files = sorted(csv_files, key=lambda x: int(x.split('_Day')[1].split('_')[0]))

# Подготовка данных
data_list = [pd.read_csv(os.path.join(data_folder, file), header=None).values for file in csv_files]
data_array = np.array(data_list)  # Формат: (число дней, 24, 25)

# Уплощение данных для более удобной обработки в моделях регрессии
num_days, rows, cols = data_array.shape
data_flattened = data_array.reshape(num_days, -1)  # Формат: (число дней, 600)

# Подготовка признаков и целевой матрицы для диапазона (3, num_days)
X = np.array([data_flattened[i-3:i].flatten() for i in range(3, num_days)])  # Формат: (num_days-3, 1800)
y = data_flattened[3:num_days]  # Цель - 4-й день в каждой последовательности

# Разделение на обучающую и тестовую выборки и валидация (отдельное фиксированное разделение)
train_size = int(0.8 * len(X))  # 80% для обучения
X_train = X[:train_size]
y_train = y[:train_size]
X_test = X[train_size:]
y_test = y[train_size:]

# Масштабирование данных
scaler_X = MinMaxScaler()
scaler_X.fit(X_train)  # Применение к обучающему набору
X_train_scaled = scaler_X.transform(X_train)
X_test_scaled = scaler_X.transform(X_test)

scaler_y = MinMaxScaler()
scaler_y.fit(y_train)  # Применение к обучающему набору
y_train_scaled = scaler_y.transform(y_train)
y_test_scaled = scaler_y.transform(y_test)

### Линейная регрессия
lr_model = LinearRegression()
lr_model.fit(X_train_scaled, y_train_scaled)

y_pred_test_scaled_lr = lr_model.predict(X_test_scaled)
y_pred_test_lr = scaler_y.inverse_transform(y_pred_test_scaled_lr)

# Валидация для дней с 3 по 93
XX = np.array([data_flattened[i-3:i].flatten() for i in range(3, 96)])  # Формат: (90, 1800)
yy = data_flattened[3:93]  # Цель для валидации

yy_pred_lr = lr_model.predict(scaler_X.transform(XX))
yy_pred_lr = scaler_y.inverse_transform(yy_pred_lr)

# Расчет остатков для линейной регрессии
residuals_lr = [np.mean((yy[i] - yy_pred_lr[i])**2) for i in range(len(yy))]

# Построение графика остатков для всех моделей
days = [f'День {i+1}' for i in range(90)]  # Начинаем метки с Дня 4 до Дня 93
plt.figure(figsize=(12, 6))
plt.plot(days, residuals_lr, label="Остатки линейной регрессии", marker="o")

# Настройка графика
plt.xticks(ticks=range(0, len(days), 2), labels=[f'День {i+1}' for i in range(0, len(days), 2)], rotation=45, ha="right")
plt.xlabel('Дни (валидирующий набор)')
plt.ylabel('Остатки (MSE)')
plt.title('Остатки моделей (валидирующий набор)')
plt.legend()
plt.grid(True)

# Сохранение и отображение графика
plt.savefig(os.path.join(output_folder, 'residuals_plot_models_comparison_with_naive.png'))
plt.show()

Мой результат:
введите описание изображения здесь

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

Но в моем случае, судя по приведенному выше графику, модель регрессии работает исключительно хорошо (то есть среднеквадратичная ошибка очень низкая, близка к нулю), не мог бы кто-нибудь проверить мою модель регрессии в коде (если я допустил какие-то ошибки или баги, о которых я мог не знать)?

На самом деле, я реализовал мой код на основе предложений @RobertLong из его ответа на вышеупомянутый вопрос.

Ссылка на папку с данными за все 93 дня ссылка, которую я использовал для кода.

Ответ или решение

Почему линейная регрессия хорошо работает с временными рядами

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

1. Подходящие условия для линейной регрессии

В вашем случае линейная регрессия оказывается эффективной по нескольким причинам:

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

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

2. Формирование признаков

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

3. Применение линейной регрессии

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

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

4. Результаты и их интерпретация

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

  • Линейные зависимости: Рынок или сценарий, с которым вы работаете, может иметь сильные линейные зависимости, что делает линейную регрессию подходящей.

  • Однородность данных: Если данные в ваших CSV-файлах не имеют резких изменений и колебаний, линейная регрессия сможет справиться с задачей предсказания без сильных колебаний ошибок.

Заключение

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

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

Оцените материал
Добавить комментарий

Капча загружается...