本文主要介绍了利用Python中的LSTM模型实现时间序列预测和分析。通过示例代码进行了非常详细的介绍,对大家的学习或工作有一定的参考价值。有需要的朋友就跟着下面的边肖学习吧。
时间序列模型
时间序列预测分析是利用一个事件过去的时间特征来预测该事件未来的特征。这是一种相对复杂的预测建模问题。与回归分析模型的预测不同,时间序列模型依赖于事件发生的顺序,同样大小的值改变顺序后,输入模型产生的结果是不同的。
以栗子为例:根据一只股票近两年的每日股价数据,猜测接下来一周的股价变化;根据近两年每周想在一家店消费的人数,预测下周来店的人数等等。
RNN 和 LSTM 模型
时间序列模型最常用和最有力的工具是递归神经网络(RNN)。与普通神经网络计算结果相互独立的特点相比,RNN每一个隐层的计算结果都与当前输入和最后一个隐层结果有关。这样,RNN的计算结果具有记忆以前结果的特点。
典型的RNN网络结构如下:
右边的结构在计算时容易理解和记忆。简单来说,X是输入层,O是输出层,S是隐藏层,T是计算次数;v,W,U为权重,其中St=f(U*Xt W*St-1)在计算t时间的隐层状态时使用,从而实现当前输入结果与前一次计算相衔接的目的。想要更深入的了解RNN,可以戳这里。
RNN的局限:
如果RNN模型需要实现长时记忆,就需要将当前的隐式状态计算与之前的N次计算联系起来,即ST=F (u * xtw1 * ST-1w2 * ST-2.wn * ST-n)。那样的话,计算量会呈指数级增长,导致模型的训练时间大幅增加。因此,RNN模型一般直接用于长时记忆的计算。
LSTM模型
LSTM(长短期记忆)模型是RNN的一个变种,最早是由于尔根施密德胡伯提出的。经典的LSTM模型结构如下:
LSTM的特点是在RNN结构之外增加了每层的阀门节点。有三种类型的阀门:忘记门,输入门和输出门。这些阀门可以被打开或关闭,以判断模型网络的记忆状态(前一个网络的状态)是否达到该层中的阈值,并将其添加到该层的当前计算中。如图,阀门节点使用sigmoid函数计算网络的记忆状态作为输入;如果输出结果达到阈值,则将该值输出与当前层的计算结果相乘,作为下一层的输入(PS:这里的相乘是指手指矩阵中的逐元素相乘);如果没有达到阈值,输出结果将被遗忘。包括阀门节点在内的每一层的权重将在每次模型反向传播训练期间更新。更具体的LSTM判断计算过程如下图所示:
这些阀门节点实现了LSTM模型的记忆功能。当阀门打开时,以前模型的训练结果将与当前模型计算相关,而当阀门关闭时,以前的计算结果将不再影响当前计算。因此,我们可以通过调节阀门的开启和关闭来实现早期序列对最终结果的影响。而当你不想让前面的结果对后面的产生影响的时候,比如在自然语言处理中开始分析新的段落或者章节,就把阀门关掉。(关于LSTM更具体的了解,可以戳这里)
下图具体演示了阀门是如何工作的:通过阀门控制,第一个序列的输入变量影响第四个和第六个序列的变量计算结果。
黑色圆圈表示该节点的计算结果输出到下一层或下一次计算;空心圆表示该节点的计算结果没有输入到网络中,也没有从上一次接收到信号。
Python中实现LSTM模型搭建
Python中有相当多的包可以直接调用来构建LSTM模型,比如PyBrain、Keers、TensorFlow、Cikit-Neural Network等。(更多在此)。我们这里选择keras。(PS:如果操作系统是linux或者mac,强推Tensorflow!)
因为LSTM神经网络模型的训练可以通过调整许多参数来优化,如激活函数、LSTM层数、输入和输出的可变维数等。调整过程相当复杂。这里只举一个最简单的应用例子来描述LSTM的建造过程。
应用实例
根据某顾客在某店的历史消费时间,猜测该顾客前后会来店的时间。具体数据如下:
花费时间
2015-05-15 14:03:51
2015-05-15 15:32:46
2015-06-28 18:00:17
2015-07-16 21:27:18
2015-07-16 22:04:51
2015-09-08 14:59:56
.
.
具体操作:
1.原始数据转换
首先,我们需要将时间点数据数字化。常用的方法是将具体时间转换成时间段,以表示用户两次相邻消费的时间间隔,然后导入模型进行训练。转换后的数据如下:
消费区间
0
四十四
18
0
54
.
.
2.生成模型训练数据集(确定训练集的窗口长度)
这里的窗口是指预测下一个消费区间需要多少个消费区间。这里先用窗口长度为3,即T-2、T-1和T个消费区间来训练模型,再用t 1区间来验证结果。数据集的格式如下:X为训练数据,Y为验证数据。
PS:这里说是不太合适,因为窗口长度需要根据模型验证结果进行调整。
X1 X2 X3 Y
0 44 18 0
44 18 0 54
.
.
注意:一般情况下,直接预测的准确性较差。最好把预测值Y按照数值bin分成几类,然后转换成one-hot标签进行训练。例如,如果将y按数值范围分为五类(1: 0-20,2: 20-40,3: 40-60,4: 60-80,5: 80-100),则上述公式可转化为:
X1 X2 X3 Y
0 44 18 0
44 18 0 4
.
y转换成一键编码后,就是(参考这里的一键编码)
1 0 0 0 0
0 0 0 0 1
.
3.网络模型结构的确定和调整。
这里我们使用python的keras库。(使用java的同学可以参考deeplearning4j的库)。网络的训练过程被设计成调整许多参数:例如
需要确定LSTM模块的激活函数(tanh);在keras中是默认值);
确定全连接人工神经网络(线性)的激活函数;默认情况下在keras中)接收LSTM输出;
为了确定各层网络节点的拒绝率(为了防止过拟合),这里我们的默认值设为0.2;
确定误差的计算方法,这里我们用均方差;
确定权重参数的迭代更新方法。这里,我们使用的是RNN网络中常用的RMSprop算法。确定模型训练的历元和批量(关于模型的这两个参数的具体解释,请点击这里)
一般来说,LSTM模块层数越多(一般不超过3层,训练越多越难收敛),高级时间表征的学习能力越强;同时,最后会增加一个普通的神经网络层来降低输出结果的维数。典型结构如下:
如果需要在同一个模型中训练多个序列,可以将序列分别输入到独立的LSTM模块中,然后将输出结果组合输入到公共层中。其结构如下:
4.模型训练和结果预测
上述数据集按照4:1的比例随机分为训练集和验证集,防止过拟合。培训模式。然后将数据的X列作为参数导入到模型中就可以得到预测值,通过与实际的Y值对比就可以得到模型的优劣。
实现代码
时间间隔序列被格式化成所需的训练集格式。
进口熊猫作为pd
将numpy作为np导入
def create_interval_dataset(数据集,回看):
'''
:参数数据集:时间间隔的输入数组
:param look_back:每个训练集特征长度
:return:将值数组转换为数据集矩阵。
'''
dataX,dataY=[],[]
对于范围内的I(len(dataset)-look _ back):
dataX.append(数据集[i:i look_back])
数据追加(数据集[我回头看])
返回np.asarray(dataX)
df=pd.read_csv('您的时间间隔文件的路径)
dataset_init=np.asarray(df) #如果只有一列
dataX,dataY=create _ interval _ dataset(dataset,lookback=3) #如果训练集序列长度
这里的输入数据来源是战斗支援车文件,如果输入数据是来自数据库的话可以参考这里
LSTM网络结构搭建
进口熊猫作为螺纹中径
将numpy作为铭牌导入
随机导入
从keras.models导入序列,模型_自_json
从喀拉斯。层进口密集、LSTM、辍学
类神经网络():
def __init__(self,**kwargs):
'''
:param * * kwargs:output _ dim=4:LSTM层的输出维度;activation _ lstm=' tanh ':LSTM层的激活函数;activation_dense='relu ':密集层的激活函数;activation_last='sigmoid ':最后一层的激活函数;drop_out=0.2:要丢弃的输入单位的分数;np_epoch=10,训练模型的世数。历元是所有训练样本的一个向前传递和一个向后传递;批处理大小=32:每次梯度更新的样本数。批量越大,你需要的内存空间就越大;loss='均方误差':损失函数;optimizer='rmsprop '
'''
自我。output _ dim=kwargs。get(' output _ dim ',8)
自我。activation _ lstm=kwargs。get(' activation _ lstm ',' relu ')
自我。activation _ dense=kwargs。get(' activation _ dense ',' relu ')
自我。activation _ last=kwargs。get(' activation _ last ',' softmax') # softmax用于多输出
自我。dense _ layer=kwargs。get(' dense _ layer ',2) #至少2层
自我。lstm _ layer=kwargs。get(' lstm _ layer ',2)
自我。drop _ out=kwargs。get(' drop _ out ',0.2)
自我。nb _ epoch=kwargs。get(' nb _ epoch ',10)
自我。batch _ size=kwargs。get(' batch _ size ',100)
self.loss=kwargs.get('loss ',' categorical _ crossentropy ')
自我。optimizer=kwargs。get('优化器',' rmsprop ')
def NN_model(self,trainX,trainY,testX,testY):
'''
:参数trainX:训练数据集
:参数培训:训练数据的期望值
:参数测试x:测试数据集
:参数测试:测试数据的epect值
:返回:培训后的模型
'''
打印"培训模式是LSTM网络!"
input_dim=trainX[1].形状[1]
output _ dim=trany。形状[1]#一次成型标签
#打印当前模型的预定义参数:
模型=顺序()
#应用具有x维度输出和y维度输入的LSTM图层。使用拒绝传统社会的人参数以避免过度拟合
模型。添加(LSTM(output _ dim=self。输出_尺寸
输入尺寸=输入尺寸,
激活=自我。激活_ lstm,
dropout_U=self.drop_out,
return_sequences=True))
对于范围内的我(自我。lstm _ layer-2):
模型。添加(LSTM(output _ dim=self。输出_尺寸
输入_尺寸=自身。输出_尺寸,
激活=自我。激活_ lstm,
dropout_U=self.drop_out,
return_sequences=True))
#参数返回序列在最后一个lstm层中应为假的,以避免输入维度与密集层不兼容
模型。添加(LSTM(output _ dim=self。输出_尺寸
输入_尺寸=自身。输出_尺寸,
激活=自我。激活_ lstm,
dropout_U=self.drop_out))
对于范围内的我(自密集层-1):
模型。add(Dense(output _ dim=self。输出_尺寸,
激活=自我。activation _ last))
模型。add(Dense(output _ dim=output _ dim,
输入_尺寸=自身。输出_尺寸,
激活=自我。activation _ last))
#配置学习过程
model.compile(loss=self.loss,optimizer=self.optimizer,metrics=['accuracy'])
#用固定数量的缓存训练模型
model.fit(x=trainX,y=trainY,nb_epoch=self.nb_epoch,batch_size=self.batch_size,validation_data=(testX,testY))
#将模型存储到json文件
model_json=model.to_json()
用打开(模型路径,' w ')作为json_file:
json_file.write(模型_json)
#将模型权重存储到hdf5文件
如果型号_重量_路径:
如果os.path。存在(型号_重量_路径):
os.remove(型号_重量_路径)
模型。保存重量(模型重量路径)#例如:model_weight.h5
回报模型
这里写的只涉及LSTM网络的结构搭建,至于如何把数据处理规范化成网络所需的结构以及把模型预测结果与实际值比较统计的可视化,就需要根据实际情况做调整了。具体脚本可以参考下这个
参考文档:
[力推]:了解LSTMs
Keras Documnet
什么是神经网络中的批量大小?
基于LSTM递归神经网络的时间序列预测
将您的神经网络模型保存到JSON
递归神经网络教程,第一部分——递归神经网络简介
循环网络和LSTMs初学者指南
基于LSTM递归网络的大脑时间序列预测
大脑文档
预测序列中下一个值的递归神经网络
有哪些好的实现LSTM网络的计算机编程语言库?
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。