实践股票数据时序建模分析,基于LSTM+GRU开发构建股票预测模型

时间序列分析建模最近做的不多,在之前做过很多相关的项目,在前面的博文中也都有比较详细的实践记录,感兴趣的可以自行移步阅读即可,这里就不再一一给出详细地址了,最近正好有项目需要用到时序建模相关的模型,想着正好一起找时间梳理记录一下,项目的数据不方便直接使用做实验,这里就从网上随便找了一个股票的数据集来作为实验数据集使用。

首先看下实例数据集:

19-08-05,1219.02002,1225.079956,1219.02002,1219.709961,1558790000
22-08-05,1219.709961,1228.959961,1216.469971,1221.72998,1621330000
23-08-05,1221.72998,1223.040039,1214.439941,1217.589966,1678620000
24-08-05,1217.569946,1224.150024,1209.369995,1209.589966,1930800000
25-08-05,1209.589966,1213.72998,1209.569946,1212.369995,1571110000
26-08-05,1212.400024,1212.400024,1204.22998,1205.099976,1541090000
29-08-05,1205.099976,1214.280029,1201.530029,1212.280029,1599450000
30-08-05,1212.280029,1212.280029,1201.069946,1208.410034,1916470000
31-08-05,1208.410034,1220.359985,1204.400024,1220.329956,2365510000
01-09-05,1220.329956,1227.290039,1216.180054,1221.589966,2229860000
02-09-05,1221.589966,1224.449951,1217.75,1218.02002,1640160000
06-09-05,1218.02002,1233.609985,1218.02002,1233.390015,1932090000
07-09-05,1233.390015,1237.060059,1230.930054,1236.359985,2067700000
08-09-05,1236.359985,1236.359985,1229.51001,1231.670044,1955380000
09-09-05,1231.670044,1243.130005,1231.670044,1241.47998,1992560000
12-09-05,1241.47998,1242.599976,1239.150024,1240.560059,1938050000
13-09-05,1240.569946,1240.569946,1231.199951,1231.199951,2082360000
14-09-05,1231.199951,1234.73999,1226.160034,1227.160034,1986750000
15-09-05,1227.160034,1231.880005,1224.849976,1227.72998,2079340000
16-09-05,1228.420044,1237.949951,1228.420044,1237.910034,3152470000
19-09-05,1237.910034,1237.910034,1227.650024,1231.02002,2076540000
20-09-05,1231.02002,1236.48999,1220.069946,1221.339966,2319250000
21-09-05,1221.339966,1221.52002,1209.890015,1210.199951,2548150000
22-09-05,1210.199951,1216.640015,1205.349976,1214.619995,2424720000
23-09-05,1214.619995,1218.829956,1209.800049,1215.290039,1973020000
26-09-05,1215.290039,1222.560059,1211.839966,1215.630005,2022220000
27-09-05,1215.630005,1220.170044,1211.109985,1215.660034,1976270000
28-09-05,1215.660034,1220.97998,1212.719971,1216.890015,2106980000
29-09-05,1216.890015,1228.699951,1211.540039,1227.680054,2176120000
30-09-05,1227.680054,1229.569946,1225.219971,1228.810059,2097520000
03-10-05,1228.810059,1233.339966,1225.150024,1226.699951,2097490000
04-10-05,1226.699951,1229.880005,1214.02002,1214.469971,2341420000
05-10-05,1214.469971,1214.469971,1196.25,1196.390015,2546780000
06-10-05,1196.390015,1202.140015,1181.920044,1191.48999,2792030000
07-10-05,1191.48999,1199.709961,1191.459961,1195.900024,2126080000
10-10-05,1195.900024,1196.52002,1186.119995,1187.329956,2195990000
11-10-05,1187.329956,1193.099976,1183.160034,1184.869995,2299040000
12-10-05,1184.869995,1190.02002,1173.650024,1177.680054,2491280000
13-10-05,1177.680054,1179.560059,1168.199951,1176.839966,2351150000
14-10-05,1176.839966,1187.130005,1175.439941,1186.569946,2188940000
17-10-05,1186.569946,1191.209961,1184.47998,1190.099976,2054570000
18-10-05,1190.099976,1190.099976,1178.130005,1178.140015,2197010000
19-10-05,1178.140015,1195.76001,1170.550049,1195.76001,2703590000
20-10-05,1195.76001,1197.300049,1173.300049,1177.800049,2617250000
21-10-05,1177.800049,1186.459961,1174.920044,1179.589966,2470920000
24-10-05,1179.589966,1199.390015,1179.589966,1199.380005,2197790000
25-10-05,1199.380005,1201.300049,1189.290039,1196.540039,2312470000

算得上是一个标准的时序数据集了。

接下来需要加载解析原始数据集来构建训练数据集和测试数据集,核心实现如下所示:

def test_data(seq_len, normalise):
    data_windows = []
    for i in range(len_test - seq_len):
        data_windows.append(data_test[i : i + seq_len])
    data_windows = np.array(data_windows).astype(float)
    data_windows = (
        normaliseWindows(data_windows, single_window=False)
        if normalise
        else data_windows
    )
    x = data_windows[:, :-1]
    y = data_windows[:, -1, [0]]
    return x, y

def train_data(seq_len, normalise):
    data_x = []
    data_y = []
    for i in range(len_train - seq_len):
        x, y = nextWindow(i, seq_len, normalise)
        data_x.append(x)
        data_y.append(y)
    return np.array(data_x), np.array(data_y)

完成数据集的构建之后接下来就可以基于深度学习框架来完成模型的初始化搭建了,LSTM和GRU是两种常见的循环神经网络(RNN)结构,它们被广泛用于处理序列数据。本文开发构建的时序预测模型主要是结合LSTM和GRU实现的,下面简单对LSTM和GRU进行总结分析:

LSTM模型:
LSTM(长短期记忆)模型通过引入门控机制和细胞状态解决了传统RNN的长程依赖问题。LSTM能够在网络中传递长距离信息,从而捕捉序列中的时序依赖关系。
细胞状态(Cell State):细胞状态是LSTM的核心,它贯穿整个序列,能够在网络中传递长距离信息。
输入门(Input Gate):决定哪些新信息应该被存储在单元中。它使用前一时刻的隐藏状态和当前输入作为输入,并输出一个介于0和1之间的数值,表示存储和忽略新信息的比例。
遗忘门(Forget Gate):决定哪些信息在单元中被丢弃。它使用前一时刻的隐藏状态和当前输入作为输入,并输出一个介于0和1之间的数值,表示保留和丢弃的比例。
输出门(Output Gate):决定了即将输出到下一个时刻的隐藏状态。它使用前一时刻的隐藏状态和当前输入作为输入,并输出一个介于0和1之间的数值,表示输出的比例。
GRU模型:
GRU(门控循环单元)是RNN的一个新变体,工作原理和LSTM很相似。GRU没有细胞状态,只有一个隐藏状态用于传送信息。它只有两个门结构:重置门和更新门。
重置门(Reset Gate):决定先前的信息哪些部分需要遗忘。
更新门(Update Gate):决定哪些新信息应该被存储在单元中。它可以决定要丢弃哪些信息和要添加哪些新信息。
LSTM和GRU通过引入门控机制和不同的信息流控制方式,增强了RNN处理序列数据的能力,特别是在处理长距离依赖关系方面表现优异。两者在实现细节上有所不同,但都能有效地捕捉序列中的时序依赖关系。在实际应用中,研究人员通常会根据任务需求选择合适的模型结构。

这里我选择的比较熟悉的Keras框架,模型核心实现如下所示:

def build_model(self):
    """
    build
    """
    timer.start()
    self.model.add(LSTM(64, input_shape=(self.step, self.input_dim), return_sequences=True))
    self.model.add(Activation("relu"))
    self.model.add(Dropout(0.2))
    self.model.add(LSTM(128, input_shape=(self.step, self.input_dim), return_sequences=True))
    self.model.add(Activation("tanh"))
    self.model.add(GRU(128, input_shape=(self.step, self.input_dim), return_sequences=True))
    self.model.add(Activation("tanh"))
    self.model.add(Dropout(0.20))
    self.model.add(Dense(64, activation="relu"))
    self.model.add(Dropout(0.20))
    self.model.add(Flatten())
    self.model.add(Dense(1))
    self.model.compile(loss="mse", optimizer="adam")
    print('[Model] Model Compiled')
    return self.model

