序列预测不同于传统的分类和回归问题。
它要求你考虑观测的顺序,并且使用像长短期记忆(LSTM)递归神经网络这样有记忆性的,并且可以学习观测之间时间依赖性的模型。
通过在实践中应用LSTM来学习如何在序列预测问题上使用LSTM是至关重要的,因此,你需要一套定义明确的问题,让你专注于不同的问题类型和结构。这种学习方法的重要性在于这样你可以建立以下直觉:序列预测问题是如何不同于其他问题,并且如何利用复杂模型像LSTMs来解决这类问题。
在本教程中,你将学习一组5个狭义的可扩展序列预测问题,你可以使用这些问题来应用和学习更多关于长短期记忆(LSTM)递归神经网络的知识。
完成本教程后,你将知道:
让我们开始吧。
本教程分为5个部分; 他们是:
序列问题在设计时考虑了以下特点:
我会尝试提供一个专注的,有一定难度的和需要网络架构的混合结构的问题。
如果您对我的想法有进一步的扩展或类似精心设计的问题,请在下面的评论中告诉我。
在本问题中,生成一个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
...
这将要求网络学习要么在最后一个观测后自己添加一个修正值要么记住此问题的所有可能的子序列。
这个设计将被建模为多对一的序列预测问题。
这是测试序列学习的原始特征的一个简单问题。这个问题可以通过多层感知网络来解决。
问题是记住序列中的第一个值,并在序列的末尾重复。
这个问题是基于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
每个时间步长都将展现给网络,但网络必须记住在第一步值。不同之处在于,网络能够通过反向传播算法,更好地了解序列之间,长序列之间的差异。
这个问题的设计将被建模为多对一的序列预测问题。
此外,这个问题不能被多层感知器学习。
在此问题中,生成随机的整数序列。该模型必须记住一个特定滞后时间的整数,并在该序列的末尾回显该整数。
例如,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)的记忆能力提出更高的要求。
与上面的“价值记忆”问题不同,这里每个训练阶段都会产生一个新的序列。这将要求模型学习一个一般的回显问题的解决方案,而不是记住一个特定的序列或随机数序列。
在这两种情况下,这个问题都将被建模为多对一的序列预测问题。
这个问题也涉及随机整数序列的生成。
与之前的问题只需要回显一个时间步的值不同,这里的问题要求模型记住并输出原始输入序列的一个部分子序列。
最简单的解决方案就是是前一节中的回显问题。相反的,这里我们需要关注整个序列的输出,最简单的方案就是让模型记住并输出整个输入序列。
例如:
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)。
再次,一个热门的编码方案将会更受欢迎,尽管问题可以用归一化整数建模。
这个问题被定义为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时正确预测输出。
如果您正在深入研究,本节将提供更多有关该主题的资源。
在本教程中,您看到了一套精心设计的序列预测问题,您可以使用这些问题来探索长短期记忆(LSTM)递归神经网络的学习和记忆能力。
具体来说,你了解到: