Python中利用LSTM模型进行时间序列预测分析的实现


Posted in Python onJuly 26, 2019

时间序列模型

时间序列预测分析就是利用过去一段时间内某事件时间的特征来预测未来一段时间内该事件的特征。这是一类相对比较复杂的预测建模问题,和回归分析模型的预测不同,时间序列模型是依赖于事件发生的先后顺序的,同样大小的值改变顺序后输入模型产生的结果是不同的。
举个栗子:根据过去两年某股票的每天的股价数据推测之后一周的股价变化;根据过去2年某店铺每周想消费人数预测下周来店消费的人数等等

RNN 和 LSTM 模型

时间序列模型最常用最强大的的工具就是递归神经网络(recurrent neural network, RNN)。相比与普通神经网络的各计算结果之间相互独立的特点,RNN的每一次隐含层的计算结果都与当前输入以及上一次的隐含层结果相关。通过这种方法,RNN的计算结果便具备了记忆之前几次结果的特点。

典型的RNN网路结构如下:

Python中利用LSTM模型进行时间序列预测分析的实现

右侧为计算时便于理解记忆而产开的结构。简单说,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模型结构如下:

Python中利用LSTM模型进行时间序列预测分析的实现

LSTM的特点就是在RNN结构以外添加了各层的阀门节点。阀门有3类:遗忘阀门(forget gate),输入阀门(input gate)和输出阀门(output gate)。这些阀门可以打开或关闭,用于将判断模型网络的记忆态(之前网络的状态)在该层输出的结果是否达到阈值从而加入到当前该层的计算中。如图中所示,阀门节点利用sigmoid函数将网络的记忆态作为输入计算;如果输出结果达到阈值则将该阀门输出与当前层的的计算结果相乘作为下一层的输入(PS:这里的相乘是在指矩阵中的逐元素相乘);如果没有达到阈值则将该输出结果遗忘掉。每一层包括阀门节点的权重都会在每一次模型反向传播训练过程中更新。更具体的LSTM的判断计算过程如下图所示:

Python中利用LSTM模型进行时间序列预测分析的实现

LSTM模型的记忆功能就是由这些阀门节点实现的。当阀门打开的时候,前面模型的训练结果就会关联到当前的模型计算,而当阀门关闭的时候之前的计算结果就不再影响当前的计算。因此,通过调节阀门的开关我们就可以实现早期序列对最终结果的影响。而当你不不希望之前结果对之后产生影响,比如自然语言处理中的开始分析新段落或新章节,那么把阀门关掉即可。(对LSTM想要更具体的了解可以戳这里)

下图具体演示了阀门是如何工作的:通过阀门控制使序列第1的输入的变量影响到了序列第4,6的的变量计算结果。

Python中利用LSTM模型进行时间序列预测分析的实现

黑色实心圆代表对该节点的计算结果输出到下一层或下一次计算;空心圆则表示该节点的计算结果没有输入到网络或者没有从上一次收到信号。

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. 原始数据转化

首先需要将时间点数据进行数值化。将具体时间转化为时间段用于表示该用户相邻两次消费的时间间隔,然后再导入模型进行训练是比较常用的手段。转化后的数据如下:

消费间隔
0
44
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转化成one-hot以后则是(关于one-hot编码可以参考这里)

1  0  0  0  0
0  0  0  0  1
...

3. 网络模型结构的确定和调整

这里我们使用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层,再多训练的时候就比较难收敛),对高级别的时间表示的学习能力越强;同时,最后会加一层普通的神经网路层用于输出结果的降维。典型结构如下:

Python中利用LSTM模型进行时间序列预测分析的实现

如果需要将多个序列进行同一个模型的训练,可以将序列分别输入到独立的LSTM模块然后输出结果合并后输入到普通层。结构如下:

Python中利用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文件,如果输入数据是来自数据库的话可以参考这里

LSTM网络结构搭建

