程序简介
程序调用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