python调用tensorflow.keras搭建长短记忆型网络(LSTM)——以预测股票收盘价为例
目录
程序简介
程序调用tensorflow.keras搭建了一个简单长短记忆型网络(LSTM),以上证指数为例,对数据进行标准化处理,输入5天的’收盘价’, ‘最高价’, ‘最低价’,’开盘价’,输出1天的’收盘价’,利用训练集训练网络后,输出测试集的MAE
长短记忆型网络(LSTM):是一种改进之后的循环神经网络,可以解决RNN无法处理长距离的依赖的问题。
程序/数据集下载
代码分析
导入模块、路径
# -*- coding: utf-8 -*- from sklearn.preprocessing import StandardScaler from tensorflow.keras.layers import Input,Dense,LSTM,GRU,BatchNormalization from tensorflow.keras.layers import PReLU from tensorflow.keras.models import Model from tensorflow.keras.optimizers import Adam from sklearn.metrics import mean_absolute_error as MAE import matplotlib.pyplot as plt import matplotlib.ticker as ticker import pandas as pd import numpy as np import os #用来正常显示中文标签 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示负号 plt.rcParams['axes.unicode_minus']=False #路径目录 baseDir = ''#当前目录 staticDir = os.path.join(baseDir,'Static')#静态文件目录 resultDir = os.path.join(baseDir,'Result')#结果文件目录
读取数据,查看5行
#读取数据 data = pd.read_csv(staticDir+'/000001.csv',encoding='gbk').iloc[-100:,:] data = data.set_index(['日期']) data.head()
股票代码 | 名称 | 收盘价 | 最高价 | 最低价 | 开盘价 | 前收盘 | 涨跌额 | 涨跌幅 | 成交量 | 成交金额 | |
---|---|---|---|---|---|---|---|---|---|---|---|
日期 | |||||||||||
2019/9/16 | '000001 | 上证指数 | 3030.7544 | 3042.9284 | 3020.0495 | 3041.9220 | 3031.2351 | -0.4807 | -0.0159 | 221878959 | 2.37E+11 |
2019/9/17 | '000001 | 上证指数 | 2978.1178 | 3023.7109 | 2970.5704 | 3023.7109 | 3030.7544 | -52.6366 | -1.7367 | 223338061 | 2.38E+11 |
2019/9/18 | '000001 | 上证指数 | 2985.6586 | 2996.4022 | 2982.4003 | 2984.0837 | 2978.1178 | 7.5408 | 0.2532 | 168046699 | 2.00E+11 |
2019/9/19 | '000001 | 上证指数 | 2999.2789 | 2999.2789 | 2975.3978 | 2992.9222 | 2985.6586 | 13.6203 | 0.4562 | 162690615 | 1.93E+11 |
2019/9/20 | '000001 | 上证指数 | 3006.4467 | 3011.3400 | 2996.1929 | 3004.8142 | 2999.2789 | 7.1678 | 0.239 | 182145302 | 2.18E+11 |
对输入输出进行标准化,查看5行
#标准化数据集 outputCol = ['收盘价']#输出列 inputCol = ['收盘价', '最高价','最低价','开盘价']#输入列 X = data[inputCol] Y = data[outputCol] xScaler = StandardScaler() yScaler = StandardScaler() X = xScaler.fit_transform(X) Y = yScaler.fit_transform(Y) X[:5,:]
array([[0.94704786, 0.91606531, 0.98497021, 1.04253169], [0.21175964, 0.65151178, 0.33108448, 0.80913257], [0.31709816, 0.2755725 , 0.48742125, 0.30125807], [0.50736208, 0.31517397, 0.39488046, 0.41453503], [0.60749011, 0.48121048, 0.66969587, 0.5669466 ]])
将数据按时间步进行整理,时间步这里设置为5天,输入为1天
#按时间步组成输入输出集 timeStep = 5#输入天数 outStep = 1#输出天数 xAll = list() yAll = list() #按时间步整理数据 输入数据尺寸是(timeStep,5) 输出尺寸是(outSize) for row in range(data.shape[0]-timeStep-outStep+1): x = X[row:row+timeStep] y = Y[row+timeStep:row+timeStep+outStep] xAll.append(x) yAll.append(y) xAll = np.array(xAll).reshape(-1,timeStep,len(inputCol)) yAll = np.array(yAll).reshape(-1,outStep) print('输入集尺寸',xAll.shape) print('输出集尺寸',yAll.shape)
输入集尺寸 (95, 5, 4) 输出集尺寸 (95, 1)
数据集分割为训练集和测试集
#分成测试集,训练集 testRate = 0.2#测试比例 splitIndex = int(xAll.shape[0]*(1-testRate)) xTrain = xAll[:splitIndex] xTest = xAll[splitIndex:] yTrain = yAll[:splitIndex] yTest = yAll[splitIndex:]
搭建一个简单的LSTM网络,结构下文会打印出来
def buildLSTM(timeStep,inputColNum,outStep,learnRate=1e-4): ''' 搭建LSTM网络,激活函数为tanh timeStep:输入时间步 inputColNum:输入列数 outStep:输出时间步 learnRate:学习率 ''' #输入层 inputLayer = Input(shape=(timeStep,inputColNum)) #中间层 middle = LSTM(100,activation='tanh')(inputLayer) middle = Dense(100,activation='tanh')(middle) #输出层 全连接 outputLayer = Dense(outStep)(middle) #建模 model = Model(inputs=inputLayer,outputs=outputLayer) optimizer = Adam(lr=learnRate) model.compile(optimizer=optimizer,loss='mse') model.summary() return model #搭建LSTM lstm = buildLSTM(timeStep=timeStep,inputColNum=len(inputCol),outStep=outStep,learnRate=1e-4)
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) (None, 5, 4) 0 _________________________________________________________________ lstm (LSTM) (None, 100) 42000 _________________________________________________________________ dense (Dense) (None, 100) 10100 _________________________________________________________________ dense_1 (Dense) (None, 1) 101 ================================================================= Total params: 52,201 Trainable params: 52,201 Non-trainable params: 0 _________________________________________________________________
利用训练集对网络进行训练
#训练网络 epochs = 1000#迭代次数 batchSize = 500#批处理量 lstm.fit(xTrain,yTrain,epochs=epochs,verbose=0,batch_size=batchSize)
对测试集进行预测,保存预测结果,查看5行
#预测 测试集对比 yPredict = lstm.predict(xTest) yPredict = yScaler.inverse_transform(yPredict)[:,0] yTest = yScaler.inverse_transform(yTest)[:,0] result = {'观测值':yTest,'预测值':yPredict} result = pd.DataFrame(result) result.index = data.index[timeStep+xTrain.shape[0]:result.shape[0]+timeStep+xTrain.shape[0]] result.to_excel(resultDir+'/预测结果.xlsx') result.head()
观测值 | 预测值 | |
---|---|---|
日期 | ||
2020/1/15 | 3090.0379 | 3119.753662 |
2020/1/16 | 3074.0814 | 3103.595947 |
2020/1/17 | 3075.4955 | 3085.278809 |
2020/1/20 | 3095.7873 | 3079.762451 |
2020/1/21 | 3052.1419 | 3094.907471 |
计算测试集MAE,进行可视化
mae = MAE(result['观测值'],result['预测值']) print('模型测试集MAE',mae) #可视化 fig,ax = plt.subplots(1,1) ax.plot(result.index,result['预测值'],label='预测值') ax.plot(result.index,result['观测值'],label='观测值') ax.set_title('LSTM预测效果,MAE:%2f'%mae) ax.legend() ax.xaxis.set_major_locator(ticker.MultipleLocator(5)) fig.savefig(resultDir+'/预测折线图.png',dpi=500)
模型测试集MAE 37.06394592927633