import pandas as pd
import numpy as np
import random
from keras.models 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 = kwargs.get('output_dim', 8)
    self.activation_lstm = kwargs.get('activation_lstm', 'relu')
    self.activation_dense = kwargs.get('activation_dense', 'relu')
    self.activation_last = kwargs.get('activation_last', 'softmax')  # softmax for multiple output
    self.dense_layer = kwargs.get('dense_layer', 2)   # at least 2 layers
    self.lstm_layer = kwargs.get('lstm_layer', 2)
    self.drop_out = kwargs.get('drop_out', 0.2)
    self.nb_epoch = kwargs.get('nb_epoch', 10)
    self.batch_size = kwargs.get('batch_size', 100)
    self.loss = kwargs.get('loss', 'categorical_crossentropy')
    self.optimizer = kwargs.get('optimizer', 'rmsprop')

    def NN_model(self, trainX, trainY, testX, testY):
    """
    :param trainX: training data set
    :param trainY: expect value of training data
    :param testX: test data set
    :param testY: epect value of test data
    :return: model after training
    """
    print "Training model is LSTM network!"
    input_dim = trainX[1].shape[1]
    output_dim = trainY.shape[1] # one-hot label
    # print predefined parameters of current model:
    model = Sequential()
    # applying a LSTM layer with x dim output and y dim input. Use dropout parameter to avoid overfitting
    model.add(LSTM(output_dim=self.output_dim,
            input_dim=input_dim,
            activation=self.activation_lstm,
            dropout_U=self.drop_out,
            return_sequences=True))
    for i in range(self.lstm_layer-2):
      model.add(LSTM(output_dim=self.output_dim,
            input_dim=self.output_dim,
            activation=self.activation_lstm,
            dropout_U=self.drop_out,
            return_sequences=True))
    # argument return_sequences should be false in last lstm layer to avoid input dimension incompatibility with dense layer
    model.add(LSTM(output_dim=self.output_dim,
            input_dim=self.output_dim,
            activation=self.activation_lstm,
            dropout_U=self.drop_out))
    for i in range(self.dense_layer-1):
      model.add(Dense(output_dim=self.output_dim,
            activation=self.activation_last))
    model.add(Dense(output_dim=output_dim,
            input_dim=self.output_dim,
            activation=self.activation_last))
    # configure the learning process
    model.compile(loss=self.loss, optimizer=self.optimizer, metrics=['accuracy'])
    # train the model with fixed number of epoches
    model.fit(x=trainX, y=trainY, nb_epoch=self.nb_epoch, batch_size=self.batch_size, validation_data=(testX, testY))
    # store model to json file
    model_json = model.to_json()
    with open(model_path, "w") as json_file:
      json_file.write(model_json)
    # store model weights to hdf5 file
    if model_weight_path:
      if os.path.exists(model_weight_path):
        os.remove(model_weight_path)
      model.save_weights(model_weight_path) # eg: model_weight.h5
    return model

这里写的只涉及LSTM网络的结构搭建,至于如何把数据处理规范化成网络所需的结构以及把模型预测结果与实际值比较统计的可视化,就需要根据实际情况做调整了。具体脚本可以参考下这个

参考文档:

[力推]: Understanding LSTMs

Keras Documnet

What is batch size in neural network?

Time Series Prediction with LSTM Recurrent Neural Networks in Python with Keras

Save Your Neural Network Model to JSON

RECURRENT NEURAL NETWORKS TUTORIAL, PART 1 ? INTRODUCTION TO RNNS

A Beginner's Guide to Recurrent Networks and LSTMs

Pybrain time series prediction using LSTM recurrent nets

PyBrain Document

Recurrent neural network for predicting next value in a sequence

