Time Series 简明教程

Time Series - LSTM Model

现在,我们已熟悉时间序列的统计建模,机器学习目前盛行,所以也务必要熟悉一些机器学习模型。我们从时间序列领域最流行的模型——长短期记忆模型开始。

LSTM 是一类循环神经网络。因此,在跳到 LSTM 之前,务必要了解神经网络和循环神经网络。

Neural Networks

由链接神经元构建多层结构的人工神经网络,灵感来自于生物神经网络。它不仅是一种算法,而是允许我们在数据上执行复杂运算的各种算法组合。

Recurrent Neural Networks

这是一类专门用于处理临时数据的类神经网络。RNN 的神经元具有单元状态/记忆,输入根据此内部状态进行处理,这是通过神经网络中的循环来完成的。RNN 中的“tanh”层有周期性模块,可让它们保留信息。然而,保留的时间不会很长,因此我们才需要 LSTM 模型。

LSTM

这是一种特殊类别的循环神经网络,能够学习数据中的长期依赖性。这是因为模型的周期性模块将四个层层进行交互。

neural network

上图以黄色框表示四个神经网络层,以绿色圆圈表示逐点运算符,以黄色圆圈表示输入,以蓝色圆圈表示单元状态。一个 LSTM 模块具有一个单元状态和三个门,这给了它有选择地学习、取消学习,或者保留每个单元信息的能力。LSTM 中的单元状态帮助信息在单元之间流动,并通过只允许少量线性交互而保持不变。每个单元具有输入、输出,以及可以将信息添加到单元状态、或者从单元状态中移除信息的遗忘门。遗忘门使用一个 sigmoid 函数来确定前一个单元状态中的哪些信息应该被忘记。输入门使用“sigmoid”和“tanh”的逐点乘法运算来控制信息流向当前单元状态。最后,输出门决定哪些信息应传递到下一个隐藏状态

现在我们已经了解了 LSTM 模型的内部工作原理,让我们来实施它。要了解 LSTM 的实施,我们从一个简单的示例开始——一条直线。我们来看看 LSTM 能否学习直线关系并预测它。

首先,我们创建描述一条直线的数据集。

In [402]:

x = numpy.arange (1,500,1)
y = 0.4 * x + 30
plt.plot(x,y)

Out[402]:

[<matplotlib.lines.Line2D at 0x1eab9d3ee10>]
code snippet19

In [403]:

trainx, testx = x[0:int(0.8*(len(x)))], x[int(0.8*(len(x))):]
trainy, testy = y[0:int(0.8*(len(y)))], y[int(0.8*(len(y))):]
train = numpy.array(list(zip(trainx,trainy)))
test = numpy.array(list(zip(trainx,trainy)))

现在数据已经创建并分成训练和测试。让我们将时间序列数据转换为监督学习数据,根据回看期的值,这实质上是用于预测时间 t 值的滞后数。

因此像这样的时间序列 −

time variable_x
t1  x1
t2  x2
 :   :
 :   :
T   xT

在回溯周期为 1 时,转化为 −

x1   x2
x2   x3
 :    :
 :    :
xT-1 xT

In [404]:

def create_dataset(n_X, look_back):
   dataX, dataY = [], []
   for i in range(len(n_X)-look_back):
      a = n_X[i:(i+look_back), ]
      dataX.append(a)
      dataY.append(n_X[i + look_back, ])
   return numpy.array(dataX), numpy.array(dataY)

In [405]:

look_back = 1
trainx,trainy = create_dataset(train, look_back)
testx,testy = create_dataset(test, look_back)

trainx = numpy.reshape(trainx, (trainx.shape[0], 1, 2))
testx = numpy.reshape(testx, (testx.shape[0], 1, 2))

现在,我们将训练模型。

少量训练数据显示给网络,当所有训练数据分批显示给模型并且计算误差时称为一次 epoch。Epochs 将继续运行直到误差减少为止。

In []:

from keras.models import Sequential
from keras.layers import LSTM, Dense

model = Sequential()
model.add(LSTM(256, return_sequences = True, input_shape = (trainx.shape[1], 2)))
model.add(LSTM(128,input_shape = (trainx.shape[1], 2)))
model.add(Dense(2))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
model.fit(trainx, trainy, epochs = 2000, batch_size = 10, verbose = 2, shuffle = False)
model.save_weights('LSTMBasic1.h5')

In [407]:

model.load_weights('LSTMBasic1.h5')
predict = model.predict(testx)

现在,让我们看看我们的预测值是什么。

In [408]:

plt.plot(testx.reshape(398,2)[:,0:1], testx.reshape(398,2)[:,1:2])
plt.plot(predict[:,0:1], predict[:,1:2])

Out[408]:

[<matplotlib.lines.Line2D at 0x1eac792f048>]
code snippet22

现在,我们应尝试以类似方式对正弦波或余弦波建模。您可以运行下面提供的代码并使用模型参数进行操作,以查看结果如何变化。

In [409]:

x = numpy.arange (1,500,1)
y = numpy.sin(x)
plt.plot(x,y)

Out[409]:

[<matplotlib.lines.Line2D at 0x1eac7a0b3c8>]
code snippet23

In [410]:

trainx, testx = x[0:int(0.8*(len(x)))], x[int(0.8*(len(x))):]
trainy, testy = y[0:int(0.8*(len(y)))], y[int(0.8*(len(y))):]
train = numpy.array(list(zip(trainx,trainy)))
test = numpy.array(list(zip(trainx,trainy)))

In [411]:

look_back = 1
trainx,trainy = create_dataset(train, look_back)
testx,testy = create_dataset(test, look_back)
trainx = numpy.reshape(trainx, (trainx.shape[0], 1, 2))
testx = numpy.reshape(testx, (testx.shape[0], 1, 2))

In []:

model = Sequential()
model.add(LSTM(512, return_sequences = True, input_shape = (trainx.shape[1], 2)))
model.add(LSTM(256,input_shape = (trainx.shape[1], 2)))
model.add(Dense(2))
model.compile(loss = 'mean_squared_error', optimizer = 'adam')
model.fit(trainx, trainy, epochs = 2000, batch_size = 10, verbose = 2, shuffle = False)
model.save_weights('LSTMBasic2.h5')

In [413]:

model.load_weights('LSTMBasic2.h5')
predict = model.predict(testx)

In [415]:

plt.plot(trainx.reshape(398,2)[:,0:1], trainx.reshape(398,2)[:,1:2])
plt.plot(predict[:,0:1], predict[:,1:2])

Out [415]:

[<matplotlib.lines.Line2D at 0x1eac7a1f550>]
codesnippet23

现在,您可以继续处理任意数据集了。