这里隐藏层的神经单元数量未必是最优的,这里仅仅是根据历史开发经验设定的,后期如果效果不好的话可以针对性地进行一些调参的工作。

完成上述工作之后就可以开始训练模型,核心实现如下所示:

history=self.model.fit(
    x,
    y,
    epochs=epochs,
    batch_size=batch_size,
    callbacks=callbacks,
    validation_split=0.1,
)
self.model.save(save_fname)
print('[Model] Training Completed. Model saved as %s' % save_fname)
plt.clf()
plt.plot(history.history["loss"])
plt.plot(history.history["val_loss"])
plt.title("Model Loss Cruve")
plt.ylabel("Loss")
plt.xlabel("Epochs")
plt.legend(["train", "test"], loc="upper left")
plt.savefig(self.save_dir + "train_validation_loss.png")
plt.close()
historyResult = {}
historyResult["loss"] = history.history["loss"]
historyResult["val_loss"] = history.history["val_loss"]
# loss数据离线存储
with open(self.save_dir + "history.json", "w") as f:
    f.write(json.dumps(historyResult))

训练完成后,我们对整体训练过程的loss进行可视化展示,如下所示:

也可以调整一些参数,这里我得到的更好的参数如下:

在该参数设置下,整体训练loss曲线如下所示:

基于预留的测试集对模型预测效果进行对比分析,这里选取的用于评估时序预测建模效果的指标主要是MSE和R2,时间序列预测任务中,MSE(均方误差)和R2(确定系数)是常用的用于评估模型拟合效果的指标。以下是它们的详细介绍:
均方误差(Mean Squared Error,MSE):MSE是预测值与真实值之间差的平方的平均值。它衡量了模型预测的准确性。
当MSE越小,模型的预测效果越好。
判定系数(Coefficient of Determination,R2):
R2用于评估模型对数据的拟合程度,表示模型解释的变异与总变异的比例。
R2的值越接近于1,表示模型拟合效果越好。
R2越接近于0,表示模型的拟合效果越差。
这两个指标各有特点:MSE关注预测的准确性,而R2关注模型解释的变异比例。在实际应用中,通常会结合使用这两个指标来全面评估模型的拟合效果。

如下所示:

调优参数后预测对比效果如下所示:

可见调参对于提升原始参数设置的效果还是有很大的帮助的,但是这个也不是绝对的,有的数据集就会比较依赖于一个好的参数组合,有的数据集就对调参没有太高的敏感性了,还是需要根据具体的数据来做实验分析。

基于深度学习的时序数据异常检测预测模型通常使用循环神经网络(RNN)或卷积神经网络(CNN)等模型进行建模。 其中,RNN模型是一种经典的序列建模方法,可以很好地处理时间序列数据。在RNN模型中,每个时间步的输入都是当前的观测值和前面的历史观测值,通过对历史数据进行记忆和学习,可以预测当前时刻的观测值。在时序数据异常检测中,可以使用LSTMGRU等RNN模型进行建模,通过对时间序列数据进行预测并计算预测误差来检测异常。具体地,可以将时序数据分为训练集和测试集,训练集用于训练模型,测试集用于检测异常。在训练阶段,可以使用历史数据作为输入,训练模型的参数,使得模型能够准确地预测下一个时间步的观测值。在测试阶段,对于每个时间步,可以使用模型预测当前时刻的观测值,并计算预测误差,如果误差超过了阈值,则判定为异常。 另外,CNN模型也可以用于时序数据异常检测的预测模型中。CNN模型可以有效地提取时间序列数据中的特征,尤其是对于一些周期性的时间序列数据,如股票数据、气象数据等,CNN模型可以很好地提取周期性的特征。在时序数据异常检测中,可以使用CNN模型时间序列数据进行建模,并使用滑动窗口的方式对时间序列数据进行分割,以便进行预测和异常检测。 总的来说,基于深度学习的时序数据异常检测预测模型可以很好地处理时间序列数据,并且具有较高的准确率和鲁棒性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Together_CZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值