What are some good Python libraries that implement LSTM networks?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
举例讲解Python中is和id的用法
Apr 03 Python
Python三级菜单的实例
Sep 13 Python
Python有序字典简单实现方法示例
Sep 28 Python
python skimage 连通性区域检测方法
Jun 21 Python
浅谈Python采集网页时正则表达式匹配换行符的问题
Dec 20 Python
Django中在xadmin中集成DjangoUeditor过程详解
Jul 24 Python
python中读入二维csv格式的表格方法详解(以元组/列表形式表示)
Apr 24 Python
jenkins+python自动化测试持续集成教程
May 12 Python
python变量的作用域是什么
May 26 Python
python Scrapy框架原理解析
Jan 04 Python
Python实现视频中添加音频工具详解
Dec 06 Python
Python实现视频自动打码的示例代码
Apr 08 Python
django的model操作汇整详解
Jul 26 #Python
django的csrf实现过程详解
Jul 26 #Python
详解Python 4.0 预计推出的新功能
Jul 26 #Python
python mysql断开重连的实现方法
Jul 26 #Python
seek引发的python文件读写的问题及解决
Jul 26 #Python
python经典趣味24点游戏程序设计
Jul 26 #Python
对django后台admin下拉框进行过滤的实例
Jul 26 #Python
You might like
使用sockets:从新闻组中获取文章(二)
2006/10/09 PHP
PHP 变量定义和变量替换的方法
2009/07/30 PHP
zf框架的Filter过滤器使用示例
2014/03/13 PHP
ThinkPHP中公共函数路径和配置项路径的映射分析
2014/11/22 PHP
PHP的Laravel框架中使用消息队列queue及异步队列的方法
2016/03/21 PHP
TP5框架实现上传多张图片的方法分析
2020/03/29 PHP
PHP var关键字相关原理及使用实例解析
2020/07/11 PHP
一个用js实现控制台控件的代码
2007/09/04 Javascript
jquery调用asp.net 页面后台的实现代码
2011/04/27 Javascript
imgAreaSelect 中文文档帮助说明
2011/10/08 Javascript
Javascript 中的 call 和 apply使用介绍
2012/02/22 Javascript
在子窗口中关闭父窗口的一句代码
2013/10/21 Javascript
javascript基于prototype实现类似OOP继承的方法
2015/12/16 Javascript
Bootstrap3.0学习教程之JS折叠插件
2016/05/27 Javascript
利用jQuery实现一个简单的表格上下翻页效果
2017/03/14 Javascript
解决Vue中mounted钩子函数获取节点高度出错问题
2018/05/18 Javascript
JavaScript反射与依赖注入实例详解
2018/05/29 Javascript
vue-router两种模式区别及使用注意事项详解
2019/08/01 Javascript
微信小程序中插入激励视频广告并获取收益(实例代码)
2019/12/06 Javascript
PHP读取远程txt文档到数组并实现遍历
2020/08/25 Javascript
让Vue响应Map或Set的变化操作
2020/11/11 Javascript
python中的字典详细介绍
2014/09/18 Python
通过Python来使用七牛云存储的方法详解
2015/08/07 Python
Python实现改变与矩形橡胶的线条的颜色代码示例
2018/01/05 Python
Python中装饰器学习总结
2018/02/10 Python
Python封装成可带参数的EXE安装包实例
2019/08/24 Python
日本最大的眼镜购物网站:Oh My Glasses
2016/11/13 全球购物
Banggood官网:面向全球客户的综合商城
2017/04/19 全球购物
小学教师培训方案
2014/06/09 职场文书
药店促销活动策划方案
2014/08/24 职场文书
村党支部群众路线教育实践活动对照检查材料
2014/09/26 职场文书
习近平在党的群众路线教育实践活动总结大会上的讲话全文
2014/10/25 职场文书
2014年语文教学工作总结
2014/12/17 职场文书
高三物理教学反思
2016/02/20 职场文书
详解MySQL连接挂死的原因
2021/05/18 MySQL
Win11右下角图标点了没反应怎么办?Win11点击右下角图标无反应解决方法汇总
2022/07/07 数码科技