基于python的时间序列案例-Python中利⽤LSTM模型进⾏时间
序列预测分析
时间序列模型
时间序列预测分析就是利⽤过去⼀段时间内某事件时间的特征来预测未来⼀段时间内该事件的特征。这是⼀类相对⽐较复杂的预测建模问题,和回归分析模型的预测不同,时间序列模型是依赖于事件发⽣的先后顺序的,同样⼤⼩的值改变顺序后输⼊模型产⽣的结果是不同的。
举个栗⼦:根据过去两年某股票的每天的股价数据推测之后⼀周的股价变化;根据过去2年某店铺每周想消费⼈数预测下周来店消费的⼈数等等
RNN 和 LSTM 模型
时间序列模型最常⽤最强⼤的的⼯具就是递归神经⽹络(recurrent neural network, RNN)。相⽐与普通神经⽹络的各计算结果之间相互独⽴的特点,RNN的每⼀次隐含层的计算结果都与当前输⼊以及上⼀次的隐含层结果相关。通过这种⽅法,RNN的计算结果便具备了记忆之前⼏次结果的特点。
典型的RNN⽹路结构如下:
右侧为计算时便于理解记忆⽽产开的结构。简单说,x为输⼊层,o为输出层,s为隐含层,⽽t指第⼏次的计算;V,W,U为权重,其中计算第t次的隐含层状态时为St = f(U*Xt + W*St-1),实现当前输⼊结果与之前的计算挂钩的⽬的。对RNN想要更深⼊的了解可以戳这⾥。
RNN的局限:
由于RNN模型如果需要实现长期记忆的话需要将当前的隐含态的计算与前n次的计算挂钩,即St = f(U*Xt + W1*St-1 + W2*St-2 + ... + Wn*St-n),那样的话计算量会呈指数式增长,导致模型训练的时间⼤幅增加,因此RNN模型⼀般直接⽤来进⾏长期记忆计算。
LSTM模型
LSTM(Long Short-Term Memory)模型是⼀种RNN的变型,最早由Juergen Schmidhuber提出的。
经典的LSTM模型结构如下:
LSTM的特点就是在RNN结构以外添加了各层的阀门节点。阀门有3类:遗忘阀门(forget gate),输⼊阀门(input gate)和输出阀门(output gate)。这些阀门可以打开或关闭,⽤于将判断模型⽹络的记忆态(之前⽹络的状态)在该层输出的结果是否达到阈值从⽽加⼊到当前该层的计算中。如图中所⽰,阀门节点利⽤sigmoid函数将⽹络的记忆态作为输⼊计算;如果输出结果达到阈值则将该阀门输出与当前层的的计算结果相乘作为下⼀层的输⼊(PS:这⾥的相乘是在指矩阵中的逐元素相乘);如果
没有达到阈值则将该输出结果遗忘掉。每⼀层包括阀门节点的权重都会在每⼀次模型反向传播训练过程中更新。更具体的LSTM的判断计算过程如下图所⽰:
LSTM模型的记忆功能就是由这些阀门节点实现的。当阀门打开的时候,前⾯模型的训练结果就会关联到当前的模型计算,⽽当阀门关闭的时候之前的计算结果就不再影响当前的计算。因此,通过调节阀门的开关我们就可以实现早期序列对最终结果的影响。⽽当你不不希望之前结果对之后产⽣影响,⽐如⾃然语⾔处理中的开始分析新段落或新章节,那么把阀门关掉即可。(对LSTM想要更具体的了解可以戳这⾥)
下图具体演⽰了阀门是如何⼯作的:通过阀门控制使序列第1的输⼊的变量影响到了序列第4,6的的变
量计算结果。
⿊⾊实⼼圆代表对该节点的计算结果输出到下⼀层或下⼀次计算;空⼼圆则表⽰该节点的计算结果没有输⼊到⽹络或者没有从上⼀次收到信号。
Python中实现LSTM模型搭建
Python中有不少包可以直接调⽤来构建LSTM模型,⽐如pybrain, kears, tensorflow, cikit-neuralnetwork等(更多戳这⾥)。这⾥我们选⽤keras。(PS:如果操作系统⽤的linux或者mac,强推Tensorflow)
因为LSTM神经⽹络模型的训练可以通过调整很多参数来优化,例如activation函数,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. 原始数据转化
⾸先需要将时间点数据进⾏数值化。将具体时间转化为时间段⽤于表⽰该⽤户相邻两次消费的时间间隔,然后再导⼊模型进⾏训练是⽐较常⽤的⼿段。转化后的数据如下:
消费间隔
44
18
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转化成one-hot以后则是(关于one-hot编码可以参考这⾥)
1 0 0 0 0
0 0 0 0 1
...
3. ⽹络模型结构的确定和调整
java调用python模型这⾥我们使⽤python的keras库。(⽤java的同学可以参考下deeplearning4j这个库)。⽹络的训练过程设计到许多参数的调整:⽐如
需要确定LSTM模块的激活函数(activation fucntion)(keras中默认的是tanh);
确定接收LSTM输出的完全连接⼈⼯神经⽹络(fully-connected artificial neural network)的激活函数(keras中默认为linear);
确定每⼀层⽹络节点的舍弃率(为了防⽌过度拟合(overfit)),这⾥我们默认值设定为0.2;
确定误差的计算⽅式,这⾥我们使⽤均⽅误差(mean squared error);
确定权重参数的迭代更新⽅式,这⾥我们采⽤RMSprop算法,通常⽤于RNN⽹络。
确定模型训练的epoch和batch size(关于模型的这两个参数具体解释戳这⾥)
⼀般来说LSTM模块的层数越多(⼀般不超过3层,再多训练的时候就⽐较难收敛),对⾼级别的时间表⽰的学习能⼒越强;同时,最后会加⼀层普通的神经⽹路层⽤于输出结果的降维。典型结构如下:
如果需要将多个序列进⾏同⼀个模型的训练,可以将序列分别输⼊到独⽴的LSTM模块然后输出结果合并后输⼊到普通层。结构如下:
4. 模型训练和结果预测
将上述数据集按4:1的⽐例随机拆分为训练集和验证集,这是为了防⽌过度拟合。训练模型。然后将数据的X列作为参数导⼊模型便可得到预测值,与实际的Y值相⽐便可得到该模型的优劣。
实现代码
时间间隔序列格式化成所需的训练集格式
import pandas as pd
import numpy as np
def create_interval_dataset(dataset, look_back):
"""
:param dataset: input array of time intervals
:param look_back: each training set feature length
:return: convert an array of values into a dataset matrix.
"""
dataX, dataY = [], []
for i in range(len(dataset) - look_back):
dataX.append(dataset[i:i+look_back])
dataY.append(dataset[i+look_back])
return np.asarray(dataX), np.asarray(dataY)
df = pd.read_csv("path-to-your-time-interval-file")
dataset_init = np.asarray(df) # if only 1 column
dataX, dataY = create_interval_dataset(dataset, lookback=3) # look back if the training set sequence length
这⾥的输⼊数据来源是csv⽂件,如果输⼊数据是来⾃数据库的话可以参考这⾥
2. LSTM⽹络结构搭建
import pandas as pd
import numpy as np
import random
dels import Sequential, model_from_json
from keras.layers import Dense, LSTM, Dropout
class NeuralNetwork():
def __init__(self, **kwargs):
"""
:param **kwargs: output_dim=4: output dimension of LSTM layer; activation_lstm='tanh': activation function for LSTM layers; activation_dense='relu': activation function for Dense layer; activation_last='sigmoid': activation function for last layer; drop_out=0.2: fraction of input units to drop; np_epoch=10, the number of epoches to train the model. epoch is one forward pass and one backward pass of all the training examples; batch_size=32: number of samples per gradient update. The higher the batch size, the more memory space you'll need; loss='mean_square_error': loss function; optimizer='rmsprop'
"""
self.output_dim = ('output_dim', 8)
self.activation_lstm = ('activation_lstm', 'relu')
self.activation_dense = ('activation_dense', 'relu')
self.activation_last = ('activation_last', 'softmax') # softmax for multiple output
self.dense_layer = ('dense_layer', 2) # at least 2 layers
self.lstm_layer = ('lstm_layer', 2)
self.drop_out = ('drop_out', 0.2)
self.nb_epoch = ('nb_epoch', 10)
self.batch_size = ('batch_size', 100)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论