用于多元时间序列的Keras递归神经网络

时间:2018-08-22 22:22:31

标签: python keras time-series recurrent-neural-network

我一直在阅读有关Keras RNN模型(LSTM和GRU)的信息,作者似乎主要关注语言数据或使用由先前时间步组成的训练实例的单变量时间序列。我的数据有些不同。

我有10个十年中每年测量的20个变量作为输入数据,而对于11年级有20个变量作为输出数据。我想做的是预测第11年变量之一(而不是其他19个变量)的值。

我的数据结构为X.shape = [persons, years, variables] = [100000, 10, 20]Y.shape = [persons, variable] = [100000, 1]。下面是我的LSTM模型的Python代码。

## LSTM model.

# Define model.

network_lstm = models.Sequential()
network_lstm.add(layers.LSTM(128, activation = 'tanh', 
     input_shape = (X.shape[1], X.shape[2])))
network_lstm.add(layers.Dense(1, activation = None))

# Compile model.

network_lstm.compile(optimizer = 'adam', loss = 'mean_squared_error')

# Fit model.

history_lstm = network_lstm.fit(X, Y, epochs = 25, batch_size = 128)

我有四个(相关)问题,请:

  1. 我是否为我拥有的数据结构正确编码了Keras模型?我从完全连接的网络(使用平坦的数据)以及LSTM,GRU和1D CNN模型获得的性能几乎相同,并且我不知道我是否在Keras中犯了错误,或者是否是循环模型简单地在这种情况下没有帮助。

  2. 我是否应该将Y作为具有Y.shape = [persons, years] = [100000, 11]形状的序列,而不是在X中包括变量,使其具有X.shape = [persons, years, variables] = [100000, 10, 19]的形状?如果是这样,如何获取RNN以输出预测的序列?当我使用return_sequences = True时,Keras返回错误。

  3. 这是预测我拥有的数据的最佳方法吗? Keras RNN模型甚至其他模型中是否有更好的选项选择?

  4. 如何模拟类似于我现有数据结构的数据,以使RNN模型的性能优于完全连接的网络?

更新:

我已经尝试了一个模拟,我希望这是一个非常简单的情况,其中应该期望RNN胜过FNN。

尽管当LSTM的隐藏层较少时(4),LSTM的性能往往优于FNN,但是在隐藏层较多的情况下(8+),性能变得相同。谁能想到一个更好的模拟,在这种模拟中,预期RNN会在数据结构相似的情况下胜过FNN?

from keras import models
from keras import layers

from keras.layers import Dense, LSTM

import numpy as np
import matplotlib.pyplot as plt

下面的代码模拟10,000个实例,10个时间步和2个变量的数据。如果第二个变量在第一个时间步中具有0,则Y是最后一个时间步的第一个变量的值乘以3。如果第二个变量在第一个时间步中具有1,则Y为最后一个时间步的第一个变量的值乘以9。

我希望RNN会在内存中的第一个时间步保留第二个变量的值,并使用该值来知道哪个值(3或9)将最后一个时间步的第一个变量乘以< / p>

## Simulate data.

instances = 10000

sequences = 10

X = np.zeros((instances, sequences * 2))

X[:int(instances / 2), 1] = 1

for i in range(instances):

    for j in range(0, sequences * 2, 2):

        X[i, j] = np.random.random()

Y = np.zeros((instances, 1))

for i in range(len(Y)):

    if X[i, 1] == 0:

        Y[i] = X[i, -2] * 3

    if X[i, 1] == 1:

        Y[i] = X[i, -2] * 9

以下是FNN的代码:

## Densely connected model.

# Define model.

network_dense = models.Sequential()
network_dense.add(layers.Dense(4, activation = 'relu', 
     input_shape = (X.shape[1],)))
network_dense.add(Dense(1, activation = None))

# Compile model.

network_dense.compile(optimizer = 'rmsprop', loss = 'mean_absolute_error')

# Fit model.

history_dense = network_dense.fit(X, Y, epochs = 100, batch_size = 256, verbose = False)

plt.scatter(Y[X[:, 1] == 0, :], network_dense.predict(X[X[:, 1] == 0, :]), alpha = 0.1)
plt.plot([0, 3], [0, 3], color = 'black', linewidth = 2)
plt.title('FNN, Second Variable has a 0 in the Very First Time Step')
plt.xlabel('Actual')
plt.ylabel('Predicted')

plt.show()

plt.scatter(Y[X[:, 1] == 1, :], network_dense.predict(X[X[:, 1] == 1, :]), alpha = 0.1)
plt.plot([0, 9], [0, 9], color = 'black', linewidth = 2)
plt.title('FNN, Second Variable has a 1 in the Very First Time Step')
plt.xlabel('Actual')
plt.ylabel('Predicted')

plt.show()

以下是LSTM的代码:

## Structure X data for LSTM.

X_lstm = X.reshape(X.shape[0], X.shape[1] // 2, 2)

X_lstm.shape

## LSTM model.

# Define model.

network_lstm = models.Sequential()
network_lstm.add(layers.LSTM(4, activation = 'relu', 
     input_shape = (X_lstm.shape[1], 2)))
network_lstm.add(layers.Dense(1, activation = None))

# Compile model.

network_lstm.compile(optimizer = 'rmsprop', loss = 'mean_squared_error')

# Fit model.

history_lstm = network_lstm.fit(X_lstm, Y, epochs = 100, batch_size = 256, verbose = False)

plt.scatter(Y[X[:, 1] == 0, :], network_lstm.predict(X_lstm[X[:, 1] == 0, :]), alpha = 0.1)
plt.plot([0, 3], [0, 3], color = 'black', linewidth = 2)
plt.title('LSTM, FNN, Second Variable has a 0 in the Very First Time Step')
plt.xlabel('Actual')
plt.ylabel('Predicted')

plt.show()

plt.scatter(Y[X[:, 1] == 1, :], network_lstm.predict(X_lstm[X[:, 1] == 1, :]), alpha = 0.1)
plt.plot([0, 9], [0, 9], color = 'black', linewidth = 2)
plt.title('LSTM, FNN, Second Variable has a 1 in the Very First Time Step')
plt.xlabel('Actual')
plt.ylabel('Predicted')

plt.show()

1 个答案:

答案 0 :(得分:1)

  1. 是的,所使用的代码对于您要执行的操作是正确的。 10年是用来预测下一年的时间窗口,因此应该是模型中20个变量中每个变量的输入数量。 100,000个观测值的样本大小与模型的输入形状无关。

  2. 您最初塑造因变量Y的方式是正确的。您正在预测1年的1个变量的窗口,并且您有100,000个观测值。关键字参数return_sequences=True将导致引发错误,因为您只有一个LSTM层。如果要实现多个LSTM层,并且将所讨论的层后跟另一个LSTM层,请将此参数设置为True

我希望能为3提供一些指导,但实际上没有您的数据集,我不知道是否可以肯定地回答这个问题。

我会说LSTM旨在解决常规RNN中存在的长期依赖问题。这个问题归结为,随着观察相关信息到该信息将变得有用之间的差距越来越大,标准RNN将很难学习它们之间的关系。考虑基于活动的3天与全年预测股票价格。

这导致数字4。如果我宽松地使用“类似”一词,并将您的时间范围扩展到50年而不是10年,那么使用LSTM所获得的优势将变得更加明显。尽管我相信经验丰富的人将能够提供更好的答案,但我希望看到它。

我发现此页面有助于理解LSTM:

https://colah.github.io/posts/2015-08-Understanding-LSTMs/