写点什么

使用 TensorFlow 的递归神经网络(LSTM)进行序列预测

  • 2016-07-06
  • 本文字数:4120 字

    阅读完需:约 14 分钟

本篇文章介绍使用 TensorFlow 的递归神经网络(LSTM)进行序列预测。作者在网上找到的使用 LSTM 模型的案例都是解决自然语言处理的问题,而没有一个是来预测连续值的。

所以呢,这里是基于历史观察数据进行实数序列的预测。传统的神经网络模型并不能解决这种问题,进而开发出递归神经网络模型,递归神经网络模型可以存储历史数据来预测未来的事情。

在这个例子里将预测几个函数:

  • 正弦函数:sin

  • 同时存在正弦函数和余弦函数:sin 和 cos

  • x*sin(x)

首先,建立 LSTM 模型,lstm_model,这个模型有一系列的不同时间步的 lstm 单元(cell),紧跟其后的是稠密层。

复制代码
def lstm_model(time_steps, rnn_layers, dense_layers=None):
def lstm_cells(layers):
if isinstance(layers[0], dict):
return [tf.nn.rnn_cell.DropoutWrapper(tf.nn.rnn_cell.BasicLSTMCell(layer['steps']), layer['keep_prob'])
if layer.get('keep_prob') else tf.nn.rnn_cell.BasicLSTMCell(layer['steps'])
for layer in layers]
return [tf.nn.rnn_cell.BasicLSTMCell(steps) for steps in layers]
def dnn_layers(input_layers, layers):
if layers and isinstance(layers, dict):
return skflow.ops.dnn(input_layers,
layers['layers'],
activation=layers.get('activation'),
dropout=layers.get('dropout'))
elif layers:
return skflow.ops.dnn(input_layers, layers)
else:
return input_layers
def _lstm_model(X, y):
stacked_lstm = tf.nn.rnn_cell.MultiRNNCell(lstm_cells(rnn_layers))
x_ = skflow.ops.split_squeeze(1, time_steps, X)
output, layers = tf.nn.rnn(stacked_lstm, x_, dtype=dtypes.float32)
output = dnn_layers(output[-1], dense_layers)
return skflow.models.linear_regression(output, y)
return _lstm_model

所建立的模型期望输入数据的维度与(batch size,第一个 lstm cell 的时间步长 time_step,特征数量 num_features)相关。
接下来我们按模型所能接受的数据方式来准备数据。

