一、简介

  上一篇中我们较为详细地铺垫了关于RNN及其变种LSTM的一些基本知识,也提到了LSTM在时间序列预测上优越的性能,本篇就将对如何利用tensorflow,在实际时间序列预测任务中搭建模型来完成任务,若你对RNN及LSTM不甚了解,请移步上一篇数据科学学习手札39;

二、数据说明及预处理

2.1 数据说明

  我们本文使用到的第一个数据来自R中自带的数据集AirPassengers,这个数据集记录了Box & Jenkins航空公司1949-1960年共144个观测值(对应每个月的国际航线乘客数),是一个经典的时间序列数据集,你可以从R中导出或去uci的网站下载;

2.2 数据预处理

  我们都知道,RNN最终经由tanh激活后输出的值位于[-1,1]内,若为分类任务则可以经由softmax进行处理,但我们这里要做的是对连续数值的预测,因此需要的输出即为tanh的输出,因此需要将原始数据进行尺度放缩,而尺度放缩的方法主要有两种,一种是极差规格化,即将原数据通过下面的公式无损地映射到[0,1]之间:

  另一种是标准化,将原数据通过下面的公式转换为均值为0,标准差为1的服从正态分布的随机变量:

我们这里选择标准化(选极差规格化也可以,读者们可以自己尝试,我懒得写了。。。);

三、模型建立及训练

数据预处理部分:

  这一部分,我们完成原始数据的导入和预处理,为了配合之后的采样过程,这里选择列表作为预处理后原始数据的储存对象:

import numpy as np
import tensorflow as tf
from tensorflow.contrib import rnn
import matplotlib.pyplot as plt
from tensorflow.contrib.learn.python.learn.estimators.estimator import SKCompat
from matplotlib import style
import pandas as pd '''读入原始数据并转为list'''
path = 'C:\\Users\\windows\\Desktop\\' data = pd.read_csv(path+'AirPassenger.csv') data = data.iloc[:,0].tolist() '''自定义数据尺度缩放函数'''
def data_processing(raw_data,scale=True):
if scale == True:
return (raw_data-np.mean(raw_data))/np.std(raw_data)#标准化
else:
return (raw_data-np.min(raw_data))/(np.max(raw_data)-np.min(raw_data))#极差规格化

数据观察部分:

  这一部分,我们需要初步观察到原数据的一些基本特性,以便确定之后的一些参数,如LSTM单元内一个时间步内的递归次数:

'''观察数据'''

'''设置绘图风格'''
style.use('ggplot') plt.plot(data)

可以看出,我们的数据集具有很明显的周期性与上升趋势,下面就基于此,对LSTM的一些基本参数进行设置;

LSTM基本参数设置:

  这里我们需要设置的参数有隐层层数,因为数据集比较简单,我们设置为1;隐层神经元个数,这里我随意设置为40个;时间步中递归次数,这里根据上面观察的结论,设置为12;训练轮数,这里也是随意设置的不宜过少,2000;训练批尺寸,这里随意设置为20,表示每一轮从训练集中抽出20组序列样本进行训练:

'''设置隐层神经元个数'''
HIDDEN_SIZE = 40
'''设置隐层层数'''
NUM_LAYERS = 1
'''设置一个时间步中折叠的递归步数'''
TIMESTEPS = 12
'''设置训练轮数'''
TRAINING_STEPS = 2000
'''设置训练批尺寸'''
BATCH_SIZE = 20

生成训练集数据:

  这里为了将原始的单变量时序数据处理成LSTM可以接受的数据类型(有X输入,有真实标签Y),我们通过自编函数,将原数据(144个)从第一个开始,依次采样长度为12的连续序列作为一个时间步内部的输入序列X,并采样其之后一期的数据作为一个Y,具体过程如下:

'''样本数据生成函数'''
def generate_data(seq):
X = []#初始化输入序列X
Y= []#初始化输出序列Y
'''生成连贯的时间序列类型样本集,每一个X内的一行对应指定步长的输入序列,Y内的每一行对应比X滞后一期的目标数值'''
for i in range(len(seq) - TIMESTEPS - 1):
X.append([seq[i:i + TIMESTEPS]])#从输入序列第一期出发,等步长连续不间断采样
Y.append([seq[i + TIMESTEPS]])#对应每个X序列的滞后一期序列值
return np.array(X, dtype=np.float32), np.array(Y, dtype=np.float32)

构造LSTM模型主体

