通过5个简单序列预测实例学习LSTM递归神经网络
序列预测不同于传统的分类和回归问题。
它要求你考虑观测的顺序,并且使用像长短期记忆(LSTM)递归神经网络这样有记忆性的,并且可以学习观测之间时间依赖性的模型。
通过在实践中应用LSTM来学习如何在序列预测问题上使用LSTM是至关重要的,因此,你需要一套定义明确的问题,让你专注于不同的问题类型和结构。这种学习方法的重要性在于这样你可以建立以下直觉:序列预测问题是如何不同于其他问题,并且如何利用复杂模型像LSTMs来解决这类问题。
在本教程中,你将学习一组5个狭义的可扩展序列预测问题,你可以使用这些问题来应用和学习更多关于长短期记忆(LSTM)递归神经网络的知识。
完成本教程后,你将知道:
- 用简单的记忆任务来测试训练好的长短期记忆网络(LSTM)的记忆能力。
- 用简单的回显任务来测试训练好的长短期记忆网络(LSTM)的学习时间依赖性能力。
- 用简单的算术任务来测试长短期记忆网络(LSTM)的解释能力。
让我们开始吧。
教程概述
本教程分为5个部分; 他们是:
- 序列学习问题
- 价值记忆
- 回显随机整数
- 回显随机子序列
- 序列分类
问题的特点
序列问题在设计时考虑了以下特点:
- 专注性:专注于序列预测的一个方面,如记忆或函数逼近。
- 可扩展性:在所选定的关注点上难度几乎相同。
- 重构性:对于每个问题提出多种解决的设计方案,来促进探索不同的算法的学习能力。
我会尝试提供一个专注的,有一定难度的和需要网络架构的混合结构的问题。
如果您对我的想法有进一步的扩展或类似精心设计的问题,请在下面的评论中告诉我。
1.序列学习问题
在本问题中,生成一个0.0到1.0之间的连续实数值序列。给定一个或多个时间步长的过去值,模型必须预测序列中的下一个值。
我们可以直接生成这个序列,如下所示:
from numpy import array
# generate a sequence of real values between 0 and 1.//生成一个0.0到1.0之间的连续实数值序列
def generate_sequence(length=10):
return array([i/float(length) for i in range(length)])
print(generate_sequence())
运行示例代码生成的序列:
[ 0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
这可以被认为是一个记忆性的挑战,如果给定前一个时间的观测,模型必须预测下一个值:
X (samples//例子), y
0.0, 0.1
0.1, 0.2
0.2, 0.3
...
网络可以记忆输入输出对,这是很无聊的,但这会展现网络的函数逼近能力。
这个问题可以被定义为将随机选择的连续子列作为输入时间步长,并且将序列中的下一个值作为输出。
X (timesteps//时间步长), y
0.4, 0.5, 0.6, 0.7
0.0, 0.2, 0.3, 0.4
0.3, 0.4, 0.5, 0.6
...
这将要求网络学习要么在最后一个观测后自己添加一个修正值要么记住此问题的所有可能的子序列。
这个设计将被建模为多对一的序列预测问题。
这是测试序列学习的原始特征的一个简单问题。这个问题可以通过多层感知网络来解决。
2.价值记忆
问题是记住序列中的第一个值,并在序列的末尾重复。
这个问题是基于1997年论文Long Short Term Memory中用来演示长短期网络(LSTM)的“实验2” 。
这可以被定义为单步预测问题。
给定序列中的一个值,模型必须预测序列中的下一个值。例如,给定值“0”作为输入,模型必须预测值“1”。
考虑以下两个5整数的序列:
3, 0, 1, 2, 3
4, 0, 1, 2, 4
Python代码将生成两个任意长度的序列。如果你愿意,你可以进一步推广。
def generate_sequence(length=5):
return [i for i in range(length)]
# sequence 1//序列1
seq1 = generate_sequence()
seq1[0] = seq1[-1] = seq1[-2]
print(seq1)
# sequence 2//序列2
seq1 = generate_sequence()
seq1[0] = seq1[-1]
print(seq1)
运行示例代码生成并打印上面的两个序列。
[3, 1, 2, 3, 3]
[4, 1, 2, 3, 4]
整数可以被归一化,或者更好地进行一位有效编码。
这些方法导致了一个皱纹,因为这两个序列之间存在冲突的信息,因此模型必须知道每个一步预测的上下文(例如,它当前预测的序列)来正确地预测每个完整序列。
我们可以看到序列的第一个值不断地被重复作为序列的最后一个值。这是为模型提供上下文的指示器,指明它正在处理哪个序列。
冲突是由每个序列的倒数第二项到最后一项的转换所导致的。在序列1中,给出“2”作为输入,模型必须预测“3”,而在序列2中给出“2”作为输入模型却必须预测“4”。
Sequence 1:
X (samples), y
...
1, 2
2, 3
Sequence 2:
X (samples), y
...
1, 2
2, 4
这种皱纹很重要,它能有效防止模型记忆每个序列中的每个单步输入 - 输出值对,因为一个不考虑序列差异性的模型可能倾向于这样做。
这个设计将被建模为一对一的序列预测问题。
这是一个多层感知器和其他非递归神经网络无法学习的问题。序列中的第一个值必须记录在多个样本中。
这个问题可以被定义为提供除了最后一个值以外的整个序列,并将它们作为输入时间步长,最后预测序列的最后一个值。
X (timesteps), y
3, 0, 1, 2, 3
4, 0, 1, 2, 4
每个时间步长都将展现给网络,但网络必须记住在第一步值。不同之处在于,网络能够通过反向传播算法,更好地了解序列之间,长序列之间的差异。
这个问题的设计将被建模为多对一的序列预测问题。
此外,这个问题不能被多层感知器学习。
3.回声随机整数
在此问题中,生成随机的整数序列。该模型必须记住一个特定滞后时间的整数,并在该序列的末尾回显该整数。
例如,10个整数的随机序列可以是:
5, 3, 2, 1, 9, 9, 2, 7, 1, 6
这个问题可能被定义为在回显第5个时间步中的值,在这种情况下为9。
下面的代码将生成随机整数序列。
from random import randint
# generate a sequence of random numbers in [0, 99]//生成0到99之间的随机数
def generate_sequence(length=10):
return [randint(0, 99) for _ in range(length)]
print(generate_sequence())
运行该示例将生成并打印一个随机序列,例如:
[47, 69, 76, 9, 71, 87, 8, 16, 32, 81]
整数可以被归一化,但是更好的方法是进行一位有效编码。
这个问题的简单解决方案是回显当前的输入值。
yhat(t) = f(X(t))
例如:
X (timesteps), y
5, 3, 2, 1, 9, 9
这个小问题很容易通过多层感知器来解决,并且可以用于校准或诊断测试。
这个问题的一个更具挑战性的解决方案是回显前一个时间步骤的值。
yhat(t) = f(X(t-1))
例如:
X (timesteps), y
5, 3, 2, 1, 9, 1
这是多层感知器无法解决的问题。
回显可以类似地向前推进更多的时间步,但是这会对长短期记忆网络(LSTM)的记忆能力提出更高的要求。
与上面的“价值记忆”问题不同,这里每个训练阶段都会产生一个新的序列。这将要求模型学习一个一般的回显问题的解决方案,而不是记住一个特定的序列或随机数序列。
在这两种情况下,这个问题都将被建模为多对一的序列预测问题。
4.回显随机子序列
这个问题也涉及随机整数序列的生成。
与之前的问题只需要回显一个时间步的值不同,这里的问题要求模型记住并输出原始输入序列的一个部分子序列。
最简单的解决方案就是是前一节中的回显问题。相反的,这里我们需要关注整个序列的输出,最简单的方案就是让模型记住并输出整个输入序列。
例如:
X (timesteps), y
5, 3, 2, 4, 1, 5, 3, 2, 4, 1
这可以建模为多对一的序列预测问题,输出序列直接在输入序列的最后一个值的末尾输出。
这也可以被建模为每一步时间输出一个网络值,例如一对一模型。
更具挑战性的解决方案是输出输入序列的部分连续的子序列。
例如:
X (timesteps), y
5, 3, 2, 4, 1, 5, 3, 2
这是更具挑战性的,因为输入的数量与输出的数量不匹配。这个问题的多对多模型将需要更高级的架构,例如编码 - 解码型长短期记忆网络(LSTM)。
再次,一个热门的编码方案将会更受欢迎,尽管问题可以用归一化整数建模。
5.序列分类
这个问题被定义为0到1之间的一个随机值序列。这个序列的每个数作为本问题每个时间步长的输入。
二进制标签(0或1)与每个输入相关联。输出值全部为0。一旦序列中输入值的累积和超过阈值,输出值将从0变为1。
阈值为序列长度的1/4。
例如,下面是一个10个输入时间步长(X)的序列:
0.63144003 0.29414551 0.91587952 0.95189228 0.32195638 0.60742236 0.83895793 0.18023048 0.84762691 0.29165514
相应的分类输出(y)将是:
0 0 0 1 1 1 1 1 1 1
我们可以通过Python实现。
from random import random
from numpy import array
from numpy import cumsum
# create a sequence classification instance//创建一个分类序列的实例
def get_sequence(n_timesteps):
# create a sequence of random numbers in [0,1]//创建一个0到1之间额随机数序列
X = array([random() for _ in range(n_timesteps)])
# calculate cut-off value to change class values//计算要更改分类值的临界值
limit = n_timesteps/4.0
# determine the class outcome for each item in cumulative sequence//确定每一项的在累积序列中额类别输出
y = array([0 if x < limit else 1 for x in cumsum(X)])
return X, y
X, y = get_sequence(10)
print(X)
print(y)
运行示例生成随机输入序列,并计算相应的二进制值的输出序列。
[ 0.31102339 0.66591885 0.7211718 0.78159441 0.50496384 0.56941485
0.60775583 0.36833139 0.180908 0.80614878]
[0 0 0 0 1 1 1 1 1 1]
这是一个可以建模为一对一的序列分类问题。需要解释过去的时间步骤的状态,当输出序列从0变为1时正确预测输出。
进一步阅读
如果您正在深入研究,本节将提供更多有关该主题的资源。
- 长期的短期记忆,1997
- 如何在Python中利用Keras对不同大小批量的数据进行训练和预测
- 在Python中用一个长的短期记忆网络来演示记忆
- 学习如何使用长短期记忆回归网络回显随机整数值
- 如何使用编码 - 解码长短期记忆网络(LSTM)来回显随机整数序列
- 如何在Python中利用Keras开发一个用于序列分类的双向长短期记忆网络(LSTM)
概要
在本教程中,您看到了一套精心设计的序列预测问题,您可以使用这些问题来探索长短期记忆(LSTM)递归神经网络的学习和记忆能力。
具体来说,你了解到:
- 简单的记忆任务来测试训练好的长短期记忆网络(LSTM)的记忆能力。
- 简单的回显任务来测试训练好的长短期记忆网络(LSTM)的学习时间依赖性能力。
- 简单的算术任务来测试长短期记忆网络(LSTM)的解释能力。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 轻松应对并发问题,Newbe.Claptrap 框架中 State 和 Event 应该如何理解?
- 如何暂停一个正在运行的线程?
- WebMonitor采集端优化之路
- 美颜算法之自动祛斑算法实现 | 案例分享
- 附025.kubeadm部署Kubernetes更新证书
- 消息提示时间的格式化例子(小程序)
- 【Spark】用scala2.11编译打包构建镜像
- 移动端事件穿透的原理与解决方案
- 你被追尾了
- 深入理解JavaScript作用域
- 《闲扯Redis七》Redis字典结构的底层实现
- 深入理解JavaScript闭包之什么是闭包
- 按需取余
- Cypress 获取table内容动态tr和td
- Java 并发编程之 ConcurrentHashMap 源码分析(小长文)