Keras LSTM的X个时间步长与Y个时间步长不同(例如,学习最后4个预测下2个)

时间:2019-02-18 14:53:42

标签: python tensorflow keras deep-learning lstm

我很难在Keras中获得一个LSTM模型来训练最后4个时间步,然后仅预测接下来的2个时间步。

我确定它是有可能的,但我只是混淆了一些keras api。

Here是Google Colab工作簿,它生成一些虚假数据,将X和Y整形以传递给模型,然后训练模型。

如果我将X_N_TIMESTEPS设置为与Y_N_TIMESTEPS相同,则它训练得很好-例如,使用最后4个时间步来预测下一个4。

但是我试图变得更笼统一些,并且能够训练最后4个时间步长,然后预测接下来的2个时间步长。make_xy()函数根据我认为的需要重塑数据。例如

X.shape=(1995, 4, 3)
Y.shape=(1995, 2, 3)

我认为我所缺少的是告诉最后一个Dense()层,我希望它仅输出2个时间步长。我得到的错误是:

  

ValueError:检查目标时出错:预期density_1具有形状   (4,3)但得到形状为(2,3)的数组

哪种暗示最后一个密集层不知道我只想要2个时间步长,即使这就是我作为Y值传递的内容。

我发现this表示可能可以将output_dim传递到最后一个密集层,但是如果尝试说我需要使用keras api v2,并且在查看文档时遇到错误,则会出现错误。 Dense我认为此后api必须有所更改。

这里是所有代码(以防比colab链接更受欢迎):

import numpy as np
import pandas as pd
from numpy import concatenate
from matplotlib import pyplot
from keras.models import Sequential
from keras.callbacks import Callback
from keras.layers import LSTM, Dense, Activation
import matplotlib.pyplot as plt

# %matplotlib inline

# define some variables
N_FEATURES = 3
X_N_TIMESTEPS = 4
Y_N_TIMESTEPS = 2
N_DATA_ORIG = 3000
N_ROLLING = 1000
N_DATA = N_DATA_ORIG - N_ROLLING

# make some noisy but smooth looking data
data = np.sqrt(np.random.rand(N_DATA_ORIG,N_FEATURES))
df_data = pd.DataFrame(data)
df_data = df_data.rolling(window=N_ROLLING).mean()
df_data = df_data.dropna()
df_data = df_data.head(N_DATA)
print(df_data.shape)
data = df_data.values
print(data.shape)
print(df_data.head())

# plot the normal healthy data
fig, ax = plt.subplots(num=None, figsize=(14, 6), dpi=80, facecolor='w', edgecolor='k')
size = len(data)
for x in range(data.shape[1]):
    ax.plot(range(0,size), data[:,x], '-', linewidth=1)

def make_xy(data,x_n_timesteps,y_n_timesteps,print_info=True):
    ''' Function to reshape the data into model ready format, either for training or prediction.
    '''
    # get original data shape
    data_shape = data.shape
    # get n_features from shape of input data
    n_features = data_shape[1]
    # loop though each row of data and reshape accordingly
    for i in range(len(data)):
        # row to start on for x
        xi = i 
        # row to start on for y
        yi = i + x_n_timesteps
        x = np.array([data[i:(i+x_n_timesteps),]])
        y = np.array([data[yi:(yi+y_n_timesteps),]])
        # only collect valid shapes
        if (x.shape == (1,x_n_timesteps,n_features)) & (y.shape == (1,y_n_timesteps,n_features)):
            # if initial data then copy else concatenate
            if i == 0:
                X = x
                Y = y
            else:
                X = np.concatenate((X,x))
                Y = np.concatenate((Y,y))
    if print_info:
        print('X.shape={}'.format(X.shape))
        print('Y.shape={}'.format(Y.shape))
    return X, Y

# build network 
model = Sequential()
model.add(LSTM(10,input_shape=(X_N_TIMESTEPS,N_FEATURES),return_sequences=True))
model.add(LSTM(10,return_sequences=True))
model.add(Dense(N_FEATURES))
model.compile(loss='mae', optimizer='adam')

# print model summary
print(model.summary())

# reshape data for training
print(f'... reshaping data for training ...')
X, Y = make_xy(data,X_N_TIMESTEPS,Y_N_TIMESTEPS)

# fit model
model.fit(X, Y)

1 个答案:

答案 0 :(得分:1)

您的模型输出有4个时间步长,但是您只希望最后2个时间步长。然后您可以添加一个Lambda图层以从原始输出中选择:

from keras.layers import Lambda
model = Sequential()
model.add(LSTM(10,input_shape=(X_N_TIMESTEPS,N_FEATURES),return_sequences=True))
model.add(LSTM(10,return_sequences=True))
model.add(Dense(N_FEATURES))
model.add(Lambda(lambda x: x[:,-2:,:]))
model.compile(loss='mae', optimizer='adam')

新模型结构:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
lstm_9 (LSTM)                (None, 4, 10)             560       
_________________________________________________________________
lstm_10 (LSTM)               (None, 4, 10)             840       
_________________________________________________________________
dense_5 (Dense)              (None, 4, 3)              33        
_________________________________________________________________
lambda_3 (Lambda)            (None, 2, 3)              0         
=================================================================
Total params: 1,433
Trainable params: 1,433
Non-trainable params: 0