'''定义LSTM cell组件,该组件将在训练过程中被不断更新参数'''
def LstmCell():
lstm_cell = rnn.BasicLSTMCell(HIDDEN_SIZE, state_is_tuple=True)#
return lstm_cell '''定义LSTM模型'''
def lstm_model(X, y):
'''以前面定义的LSTM cell为基础定义多层堆叠的LSTM,我们这里只有1层'''
cell = rnn.MultiRNNCell([LstmCell() for _ in range(NUM_LAYERS)]) '''将已经堆叠起的LSTM单元转化成动态的可在训练过程中更新的LSTM单元'''
output, _ = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32) '''根据预定义的每层神经元个数来生成隐层每个单元'''
output = tf.reshape(output, [-1, HIDDEN_SIZE]) '''通过无激活函数的全连接层计算线性回归,并将数据压缩成一维数组结构'''
predictions = tf.contrib.layers.fully_connected(output, 1, None) '''统一预测值与真实值的形状'''
labels = tf.reshape(y, [-1])
predictions = tf.reshape(predictions, [-1]) '''定义损失函数,这里为正常的均方误差'''
loss = tf.losses.mean_squared_error(predictions, labels) '''定义优化器各参数'''
train_op = tf.contrib.layers.optimize_loss(loss,
tf.contrib.framework.get_global_step(),
optimizer='Adagrad',
learning_rate=0.6)
'''返回预测值、损失函数及优化器'''
return predictions, loss, train_op '''载入tf中仿sklearn训练方式的模块'''
learn = tf.contrib.learn '''初始化我们的LSTM模型,并保存到工作目录下以方便进行增量学习'''
regressor = SKCompat(learn.Estimator(model_fn=lstm_model, model_dir='Models/model_2'))

训练部分:

'''对原数据进行尺度缩放'''
data = data_processing(data) '''将所有样本来作为训练样本'''
train_X, train_y = generate_data(data) '''将所有样本作为测试样本'''
test_X, test_y = generate_data(data) '''以仿sklearn的形式训练模型,这里指定了训练批尺寸和训练轮数'''
regressor.fit(train_X, train_y, batch_size=BATCH_SIZE, steps=TRAINING_STEPS)

评价部分:

  这里我们将原数据(尺度缩放之后的)feed进我们已经训练好的模型中,得到对应的预测值:

'''利用已训练好的LSTM模型,来生成对应测试集的所有预测值'''
predicted = np.array([pred for pred in regressor.predict(test_X)]) '''绘制反标准化之前的真实值与预测值对比图'''
plt.plot(predicted, label='预测值')
plt.plot(test_y, label='真实值')
plt.title('反标准化之前')
plt.legend()
plt.show()

可以看到,预测值与真实值非常的吻合,但这并不是我们需要的形式,我们需要的是反标准化后的真实数值,下面进行相关操作;

'''自定义反标准化函数'''
def scale_inv(raw_data,scale=True):
'''读入原始数据并转为list'''
path = 'C:\\Users\\windows\\Desktop\\' data = pd.read_csv(path + 'AirPassenger.csv') data = data.iloc[:, 0].tolist() if scale == True:
return raw_data*np.std(data)+np.mean(data)
else:
return raw_data*(np.max(data)-np.min(data))+np.min(data) '''绘制反标准化之前的真实值与预测值对比图'''
plt.figure()
plt.plot(scale_inv(predicted), label='预测值')
plt.plot(scale_inv(test_y), label='真实值')
plt.title('反标准化之后')
plt.legend()
plt.show()

实际使用中,若想利用已训练好的LSTM模型来预测未出现的下一期,则直接输入最后12步(这里是12步)即可得到未来的一步预测值,若想要获得更远更多期的预测值,则可以逐步将预测值积累起来,相当于用预测值当作真实发生的值进行预测,这样的坏处是越往后可能越不准,以上这个过程的完整代码如下:

