AnyMath 文档
Notebook

时间序列的神经网络预测

导言

时间序列预测是数据分析的基本任务之一,出现在经济学,气象学,能源和许多其他领域。 经典统计方法在线性依赖关系上运行良好,但它们往往无法应对复杂的非线性模式。 神经网络提供了一个灵活的替代方案:它们能够自动识别隐藏的模式,而无需明确指定模型。

本文演示了最简单的神经网络预测方法,在自回归公式中训练。 该模型使用系列的前两个值来预测下一个值,然后迭代地构建给定地平线的预测。 这种方法可以作为探索更复杂神经网络体系结构的视觉起点。

使用的图书馆

我们将附加必要的库。 要使用神经网络,我们需要Flux库。

In [ ]:
using Flux, Random, LinearAlgebra, Statistics

初始数据

让我们定义初始数据。 让我们创建一个100点的时间序列:正弦+线性趋势+噪声。 将系列归一化(减去平均值,除以标准偏差)。 让我们形成一个特征矩阵。

In [ ]:
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)。 让我们设置学习率为0.001的Adam优化器并将其链接到网络。 我们将准备一个数组,用于记录每个时代的错误。 让我们设置5000个训练周期。

In [ ]:
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

损失函数

让我们创建一个损失函数:我们将向模型输入传递一个特征矩阵,获得预测,将它们转换为一维向量,并计算预测和真实值之间的均方根误差。

In [ ]:
function loss(model, x, y)
    y_pred = vec(model(x))
    return Flux.mse(y_pred, y)
end

神经网络训练

让我们开始学习周期:计算梯度并更新参数。 训练后,我们将获得所有100点的网络预测。

In [ ]:
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$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点的时间序列的预测值。

In [ ]:
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)
Out[0]:
150-element Vector{Float64}:
  2.077686166487098
  4.369704383951254
  6.151928340143768
  7.8801850772692745
  9.659601907697848
 10.663412370556056
 10.99663069738901
 11.154949594543305
 10.904175864829527
 11.106108789428392
 10.037363671824608
  9.406718355367095
  7.885179545387794
  ⋮
  8.16153229190152
  9.871865117523257
 11.16291496603565
 11.63761469392388
 11.440856430263558
 10.529202720345774
  8.602405889069477
  6.954229163008996
  5.774611191033784
  4.69222943408103
  3.7329430285822243
  2.9190516942247546

可视化

让我们在图表上显示原始信号,近似值和预测。

In [ ]:
# 可视化
gr()
=(1:100,z), 
          label="原始信号", 
          color=:blue, 
          linewidth=2,
          title="学习和预测结果",
          legend=:topleft
          )
阴谋!(,1:100,y_train, 
      label="近似值", 
      color=:green, 
      linestyle=:dash,
      linewidth=2)
阴谋!(图表,101:150,y_full[101:150], 
      label="预测", 
      color=:red,
      linewidth=2)
vline!(график, [100.5], label="预测的开始", color=:black, linestyle=:dash)

显示(图表)
No description has been provided for this image

结论

在这个例子中,一个完全连接的神经网络已经被实现和训练来预测一个模型时间序列。 尽管架构简单,但该模型成功地接受了信号的周期性和趋势分量,并证明了在自回归模式下进行多值预测的可能性。

在实践中,神经网络时间序列预测用于:

*预测交易系统中的商品价格、股票和汇率;

*预测电网负荷平衡用电量;

*估计贸易中货物的需求以进行库存管理;

*气象建模和短期天气预报;

*根据遥测数据监测工业设备的状况。

所呈现的脚本可以作为转向更高级架构的基础—循环和变压器网络,专门设计用于处理顺序数据。