赞
踩
LSTM是一种循环神经网络(RNN),可学习时间步长序列和数据之间的长期依赖关系,与CNN不同,LSTM可以记住预测之间的网络状态。
LSTM适用于序列和时序数据分类,此时必须基于记忆的数据点序列进行网络预测或输出。股票是随着时间变化的,恰好可以用LSTM。
#导入相关库文件
import numpy as np
import pandas as pd
import math
import sklearn
import sklearn.preprocessing
import datetime
import os
import matplotlib.pyplot as plt
import tensorflow as tf
oss_getenv()用于获取环境变量的值(存在),否则返回默认值
环境变量获取,或者把诸如“<你的Access_Key_Id>”替换成真实的AccessKeyId等。
access_key_id = os.getenv(‘OSS_TEST_ACCESS_KEY_ID’, ‘你的ACCESS_KEY_ID’) access_key_secret = os.getenv(‘OSS_TEST_ACCESS_KEY_SECRET’, ‘你KEY_SECRET’) bucket_name = os.getenv(‘OSS_TEST_BUCKET’, ‘你的bucket name’)
#准备数据,从oss2文件中下载并解压
import oss2
access_key_id = os.getenv('OSS_TEST_ACCESS_KEY_ID','LTAI4G1MuHTUeNrKdQEPnbph')
access_key_secret = os.getenv('OSS_TEST_ACCESS_KEY_SECRET','m1ILSoVqcPUxFFDqer4tKDxDkoP1ji')
bucket_name = os.getenv('OSS_TEST_BUCKET','mldemo')
endpoint = os.getenv('OSS_TEST_ENDPOINT','https://oss-cn-shanghai.aliyuncs.com')
#创建Bucket对象,所有Object相关接口都可以通过BUcket对象来进行
bucket = oss2.Bucket(oss2.Auth(access_key_id,access_key_secret),endpoint,bucket_name)
#下载到本地文件
#下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
#<yourLocalFile>由本地文件路径加文件名包括后缀组成,例如/users/local/myfile.txt。
#<yourObjectName>表示下载的OSS文件的完整名称,即包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
#bucket.get_object_to_file('<yourObjectName>', '<yourLocalFile>')
bucket.get_object_to_file('data/c12/stock_data.zip','stock_data.zip')
unzip命令常用参数
-l:显示压缩文件内所包含的文件;
-t:检查压缩文件是否正确;
-o:不必先询问用户,unzip执行后覆盖原有的文件;
·-n:解压缩时不要覆盖原有的文件;
#-q:执行时不显示任何信息;
#-d<目录>:指定文件解压缩后所要存储的目录;
压缩文件夹里边的 __MACOSX是缓存文件,可以直接删除掉
Mac在压缩文件时会往里面写入MetaData,这样做的目的是为了方便其他的Mac用户使用,就想Windows会在图片目录中加入的Thumbs.db,以方便显示预览图一样
#这些MetaData产生的文件就是 __MACOSX,本身这些文件在Mac上是隐藏属性的,也确实方便了Mac用户
#但在Windows中 __MACOSX就成了“缓存文件”或垃圾文件,只有在Windows系统才能看到,Mac不可见
#所以,当我们打开压缩文件的时候,如果出现 __MACOSX,直接删除即可,不会对你的文件有任何影响
#解压数据
#-o:不必先询问用户,unzip执行后覆盖原有的文件;
#-q:执行时不显示任何信息;
!unzip -o -q stock_data.zip
#rm -rf * 删除当前目录下的所有文件
!rm -rf __MACOSX
#ls 命令将每个由 Directory 参数指定的目录或者每个由 File 参数指定的名称写到标准输出,以及您所要求的和标志一起的其它信息。
#这里表示每个由 stock_data参数指定的名称写到标准输出
#-ilht主文件关联
!ls stock_data -ilht
主要介绍数据集各列的数据类型,是否为空值,内存占用情况;
#pandas在读取csv文件时,不会去管原来的csv中是否存在index,而在于在读取的时候是否有设置index。
#如果读取的时候不设置index,那么系统会默认生成自然序列的index,
#如果读取时,给系统#####指定index,那么生成的dataframe的index就是是指定的,
#但是这里有个问题就是,这里指定的index只能是指定已经存在的列的序号或者列名,以读取test.csv这个文件所示:
df = pd.read_csv("./stock_data/sh300index.csv",index_col = 0)
#df.info():主要介绍数据集各列的数据类型,是否为空值,内存占用情况;
df.info()
运行结果
#Pandas读取数据之后使用pandas的head()函数的时候,来观察一下读取的数据,head函数只读取前5行的数据
df.head()
运行结果:
#数据的分布情况:df.describe(): 主要介绍数据集各列的数据统计情况(最大值、最小值、标准偏差、分位数等等)。
df.describe()
运行结果:
plt.figure(figsize=(15,5));#figsize=(15,5)表示figure 的大小为宽、长(单位为inch plt.subplot(2,1,1);#subplot(2,1,1)指的是在一个2行1列共2个子图的图中,定位第1个图来进行操作。最后的数字就是表示第几个子图,此数字的变化来定位不同的子图。 plt.plot(df.open.values,color='red',label='open')#红色曲线绘制开盘价变化情况 plt.plot(df.close.values,color='green',label='close')#绿色曲线绘制收盘价变化情况 plt.plot(df.low.values,color='blue',label='low')#蓝色曲线表示最低价变化情况 plt.plot(df.high.values,color='black',label='high')#黑色曲线绘制最高价变化情况 plt.title('stock price') plt.xlabel('time [days]') plt.ylabel('price') #上面参数loc表示location哦,代表标签所放置的位置哦,下面的loc=’best’的意思就是图形你自己看着办吧,放到合适的位置就行啦, plt.legend(loc = 'best') plt.subplot(2,1,2)#定位第2个子图 plt.plot(df.vol.values,color='black',label='volume') plt.title('stock volume') plt.xlabel('time [days]') plt.ylabel('volume') plt.legend(loc = 'best') plt.show()
运行结果:
图中上面的图为股票的四个指标随时间变化的走势曲线图,下面的图为股票交易量随时间变化的走势图,可以看出,当股票价格下跌的时候,股票的交易量有所下降。
按照80%数据集,10%划分验证集,10%测试集对数据集进行划分。
#按照80%10%10%划分数据集。验证集,测试集
valid_set_size_percentage = 10#百分之十的验证集
test_set_size_percentage = 10#百分之十的次测试集
#min-max归一化,将开盘价,收盘价,最高价,最低价归一化
def normalize_data(df):
min_max_scaler = sklearn.preprocessing.MinMaxScaler()#调用sklearn的最小最大值归一化函数MinMaxScaler()
df['open'] = min_max_scaler.fit_transform(df.open.values.reshape(-1,1))#reshape(-1,1)表示将数据转换成1列
df['high'] = min_max_scaler.fit_transform(df.high.values.reshape(-1,1))#然后再进行归一化
df['low'] = min_max_scaler.fit_transform(df.low.values.reshape(-1,1))
df['high'] = min_max_scaler.fit_transform(df['close'].values.reshape(-1,1))
return df#将归一化的结果返回给df
#划分数据集 def load_data(stock,seq_len): data_raw = stock.to_numpy()#将stock的数据转换成numpy的array的数据,然后依次做数据切切分与读取 data = [] #create all possible sequences of Length seq_len for index in range(len(data_raw)-seq_len): data.append(data_raw[index: index+seq_len]) data = np.array(data); valid_set_size = int(np.round(valid_set_size_percentage/100*data.shape[0]));#验证集的数据大小=数据集的行数*10% test_set_size = int(np.round(test_set_size_percentage/100*data.shape[0])); train_set_size = data.shape[0] - (valid_set_size + test_set_size); #将三部分数据按照x和y依次切分 x_train = data[:train_set_size,:-1,:] y_train = data[:train_set_size,-1,:] x_valid = data[train_set_size:train_set_size+valid_set_size,:-1,:] y_valid = data[train_set_size:train_set_size+valid_set_size,-1,:] x_test = data[train_set_size+valid_set_size:,:-1,:] y_test = data[train_set_size+valid_set_size:,-1,:] return [x_train,y_train,x_valid,y_valid,x_test,y_test]
#去除冗余,即将原始数据列表中不需要的指标删除 df_stock = df.copy() df_stock.drop(['vol'],1,inplace=True) df_stock.drop(['lastclose'],1,inplace=True) df_stock.drop(['label'],1,inplace=True) df_stock.drop(['ZTM:ma5'],1,inplace=True) df_stock.drop(['ZTM:ma7'],1,inplace=True) df_stock.drop(['ZTM:ma10'],1,inplace=True) df_stock.drop(['ZTM:ma21'],1,inplace=True) df_stock.drop(['holdingvol'],1,inplace=True) df_stock.drop(['ZTM:MACD'],1,inplace=True) df_stock.drop(['ZTM:RSI'],1,inplace=True) #使用pandas的head函数查看输入数据(前5行) #将训练集的四个指标作为训练数据 df_stock.head()
运行结果:
df_stock_norm = normalize_data(df_stock)#调用normalize_data对df_stock归一化
#查看训练集,验证集和测试集情况
seq_len = 20 #设置最长序列长度
x_train, y_train, x_valid,y_valid,x_test,y_test = load_data(df_stock_norm,seq_len)#seq_len是我们加窗一次去的数据
print('x_train.shape =',x_train.shape)#经过处理,训练数据集是5207条,所以它的数据就是0~19,维度是4(因为有四个数据,开盘价,收盘价,最高价和最低价)
print('y_train.shape =',y_train.shape)
print('x_valid.shape =',x_valid.shape)#验证数据是651条,
print('y_valid.shape =',y_valid.shape)
print('x_test.shape =',x_test.shape)#测试数据是651条
print('y_test.shape =',y_test.shape)
运行结果:
#对指标数据可视化
plt.figure(figsize=(15, 6));
plt.plot(df_stock_norm.open.values,color='red',label='open')
plt.plot(df_stock_norm.close.values,color='green',label='close')
plt.plot(df_stock_norm.low.values,color='blue',label='low')
plt.plot(df_stock_norm.high.values,color='black',label='high')
plt.title('stock')
plt.xlabel('time [days]')
plt.ylabel('normalized price/volume')
plt.legend(loc='best')
plt.show()
运行结果:
#对训练数据随机化处理 index_in_epoch = 0; perm_array = np.arange(x_train.shape[0]) np.random.shuffle(perm_array)#shuffle将数据打乱 #数据读取方法 def get_next_batch(batch_size):#从数据里边随机抽取batch_size的数量 global index_in_epoch,x_train,perm_array start = index_in_epoch index_in_epoch += batch_size if index_in_epoch > x_train.shape[0]: np.random.shuffle(perm_array) start = 0 index_in_epoch = batch_size end = index_in_epoch return x_train[perm_array[start:end]],y_train[perm_array[start:end]]#从x_train,y_train分别读取训练数据和标签
#定义超参 n_steps = seq_len-1# #输入大小(与指标数量对应) n_inputs = 4 #输入指标的数量 n_neurons =200 #循环神经网络有多少个神经元 #输出大小(与指标数量对应) n_outputs = 4#输出指标的数量 #层数 n_layers = 2 #学习率 learning_rate =0.001 #批大小 batch_size = 50 #迭代训练次数 n_epochs = 20 #训练集大小 train_set_size = x_train.shape[0]#获取训练集的大小即训练数据的行数 #测试集大小 test_set_size = x_test.shape[0]
#用的tensorflow定义网络的结构 tf.reset_default_graph() X = tf.placeholder(tf.float32, [None, n_steps, n_inputs])#用tf.placeholder定义了输入x和输出y y = tf.placeholder(tf.float32, [None, n_outputs]) # 使用GRU单元结构 layers = [tf.contrib.rnn.GRUCell(num_units=n_neurons, activation=tf.nn.leaky_relu)#使用GRUCell定义了两层的神经网络 for layer in range(n_layers)] multi_layer_cell = tf.contrib.rnn.MultiRNNCell(layers)#将定义好的神经网络放在MultiRNNCell,构造一个多层的cell rnn_outputs, states = tf.nn.dynamic_rnn(multi_layer_cell, X, dtype=tf.float32)#将multi_layer_cell放到dynamic_rnn里面构成一个循环神经网络 stacked_rnn_outputs = tf.reshape(rnn_outputs, [-1, n_neurons]) stacked_outputs = tf.layers.dense(stacked_rnn_outputs, n_outputs) outputs = tf.reshape(stacked_outputs, [-1, n_steps, n_outputs])#将循环神经网络的输出reshape成我们需要的大小 outputs = outputs[:,n_steps-1,:] # 定义输出 #将预测与实际结果求均方误差损失 loss = tf.reduce_mean(tf.square(outputs - y)) # 使用MSE作为损失 optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) #采用Adam优化方法 training_op = optimizer.minimize(loss)#最小化loss值
# 执行训练 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for iteration in range(int(n_epochs*train_set_size/batch_size)): x_batch, y_batch = get_next_batch(batch_size) # fetch the next training batch sess.run(training_op, feed_dict={X: x_batch, y: y_batch}) #依次运行training_op if iteration % int(5*train_set_size/batch_size) == 0:#获取最小化的损失,每隔(5*train_set_size/batch_size)步就print一次MSE的值 mse_train = loss.eval(feed_dict={X: x_train, y: y_train}) mse_valid = loss.eval(feed_dict={X: x_valid, y: y_valid}) print('%.2f epochs: MSE train/valid = %.6f/%.6f'%( iteration*batch_size/train_set_size, mse_train, mse_valid)) y_train_pred = sess.run(outputs, feed_dict={X: x_train})#将训练集进行预测 y_valid_pred = sess.run(outputs, feed_dict={X: x_valid})#将验证集进行预测 y_test_pred = sess.run(outputs, feed_dict={X: x_test})#将测试集进行预测
运行结果:
可以看出训练集的均方误差损失已经减少到了0.000032,验证集的均方误差已经减少到了0.000022.
ft = 0 # 0 = open, 1 = close, 2 = highest, 3 = lowest #结果可视化 plt.figure(figsize=(15, 5)); plt.subplot(1,2,1); #测试数据可视化 plt.plot(np.arange(y_train.shape[0]), y_train[:,ft], color='blue', label='train target') plt.plot(np.arange(y_train.shape[0], y_train.shape[0]+y_valid.shape[0]), y_valid[:,ft], color='gray', label='valid target') plt.plot(np.arange(y_train.shape[0]+y_valid.shape[0], y_train.shape[0]+y_test.shape[0]+y_test.shape[0]), y_test[:,ft], color='black', label='test target') plt.plot(np.arange(y_train_pred.shape[0]),y_train_pred[:,ft], color='red', label='train prediction') #验证集数据可视化 plt.plot(np.arange(y_train_pred.shape[0], y_train_pred.shape[0]+y_valid_pred.shape[0]), y_valid_pred[:,ft], color='orange', label='valid prediction') #将测试集的预测结果可视化,看测试结果与我们实际结果存在多大的误差 plt.plot(np.arange(y_train_pred.shape[0]+y_valid_pred.shape[0], y_train_pred.shape[0]+y_valid_pred.shape[0]+y_test_pred.shape[0]), y_test_pred[:,ft], color='green', label='test prediction') plt.title('past and future stock prices') plt.xlabel('time [days]') plt.ylabel('normalized price') plt.legend(loc='best'); plt.subplot(1,2,2); plt.plot(np.arange(y_train.shape[0], y_train.shape[0]+y_test.shape[0]), y_test[:,ft], color='black', label='test target') plt.plot(np.arange(y_train_pred.shape[0], y_train_pred.shape[0]+y_test_pred.shape[0]), y_test_pred[:,ft], color='green', label='test prediction') plt.title('future stock prices') plt.xlabel('time [days]') plt.ylabel('normalized price') plt.legend(loc='best');
左图:红色曲线是训练集的预测结果,橙色是验证集的预测结果,绿色是测试集的预测结果,右图显示的是测试集的预测结果与真实值之间的拟合关系,我们可以看到拟合效果是非常好的。
https://download.csdn.net/download/fencecat/85104287
本实验使用tensorflow环境为1.14,如果安装的是tensorflow2.0版本会报错。
原文链接:https://blog.csdn.net/fencecat/article/details/124072324?spm=1001.2014.3001.5501
LeNet5股票预测文末的混淆矩阵实现模型精度可视化:
#混淆矩阵绘制 def plot_confusion_matrix(cm, labels_name, title): cm = cm.astype(np.float64) if(cm.sum(axis=0)[0]!=0): cm[:,0] = cm[:,0] / cm.sum(axis=0)[0] # 归一化 if(cm.sum(axis=0)[1]!=0): cm[:,1] = cm[:,1] / cm.sum(axis=0)[1] # 归一化 plt.imshow(cm, interpolation='nearest') # 在特定的窗口上显示图像 plt.title(title) # 图像标题 plt.colorbar() num_local = np.array(range(len(labels_name))) plt.xticks(num_local, labels_name) # 将标签印在x轴坐标上 plt.yticks(num_local, labels_name) # 将标签印在y轴坐标上 plt.ylabel('True label') plt.xlabel('Predicted label') cm=confusion_matrix(t,pre) y_true = np.array(list(map(int,t))) y_scores = np.array(list(map(int,pre))) roc=str(roc_auc_score(y_true, y_scores)) precision, recall, _thresholds = precision_recall_curve(y_true, y_scores) pr =str(auc(recall, precision)) title="ROC AUC:"+roc+"\n"+"PR AUC:"+pr labels_name=["0.0","1.0"] plot_confusion_matrix(cm, labels_name, title) for x in range(len(cm)): for y in range(len(cm[0])): plt.text(y,x,cm[x][y],color='white',fontsize=10, va='center') plt.show()
可视化结果:
可以看到实验准确率为68.9%,并不是很好,可以通过调整网络结构优化模型来提高准确度。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。