import numpy as np
import tensorflow as tf
from tensorflow.contrib import rnn
import matplotlib.pyplot as plt
from tensorflow.contrib.learn.python.learn.estimators.estimator import SKCompat
from matplotlib import style
import pandas as pd '''读入原始数据并转为list'''
path = 'C:\\Users\\windows\\Desktop\\' data = pd.read_csv(path+'AirPassenger.csv') data = data.iloc[:,0].tolist() '''自定义数据尺度缩放函数'''
def data_processing(raw_data,scale=True):
if scale == True:
return (raw_data-np.mean(raw_data))/np.std(raw_data)#标准化
else:
return (raw_data-np.min(raw_data))/(np.max(raw_data)-np.min(raw_data))#极差规格化 '''观察数据''' '''设置绘图风格'''
style.use('ggplot') plt.plot(data) '''设置隐层神经元个数'''
HIDDEN_SIZE = 40
'''设置隐层层数'''
NUM_LAYERS = 1
'''设置一个时间步中折叠的递归步数'''
TIMESTEPS = 12
'''设置训练轮数'''
TRAINING_STEPS = 10000
'''设置训练批尺寸'''
BATCH_SIZE = 20 '''样本数据生成函数'''
def generate_data(seq):
X = []#初始化输入序列X
Y= []#初始化输出序列Y
'''生成连贯的时间序列类型样本集,每一个X内的一行对应指定步长的输入序列,Y内的每一行对应比X滞后一期的目标数值'''
for i in range(len(seq) - TIMESTEPS - 1):
X.append([seq[i:i + TIMESTEPS]])#从输入序列第一期出发,等步长连续不间断采样
Y.append([seq[i + TIMESTEPS]])#对应每个X序列的滞后一期序列值
return np.array(X, dtype=np.float32), np.array(Y, dtype=np.float32) '''定义LSTM cell组件,该组件将在训练过程中被不断更新参数'''
def LstmCell():
lstm_cell = rnn.BasicLSTMCell(HIDDEN_SIZE, state_is_tuple=True)#
return lstm_cell '''定义LSTM模型'''
def lstm_model(X, y):
'''以前面定义的LSTM cell为基础定义多层堆叠的LSTM,我们这里只有1层'''
cell = rnn.MultiRNNCell([LstmCell() for _ in range(NUM_LAYERS)]) '''将已经堆叠起的LSTM单元转化成动态的可在训练过程中更新的LSTM单元'''
output, _ = tf.nn.dynamic_rnn(cell, X, dtype=tf.float32) '''根据预定义的每层神经元个数来生成隐层每个单元'''
output = tf.reshape(output, [-1, HIDDEN_SIZE]) '''通过无激活函数的全连接层计算线性回归,并将数据压缩成一维数组结构'''
predictions = tf.contrib.layers.fully_connected(output, 1, None) '''统一预测值与真实值的形状'''
labels = tf.reshape(y, [-1])
predictions = tf.reshape(predictions, [-1]) '''定义损失函数,这里为正常的均方误差'''
loss = tf.losses.mean_squared_error(predictions, labels) '''定义优化器各参数'''
train_op = tf.contrib.layers.optimize_loss(loss,
tf.contrib.framework.get_global_step(),
optimizer='Adagrad',
learning_rate=0.6)
'''返回预测值、损失函数及优化器'''
return predictions, loss, train_op '''载入tf中仿sklearn训练方式的模块'''
learn = tf.contrib.learn '''初始化我们的LSTM模型,并保存到工作目录下以方便进行增量学习'''
regressor = SKCompat(learn.Estimator(model_fn=lstm_model, model_dir='Models/model_2')) '''对原数据进行尺度缩放'''
data = data_processing(data) '''将所有样本来作为训练样本'''
train_X, train_y = generate_data(data) '''将所有样本作为测试样本'''
test_X, test_y = generate_data(data) '''以仿sklearn的形式训练模型,这里指定了训练批尺寸和训练轮数'''
regressor.fit(train_X, train_y, batch_size=BATCH_SIZE, steps=TRAINING_STEPS) '''利用已训练好的LSTM模型,来生成对应测试集的所有预测值'''
predicted = np.array([pred for pred in regressor.predict(test_X)]) '''绘制反标准化之前的真实值与预测值对比图'''
plt.figure()
plt.plot(predicted, label='预测值')
plt.plot(test_y, label='真实值')
plt.title('反标准化之前')
plt.legend()
plt.show() '''自定义反标准化函数'''
def scale_inv(raw_data,scale=True):
'''读入原始数据并转为list'''
path = 'C:\\Users\\windows\\Desktop\\' data = pd.read_csv(path + 'AirPassenger.csv') data = data.iloc[:, 0].tolist() if scale == True:
return raw_data*np.std(data)+np.mean(data)
else:
return raw_data*(np.max(data)-np.min(data))+np.min(data) '''绘制反标准化之前的真实值与预测值对比图'''
plt.figure()
plt.plot(scale_inv(predicted), label='预测值')
plt.plot(scale_inv(test_y), label='真实值')
plt.title('反标准化之后')
plt.legend()
plt.show()

  以上就是本篇文章的全部内容,如有笔误或混淆不清之处,望指出。

