股票预测 lstm(时间序列的预测步骤)

LSTM数据集实战如果对LSTM原理不懂得小伙伴可以看博主下一篇博客,因为博主水平有限,结合其他文章尽量把原理写的清楚些。数据集首先附上数据集链接:https://pan.baidu.com/s/1AKsz-ohmYHr9mBEEh76P5g提取码:6owv这个数据集是关于股票的,里面有日期,开盘价等信息。既然是时间序列预测,我们最关心的是预测值在时间维度上的走势如何,那我们只要最后一列volume和第一列date这两列就好了。实战先是导入相关包,一些常见的包就不详细说了,我们需要的Se

大家好,又见面了,我是你们的朋友全栈君。

如果对LSTM原理不懂得小伙伴可以看博主下一篇博客,因为博主水平有限,结合其他文章尽量把原理写的清楚些。

数据

首先附上数据集
链接:https://pan.baidu.com/s/1AKsz-ohmYHr9mBEEh76P5g
提取码:6owv
这个数据集是关于股票的,里面有日期,开盘价等信息。
在这里插入图片描述
既然是时间序列预测,我们最关心的是预测值在时间维度上的走势如何,那我们只要最后一列volume和第一列date这两列就好了。

实战

先是导入相关包,一些常见的包就不详细说了,我们需要的Sequential,Dense, Activation, Dropout,这些可以在博主上几期关于keras的实战介绍。mean_squared_error是sklearn里面一个评价模型好坏的指标,相对来说越小越好,但也要看数据集值的范围。MinMaxScaler是一个归一化的包,归一化有很多好处,可以让模型算的更快,一些求导呀,梯度下降这些的,归一化后数据小,这些算法自然就运行快。

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import math
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout, LSTM
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error
from keras import optimizers
import time

这个是创建变量x和y的,因为lstm时间序列不像别的回归一个x,另一个值y,lstm的x和y全是一组数据产生的,也就是它自己和自己比。有一个关键的参数是look_back这个按中文直译就是回看,回溯,理解起来也很容易,假如是这个data是[1,2,3,4,5],look_back为1的话.
x
[[1]
[2]
[3]] y就是[2 3 4],意思就是用前一个数据预测后一个,这是look_back为1的意思。假如是为8,那前8个数据预测第9个数据。小伙伴们可以试试改变这个值,看一下结果是否会更好。
注意维度,维度这样设置一是归一化需要,二是输入网络的要求。
下面这个函数功能就是把data,

def creat_dataset(dataset, look_back=1):
    dataX, dataY = [], []
    for i in range(len(dataset)-look_back-1):
        a = dataset[i: (i+look_back)]
        dataX.append(a)
        dataY.append(dataset[i+look_back])
    return np.array(dataX), np.array(dataY)

读取一下数据,这些参数的意思是,输出series,series的序号就是date,这样方便下面画图,看着也更加直观。因为我们只要首尾2列,那就是0,5.

dataframe = pd.read_csv('zgpa_train.csv',
                        header=0, parse_dates=[0],
                        index_col=0, usecols=[0, 5], squeeze=True)
dataset = dataframe.values
dataframe.head(10)

在这里插入图片描述
这里就画一下图,之所以弄成series就是为了用pandas画图。

plt.figure(figsize=(12, 8))
dataframe.plot()
plt.ylabel('price')
plt.yticks(np.arange(0, 300000000, 100000000))
plt.show()

在这里插入图片描述
这里就是归一化操作,有一个feature_range=(0, 1)这个意思是所有数据标准化到0-1区间内,就是归一化的意思,如果(0,100)那就是标准化到0-100这个区间。最后把它转换成列向量

scaler = MinMaxScaler(feature_range=(0, 1))
dataset = scaler.fit_transform(dataset.reshape(-1, 1))

分割数据集,这个很好理解,一会用来测试。

train_size = int(len(dataset)*0.8)
test_size = len(dataset)-train_size
train, test = dataset[0: train_size], dataset[train_size: len(dataset)]

调用前面函数分别生成训练集和测试集的x,y。

look_back = 1
trainX, trainY = creat_dataset(train, look_back)
testX, testY = creat_dataset(test, look_back)

建立模型,这里注意下如果是多层lstm的话一定要注意前后维度对接,也就是input和output维度,当前层的input维度是上一次层的output维度。return_sequences=True表示返回这个维度给下面。
剩下的就是很基础且通用的配置了。更详细的在博主另一篇关于keras的实战。