复制代码
def rnn_data(data, time_steps, labels=False):
"""
creates new data frame based on previous observation
* example:
l = [1, 2, 3, 4, 5]
time_steps = 2
-> labels == False [[1, 2], [2, 3], [3, 4]]
-> labels == True [2, 3, 4, 5]
"""
rnn_df = []
for i in range(len(data) - time_steps):
if labels:
try:
rnn_df.append(data.iloc[i + time_steps].as_matrix())
except AttributeError:
rnn_df.append(data.iloc[i + time_steps])
else:
data_ = data.iloc[i: i + time_steps].as_matrix()
rnn_df.append(data_ if len(data_.shape) > 1 else [[i] for i in data_])
return np.array(rnn_df)
def split_data(data, val_size=0.1, test_size=0.1):
"""
splits data to training, validation and testing parts
"""
ntest = int(round(len(data) * (1 - test_size)))
nval = int(round(len(data.iloc[:ntest]) * (1 - val_size)))
df_train, df_val, df_test = data.iloc[:nval], data.iloc[nval:ntest], data.iloc[ntest:]
return df_train, df_val, df_test
def prepare_data(data, time_steps, labels=False, val_size=0.1, test_size=0.1):
"""
Given the number of `time_steps` and some data.
prepares training, validation and test data for an lstm cell.
"""
df_train, df_val, df_test = split_data(data, val_size, test_size)
return (rnn_data(df_train, time_steps, labels=labels),
rnn_data(df_val, time_steps, labels=labels),
rnn_data(df_test, time_steps, labels=labels))
def generate_data(fct, x, time_steps, seperate=False):
"""generate data with based on a function fct"""
data = fct(x)
if not isinstance(data, pd.DataFrame):
data = pd.DataFrame(data)
train_x, val_x, test_x = prepare_data(data['a'] if seperate else data, time_steps)
train_y, val_y, test_y = prepare_data(data['b'] if seperate else data, time_steps, labels=True)
return dict(train=train_x, val=val_x, test=test_x), dict(train=train_y, val=val_y, test=test

这将会创建一个数据让模型可以查找过去 time_steps 步来预测数据。比如,LSTM 模型的第一个 cell 是 10 time_steps cell,为了做预测我们需要输入 10 个历史数据点。y 值跟我们想预测的第十个值相关。
现在创建一个基于 LSTM 模型的回归量。

复制代码
regressor = skflow.TensorFlowEstimator(model_fn=lstm_model(TIMESTEPS, RNN_LAYERS, DENSE_LAYERS),
n_classes=0,
verbose=1,
steps=TRAINING_STEPS,
optimizer='Adagrad',
learning_rate=0.03,
batch_size=BATCH_SIZE)

预测 sin 函数

复制代码
X, y = generate_data(np.sin, np.linspace(0, 100, 10000), TIMESTEPS, seperate=False)
# create a lstm instance and validation monitor
validation_monitor = skflow.monitors.ValidationMonitor(X['val'], y['val'], n_classes=0,
print_steps=PRINT_STEPS,
early_stopping_rounds=1000,
logdir=LOG_DIR)
regressor.fit(X['train'], y['train'], validation_monitor, logdir=LOG_DIR)
# > last training steps
# Step #9700, epoch #119, avg. train loss: 0.00082, avg. val loss: 0.00084
# Step #9800, epoch #120, avg. train loss: 0.00083, avg. val loss: 0.00082
# Step #9900, epoch #122, avg. train loss: 0.00082, avg. val loss: 0.00082
# Step #10000, epoch #123, avg. train loss: 0.00081, avg. val loss: 0.00081

预测测试数据

复制代码
mse = mean_squared_error(regressor.predict(X['test']), y['test'])
print ("Error: {}".format(mse))
# 0.000776

真实 sin 函数

预测 sin 函数

预测 sin 和 cos 混合函数

复制代码
def sin_cos(x):
return pd.DataFrame(dict(a=np.sin(x), b=np.cos(x)), index=x)
X, y = generate_data(sin_cos, np.linspace(0, 100, 10000), TIMESTEPS, seperate=False)
# create a lstm instance and validation monitor
validation_monitor = skflow.monitors.ValidationMonitor(X['val'], y['val'], n_classes=0,
print_steps=PRINT_STEPS,
early_stopping_rounds=1000,
logdir=LOG_DIR)
regressor.fit(X['train'], y['train'], validation_monitor, logdir=LOG_DIR)
# > last training steps
# Step #9500, epoch #117, avg. train loss: 0.00120, avg. val loss: 0.00118
# Step #9600, epoch #118, avg. train loss: 0.00121, avg. val loss: 0.00118
# Step #9700, epoch #119, avg. train loss: 0.00118, avg. val loss: 0.00118
# Step #9800, epoch #120, avg. train loss: 0.00118, avg. val loss: 0.00116
# Step #9900, epoch #122, avg. train loss: 0.00118, avg. val loss: 0.00115
# Step #10000, epoch #123, avg. train loss: 0.00117, avg. val loss: 0.00115

预测测试数据

复制代码
mse = mean_squared_error(regressor.predict(X['test']), y['test'])
print ("Error: {}".format(mse))
# 0.001144

真实的 sin_cos 函数

预测的 sin_cos 函数

预测 x*sin 函数 ```

def x_sin(x):
return x * np.sin(x)
X, y = generate_data(x_sin, np.linspace(0, 100, 10000), TIMESTEPS, seperate=False)

create a lstm instance and validation monitor

validation_monitor = skflow.monitors.ValidationMonitor(X[‘val’], y[‘val’], n_classes=0,
print_steps=PRINT_STEPS,
early_stopping_rounds=1000,
logdir=LOG_DIR)
regressor.fit(X[‘train’], y[‘train’], validation_monitor, logdir=LOG_DIR)

> last training steps

Step #32500, epoch #401, avg. train loss: 0.48248, avg. val loss: 15.98678

Step #33800, epoch #417, avg. train loss: 0.47391, avg. val loss: 15.92590

Step #35100, epoch #433, avg. train loss: 0.45570, avg. val loss: 15.77346

Step #36400, epoch #449, avg. train loss: 0.45853, avg. val loss: 15.61680

Step #37700, epoch #465, avg. train loss: 0.44212, avg. val loss: 15.48604

Step #39000, epoch #481, avg. train loss: 0.43224, avg. val loss: 15.43947

复制代码
预测测试数据

mse = mean_squared_error(regressor.predict(X[‘test’]), y[‘test’])
print (“Error: {}”.format(mse))

61.024454351

复制代码
真实的 x\*sin 函数
![](https://static001.infoq.cn/resource/image/15/c0/15117ac90c23755ac54f86d2ae723fc0.png)
预测的 x\*sin 函数
![](https://static001.infoq.cn/resource/image/a2/58/a213b516943f882848665cdf35aea858.png)
译者信息:侠天,专注于大数据、机器学习和数学相关的内容,并有个人公众号:bigdata\_ny 分享相关技术文章。
英文原文:[Sequence prediction using recurrent neural networks(LSTM) with TensorFlow](http://mourafiq.com/2016/05/15/predicting-sequences-using-rnn-in-tensorflow.html)
2016-07-06 19:0023785
用户头像

发布了 43 篇内容, 共 28.8 次阅读, 收获喜欢 7 次。

关注

评论

发布
暂无评论
发现更多内容

2021-12-15【Codeforces Round #760 (Div

爱好编程进阶

Java 程序员 后端开发

Graylog 中文手册 常用功能和问题整理

爱好编程进阶

Java 程序员 后端开发

Java stream流用法总结

爱好编程进阶

Java 程序员 后端开发

Spring Boot MyBatis配置Druid多数据源

爱好编程进阶

Java 程序员 后端开发

SpringMVC快速入门(3)默认组件加载

爱好编程进阶

Java 程序员 后端开发

一个${}引发的惨案

爱好编程进阶

Java 程序员 后端开发

【刷题第八天】11. 盛最多水的容器

白日梦

5月月更

网站开发进阶(六十三)详解CSS3中的calc()

No Silver Bullet

css3 5月月更 calc()

CRMEB 知识付费模版消息修改教程

CRMEB

JAVA生成二维码图片和解析二维码图片内容代码实例

爱好编程进阶

Java 程序员 后端开发

为什么花大本钱培训后,研发团队的表现还是很差?

高山

培训 CMMI 培训效果

【C 语言】指针 Two 之[定义指针变量、有效声明指针、使用指针、指针变量初始化]

謓泽

5月月更

Tomcat与JDK版本对应关系,Tomcat各版本特性

爱好编程进阶

Java 程序员 后端开发

【SpringBoot】6、自动配置原理【狂神篇

爱好编程进阶

Java 程序员 后端开发

【并发编程】

爱好编程进阶

Java 程序员 后端开发

【深度】阿里巴巴万级规模 K8s 集群全局高可用体系之美

爱好编程进阶

程序员 后端开发

Java对内存空间的分配与回收机制

爱好编程进阶

Java 程序员 后端开发

FLV封装格式

Loken

音视频 5月月更

反向代理 413 Request Entity Too Large 问题

HoneyMoose

Java市场饱和了?为什么都这么说?

爱好编程进阶

Java 程序员 后端开发

JSP标签

爱好编程进阶

Java 程序员 后端开发

如何备份 WordPress 数据库

海拥(haiyong.site)

WordPress 5月月更

基于SVN的CICD调研方案 _

ZuccRoger

5月月更

在Flutter中使用WillPopScope

坚果

5月月更

CDH5部署三部曲之二:部署和设置

爱好编程进阶

Java 程序员 后端开发

Java String类型和BigDecimal类型之间的转化及BigDecimal类型的介绍

爱好编程进阶

Java 程序员 后端开发

数据库连接池 -Druid 源码学习(四)

wjchenge

Druid 数据库连接池

Docker下的OpenResty三部曲之三:OpenResty加Tomcat的服务

程序员欣宸

Kubernetes openresty 5月月更

“三高”程序员谈:Mysql的“三高”集群架

爱好编程进阶

程序员 后端开发

AuthTalk | 全面拆解多租户解决方案

Authing

SaaS 多租户 Idaas

《英雄联盟》首部成人动画全球爆火

爱好编程进阶

程序员 后端开发

使用TensorFlow的递归神经网络(LSTM)进行序列预测_语言 & 开发_Mourad_InfoQ精选文章