(数据科学学习手札40)tensorflow实现LSTM时间序列预测的更多相关文章

  1. (数据科学学习手札36)tensorflow实现MLP

    一.简介 我们在前面的数据科学学习手札34中也介绍过,作为最典型的神经网络,多层感知机(MLP)结构简单且规则,并且在隐层设计的足够完善时,可以拟合任意连续函数,而除了利用前面介绍的sklearn.n ...

  2. (数据科学学习手札44)在Keras中训练多层感知机

    一.简介 Keras是有着自主的一套前端控制语法,后端基于tensorflow和theano的深度学习框架,因为其搭建神经网络简单快捷明了的语法风格,可以帮助使用者更快捷的搭建自己的神经网络,堪称深度 ...

  3. (数据科学学习手札55)利用ggthemr来美化ggplot2图像

    一.简介 R中的ggplot2是一个非常强大灵活的数据可视化包,熟悉其绘图规则后便可以自由地生成各种可视化图像,但其默认的色彩和样式在很多时候难免有些过于朴素,本文将要介绍的ggthemr包专门针对原 ...

  4. (数据科学学习手札50)基于Python的网络数据采集-selenium篇(上)

    一.简介 接着几个月之前的(数据科学学习手札31)基于Python的网络数据采集(初级篇),在那篇文章中,我们介绍了关于网络爬虫的基础知识(基本的请求库,基本的解析库,CSS,正则表达式等),在那篇文 ...

  5. (数据科学学习手札49)Scala中的模式匹配

    一.简介 Scala中的模式匹配类似Java中的switch语句,且更加稳健,本文就将针对Scala中模式匹配的一些基本实例进行介绍: 二.Scala中的模式匹配 2.1 基本格式 Scala中模式匹 ...

  6. (数据科学学习手札47)基于Python的网络数据采集实战(2)

    一.简介 马上大四了,最近在暑期实习,在数据挖掘的主业之外,也帮助同事做了很多网络数据采集的内容,接下来的数篇文章就将一一罗列出来,来续写几个月前开的这个网络数据采集实战的坑. 二.马蜂窝评论数据采集 ...

  7. (数据科学学习手札42)folium进阶内容介绍

    一.简介 在上一篇(数据科学学习手札41)中我们了解了folium的基础内容,实际上folium在地理信息可视化上的真正过人之处在于其绘制图像的高度可定制化上,本文就将基于folium官方文档中的一些 ...

  8. (数据科学学习手札32)Python中re模块的详细介绍

    一.简介 关于正则表达式,我在前一篇(数据科学学习手札31)中已经做了详细介绍,本篇将对Python中自带模块re的常用功能进行总结: re作为Python中专为正则表达式相关功能做出支持的模块,提供 ...

  9. (数据科学学习手札69)详解pandas中的map、apply、applymap、groupby、agg

    *从本篇开始所有文章的数据和代码都已上传至我的github仓库:https://github.com/CNFeffery/DataScienceStudyNotes 一.简介 pandas提供了很多方 ...

随机推荐

  1. 【Z】段错误Segment Fault定位,即core dump文件与gdb定位

    使用C++开发系统有时会出现段错误,即Segment Fault.此类错误程序直接崩溃,通常没有任何有用信息输出,很难定位bug,因而无从解决问题.今天我们介绍core dump文件,并使用gdb进行 ...

  2. React Native for Android on Windows 配置开发安装总结

    配置开发安装总结(由于当前react-native更新较快,目前是针对2015年11月底时的reacti-native android for windows版本,有些内容可能过时) 官方的安装指导在 ...

  3. PhoneGap 的消息推送插件JPush极光推送

    一. 什么是极光推送 极光推送,使得开发者可以即时地向其应用程序的用户推送通知或者消息,与用户保持互动, 从而有效地提高留存率,提升用户体验.平台提供整合了 Android 推送.iOS 推送的统一推 ...

  4. java中的泛型1

    1.泛型概述 泛型,即“参数化类型”.一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参.那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数 ...

  5. 【转】Windows Error Code(windows错误代码详解)

    本文来自: http://blog.sina.com.cn/s/blog_5e45d1be0100i0dr.html http://blog.sina.com.cn/s/blog_5e45d1be01 ...

  6. Yii 集成 PHPExcel读取Excel文件

    PHPexcel官方下载以后,放入Yii的protected\extensions\phpexcel下面 try { spl_autoload_unregister(array('YiiBase', ...

  7. SSH 与 SSL

    关于 ssh 有人已经总结得非常好了,这里推荐大家看下 阮一峰 写的 ssh原理与应用 写得简单易懂,非常赞. 关于 ssl  这里有一篇博文写得也不错,ssl协议详解 好了,那 ssh 和 ssl ...

  8. 2springboot:快速创建springboot项目

    使用IDEA快速创建springboot项目流程: 创建新的项目选择 项目的命名以及包名 需要什么包就导入什么包 进行测试的单元 <dependency> <groupId>o ...

  9. halcon 数字转字符串实现循环读取图片

    1.将字符转换为数字 tuple_number (StringImageIndex,IntImageIndex) 2.将数字转换为字符 tuple_string (IntImageIndex, '0' ...

  10. mybatis关联集合List&分布查询传递多列值

    场景:查询部门的同时,要求查询此部门下的所有用户. 部门(Department) private Integer id; private String departmentName; private ...