model = Sequential()

model.add(LSTM(input_dim=1, output_dim=50, return_sequences=True))
#model.add(Dropout(0.2))

model.add(LSTM(input_dim=50, output_dim=100, return_sequences=True))
#model.add(Dropout(0.2))

model.add(LSTM(input_dim=100, output_dim=200, return_sequences=True))
#model.add(Dropout(0.2))

model.add(LSTM(300, return_sequences=False))
model.add(Dropout(0.2))

model.add(Dense(100))
model.add(Dense(output_dim=1))

model.add(Activation('relu'))
start = time.time()
model.compile(loss='mean_squared_error', optimizer='Adam')
model.summary()

查看一下结构,我们建立的网络层数不多,参数也不多,还不到100万。
在这里插入图片描述
设置了个时间,很快,半分钟都不到就训练完50个epoch。validation_split=0.1表示拿出训练集的10%作为验证集,有了验证集能够更好的训练模型,就相当于给模型纠错。 verbose=2表示打印出每个epoch的信息,默认是1,1的话就更好看,因为有个进度条和时间。小伙伴们不妨试试。这里有个history,意思也很容易理解,训练的历史过程,下面会阐述用处。

history = model.fit(trainX, trainY, batch_size=64, nb_epoch=50, 
                    validation_split=0.1, verbose=2)
print('compilatiom time:', time.time()-start)

在这里插入图片描述
这就很简单了,把数据丢进去预测。

trainPredict = model.predict(trainX)
testPredict = model.predict(testX)

因为前面进行了归一化,现在的数据都是0-1之间的,这里的作用就是反归一化,让它恢复原来数据范围。

trainPredict = scaler.inverse_transform(trainPredict)
trainY = scaler.inverse_transform(trainY)
testPredict = scaler.inverse_transform(testPredict)
testY = scaler.inverse_transform(testY)

打印一下评分,写到这博主发现小错误,不过懒得改了,下面那个是test score。看到我们的score都非常大,那这是不是说明我们模型很差劲,并不是,这个评分只能参考参考,并不是很绝对。因为我们数据值大,数据都是10的8次方左右。稍微有一点偏差,假如是原来值800000000,预测750000000,其实相差不大,误差才1/16,但是数值大,数值的误差有50000000.这样再平方根号一系列操作后,有可能会更大也有可能变小。总之这个指标只是参考参考。博主写到这里猜想,如果拿没有反归一化的数据进行评分那么是不是评分就很小呢?小伙伴们可以试试。

trainScore = math.sqrt(mean_squared_error(trainY, trainPredict[:, 0]))
print('Train Sccore %.2f RMSE' %(trainScore))
testScore = math.sqrt(mean_squared_error(testY, testPredict[:, 0]))
print('Train Sccore %.2f RMSE' %(testScore))

在这里插入图片描述
接下来的操作是为了画图,首先empty_like方法表示创建一个空数组,这个空数组很像dataset,为什么呢,因为维度一样,但是值还没初始化。然后我们让其全为空后进行填值。最后一行的操作相当于是一个100个数值的数值,我填了前面70个,因为前面70个是我训练集的预测值,后面30为空。

trainPredictPlot = np.empty_like(dataset)
trainPredictPlot[:] = np.nan
trainPredictPlot = np.reshape(trainPredictPlot, (dataset.shape[0], 1))
trainPredictPlot[look_back: len(trainPredict)+look_back, :] = trainPredict

那么这里同理,一个100个数值的数值,前面70个为空,那么后面30个就由我测试集的预测值来填充。

testPredictPlot = np.empty_like(dataset)
testPredictPlot[:] = np.nan
testPredictPlot = np.reshape(testPredictPlot, (dataset.shape[0], 1))
testPredictPlot[len(trainPredict)+(look_back*2)+1: len(dataset)-1, :] = testPredict

这就是前面history的作用了,相当于是记录下来里面训练过程的一些参数变化吧。有一个很重要的就是损失,可以看到我们的损失下降很快,最后也收敛到一个很小的值,还是很不错的。

fig1 = plt.figure(figsize=(12, 8))
plt.plot(history.history['loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()

在这里插入图片描述
画图。

fig2 = plt.figure(figsize=(20, 15))
plt.plot(scaler.inverse_transform(dataset))
plt.plot(trainPredictPlot)
plt.plot(testPredictPlot)
plt.ylabel('price')
plt.xlabel('date')
plt.show()

蓝色是原始数据,黄色是训练数据训练完再进行预测的。绿色是测试数据。可以看出我们大概趋势是非常符合的。但是有些地方的峰值预测的不够。但整体效果还算不错。
在这里插入图片描述

fig3 = plt.figure(figsize=(20, 15))
plt.plot(np.arange(train_size+1, len(dataset)+1, 1), scaler.inverse_transform(dataset)[train_size:], label='dataset')
plt.plot(testPredictPlot, 'g', label='test')
plt.ylabel('price')
plt.xlabel('date')
plt.legend()
plt.show()

我们把预测的拿出来放大看看。绿色是测试的预测值,蓝色的是原始数据,和前面说的一样,趋势大概相同,但是峰值有误差。还有一个问题就是博主这里的代码是将预测值提前一天画的。因为真实预测出来会有滞后性,就看起来像是原始数据往后平移一天的缘故。但博主查阅了很多资料,暂时没发现很方便能消除lstm滞后性的办法。所以博主姑且认为测试集预测值提前一天的效果为最佳效果,这也是为什么上面代码要+1的原因。如果小伙伴们知道如何方便快捷消除lstm时间序列预测的滞后性,记得给博主留言噢。
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/126401.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 树莓派3B+ 人脸识别(OpenCV)

    树莓派3B+ 人脸识别(OpenCV)树莓派3B+人脸识别(OpenCV)相信大家都看了前面的OpenCV安装和人脸检测教程,有了基础后,现在我们正式进入重头戏——人脸识别的教程。注意:该教程面向python2.7+OpenCV2.4.9(官方源)其它版本需进行一些小的修改,文中会具体注明。1.生成人脸识别数据目录结构./data数据根目录./data/gener…

    2022年6月25日
    27
  • haproxy配置详解_核心交换机配置教程

    haproxy配置详解_核心交换机配置教程Linux Haproxy详细配置教程

    2022年4月20日
    49
  • H5标签datalist

    H5标签datalist实现输入框的搜索联想功能简介datalist标签的说明和用法说明用法效果简介有的时候前端为了更好地实现输入框input的交互效果,需要增加搜索联想功能,除了使用已经封装好的组件或者自己手写js以外,我们可以使用datalist标签更简便地去实现这个功能。datalist标签的说明和用法说明datalist标签用来定义选项列表,需要与input元素配合使用,来定义input可能的值…

    2025年6月19日
    3
  • 大数据认知作业[通俗易懂]

    大数据认知作业[通俗易懂]大数据认知实习作业目录关于作者关于大数据我对大数据的认识目前大数据应用利用大数据的实例大数据分析交通目录关于作者各位博友大家好,我是新晋小白JW,作为一名刚步入学习的小白,我会发表一些我的主观看法,望大家多多指导关于大数据大数据(bigdata),指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。具有海量的数据规模、快速的数据流转、多样的数据类型和价值密度低的四大特征。大数据的5V

    2022年6月1日
    36
  • Java字符串匹配_获取字符串

    Java字符串匹配_获取字符串文章目录一、示例二、解释1.replace()方法2.replaceAll()方法3.replaceFirst()方法4.常用的字符列表一、示例如图,都是为了替换字符串s中的”(“符号,但三种匹配方法,有三种不同的效果及写法。二、解释1.replace()方法replace()方法没有用到正则表达式,但会匹配所有的参数并进行替换2.replaceAll()方法replaceAll()方法使用的是正则表达式来匹配,而括号在正则表达式中是特殊字符,所以需要用双斜杠来进行转义,同时会匹配所..

    2022年8月21日
    6
  • Git详细教程(五):查看分支、创建分支、合并分支

    Git详细教程(五):查看分支、创建分支、合并分支一、查看分支查看的git命令如下:gitbranch:列出本地已经存在的分支,并且当前分支会用*标记gitbranch-r:查看远程版本库的分支列表gitbranch-a:查看所有分支列表(包括本地和远程,remotes/开头的表示远程分支)gitbranch-v查看一个分支的最后一次提交gitbranch–merged查看哪些分支已经合并到当前分支gitbranch–no-merged查看所有未合并工作的分支1、查看远程分支gitbr.

    2022年8月22日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号