【问题标题】:Keras LSTM different X timesteps to Y timesteps (e.g. learn on last 4 predict next 2)Keras LSTM 不同的 X 时间步和 Y 时间步(例如,在最后 4 个学习预测下一个 2)
【发布时间】:2019-02-18 14:53:42
【问题描述】:

在 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:检查目标时出错:预期 dense_1 具有形状 (4, 3) 但得到了形状为 (2, 3) 的数组

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

我找到了this,这表明也许我可以将 output_dim 传递给最后一个密集层,但是如果我尝试说我需要使用 keras api v2 并且当我查看@987654323 的文档时会出现错误@我认为从那以后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)

【问题讨论】:

    标签: python tensorflow keras deep-learning lstm


    【解决方案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
    

    【讨论】:

    • 很酷,谢谢。假设我仍然需要让传递给模型的 X 和 Y 在这里是相同的形状,然后基本上只是忽略我不想要的东西。我想知道我是否试图采取最后 10 个时间步并只获得下一个 2。然后训练模型采取 10 并预测 10 在某种意义上更难/更昂贵然后只是告诉它采取最后 10 并预测下一个 2。例如我想知道后者会更准确,因为在某种程度上我给它一个更简单的问题。
    • 我认为让 LSTM 层只需要 10 个时间步并预测 2 是不可能的。你可以在这里查看 LSTM 的架构:medium.com/@kangeugine/…。当我们说 10 个时间步时,它是一个 LSTM 单元做同样的事情 10 次。所以我认为输出的时间步长应该总是和输入的一样。
    • 而我的解决方案只是作为一种后处理方法。
    • 也许我需要的是更多的 seq2seq 类型设置。 blog.keras.io/…
    • 是的,看起来是这样的。
    猜你喜欢
    • 2018-03-09
    • 2020-04-11
    • 1970-01-01
    • 2020-02-28
    • 2022-01-14
    • 1970-01-01
    • 2020-04-17
    • 2021-09-08
    • 2020-07-21
    相关资源
    最近更新 更多