Прогнозирование временных рядов
Нейросетевое прогнозирование временных рядов
Введение
Прогнозирование временных рядов — одна из фундаментальных задач анализа данных, возникающая в экономике, метеорологии, энергетике и многих других областях. Классические статистические методы хорошо работают на линейных зависимостях, но часто не справляются со сложными нелинейными паттернами. Нейронные сети предлагают гибкую альтернативу: они способны автоматически выявлять скрытые закономерности без явного задания модели.
В данной работе демонстрируется простейший нейросетевой подход к прогнозированию, обученный в авторегрессионной постановке. Модель использует два предыдущих значения ряда для предсказания следующего, а затем итеративно строит прогноз на заданный горизонт. Такой подход служит наглядной отправной точкой для знакомства с более сложными архитектурами нейронных сетей.
Используемые библиотеки
Присоединим необходимые библиотеки. Для работы с нейросетью, нам понадобится библиотека Flux.
using Flux, Random, LinearAlgebra, Statistics
Исходные данные
Определим исходные данные. Создадим временной ряд из 100 точек: синусоида + линейный тренд + шум. Нормализуем ряд (вычитаем среднее, делим на стандартное отклонение). Сформируем матрицу признаков.
Random.seed!(42)
# Генерация данных
t = 1:100
L = length(t)
z = 10*sin.(0.2*t) + 0.2*t + 0.3*randn(L)
# Нормализация данных
z_mean = mean(z)
z_std = std(z)
z_norm = (z .- z_mean) ./ z_std # нормализованные данные
# Формирование входной матрицы
x = zeros(2, L)
x[1, 2:end] = z_norm[1:end-1] # z(t-1)
x[2, 3:end] = z_norm[1:end-2] # z(t-2)
x_data = Float32.(x)
z_data = Float32.(z_norm)
Настройка нейросети
Создадим нейросеть: входной слой (2→8), скрытый слой (8→4), выходной слой (4→1). Настроим оптимизатор Adam со скоростью обучения 0.001 и привяжем его к сети. Подготовим массив для записи ошибок на каждой эпохе. Зададим 5000 эпох обучения.
net = Chain(Dense(2 => 8, relu), Dense(8 => 4, relu),Dense(4 => 1))
optimizer = Adam(0.001)
opt_state = Flux.setup(optimizer, net)
losses = Float32[]
epochs = 5000
Функция потерь
Создадим функцию потерь: передадим на вход модели матрицу признаков, получим предсказания, преобразуем в одномерный вектор и вычислим среднеквадратичную ошибку между предсказаниями и истинными значениями.
function loss(model, x, y)
y_pred = vec(model(x))
return Flux.mse(y_pred, y)
end
Обучение нейросети
Запустим цикл обучения: вычислим градиенты и обновим параметры. После обучения получим предсказания сети на всех 100 точках.
for epoch in 1:epochs
current_loss = loss(net, x_data, z_data)
push!(losses, current_loss)
Flux.train!(net, [(x_data, z_data)], opt_state) do m, xb, yb
loss(m, xb, yb)
end
if epoch % 100 == 0
#println("Эпоха $epoch: loss = $(round(current_loss, digits=6))")
end
end
y_train_norm = vec(net(x_data))
y_train = y_train_norm .* z_std .+ z_mean
Прогноз временного ряда
Получим спрогнозированные значения временного ряда на 50 точек вперёд.
function forecast(net, z_norm, z_mean, z_std, horizon=50)
y_full_norm = zeros(Float32, 100 + horizon)
y_full_norm[1:100] = z_norm
for i in 1:horizon
idx = 100 + i
input_vec = Float32.([y_full_norm[idx-1], y_full_norm[idx-2]])
y_full_norm[idx] = net(reshape(input_vec, 2, 1))[1]
end
return y_full_norm .* z_std .+ z_mean
end
y_full = forecast(net, Float32.(z_norm), z_mean, z_std, 50)
Визуализация
Отобразим исходный сигнал, аппроксимацию и прогноз на графике.
# Визуализация
gr()
график = plot(1:100, z,
label="Исходный сигнал",
color=:blue,
linewidth=2,
title="Результаты обучения и прогноза",
legend=:topleft
)
plot!(график, 1:100, y_train,
label="Аппроксимация",
color=:green,
linestyle=:dash,
linewidth=2)
plot!(график, 101:150, y_full[101:150],
label="Прогноз",
color=:red,
linewidth=2)
vline!(график, [100.5], label="Начало прогноза", color=:black, linestyle=:dash)
display(график)
Заключение
В данном примере реализована и обучена полносвязная нейронная сеть для прогнозирования модельного временного ряда. Несмотря на простоту архитектуры, модель успешно приняла как периодическую, так и трендовую составляющие сигнала, а также продемонстрировала возможность многозначного прогноза в авторегрессионном режиме.
На практике нейросетевое прогнозирование временных рядов применяется для:
-
предсказания цен на сырьё, акции и валютные курсы в трейдинговых системах;
-
прогнозирования потребления электроэнергии для балансировки нагрузки энергосетей;
-
оценки спроса на товары в торговле для управления запасами;
-
метеорологического моделирования и краткосрочного прогноза погоды;
-
мониторинга состояния промышленного оборудования по телеметрическим данным.
Представленный скрипт может служить основой для перехода к более продвинутым архитектурам — рекуррентным и трансформерным сетям, специально спроектированным для работы с последовательными данными.
