【问题标题】:Tensorflow keras timeseries prediction with X and y having different shapesTensorflow keras 时间序列预测,X 和 y 具有不同的形状
【发布时间】:2020-11-05 02:15:46
【问题描述】:

我正在尝试使用具有不同维度的 Xy 的 tensorflow 和 keras 进行时间序列预测:

X.shape = (5000, 12)
y.shape = (5000, 3, 12)

当我执行以下操作时

n_input = 7
generator = TimeseriesGenerator(X, y, length=n_input, batch_size=1)

for i in range(5):
    x_, y_ = generator[i]
    print(x_.shape)
    print(y_.shape)

我得到想要的输出

(1, 7, 12)
(1, 3, 12)
(1, 7, 12)
(1, 3, 12)
...

这是因为我的数据是气象数据,我有 5000 天,用于数组 X 中的训练,我使用 7 天的滑动窗口,每天包含 12 个特征(气压、温度、湿度 a.o.)。而在目标数组y我有3天的滑动窗口,试图预测接下来的3天到7天的每个窗口。

但是当我尝试拟合模型时,由于Xy 数组的形状不匹配而出现错误:

model = Sequential()
model.add(LSTM(4, input_shape=(None, 12)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
history = model.fit_generator(generator, epochs=3).history

ValueError: A target array with shape (1, 3, 12) was passed for an output of shape (None, 1) while using as loss `mean_squared_error`. This loss expects targets to have the same shape as the output.

那么有没有办法针对尺寸不匹配调整架构?或者有没有办法重塑Xy 使它们与这个架构一起工作?我尝试了后期将X 重塑为(5000, 7, 12),但这也产生了维度错误。天呐

【问题讨论】:

    标签: python tensorflow keras time-series regression


    【解决方案1】:

    您的生成器是正确的……是您的网络不工作。

    您没有正确处理维度。你正在处理序列,所以你需要在你的 LSTM 单元中强加return_sequences=True。你的输入有 7 个时间步,而你的输出有 3 个时间步,你必须从 7 传递到 3(你可以通过池化等来做到这一点)。

    下面是一个虚拟示例。我不使用池化操作,而只是选择序列的一部分以获得 3 个时间步长的输出

    X = np.random.uniform(0,1, (5000, 12))
    y = np.random.uniform(0,1, (5000, 3, 12))
    
    n_input = 7
    generator = tf.keras.preprocessing.sequence.TimeseriesGenerator(X, y, length=n_input, batch_size=32)
    
    model = Sequential()
    model.add(LSTM(4, return_sequences=True, input_shape=(n_input, 12)))
    model.add(Lambda(lambda x: x[:,-3:,:]))
    model.add(Dense(12))
    model.compile(loss='mean_squared_error', optimizer='adam')
    
    model.summary()
    
    model.fit(generator, epochs=2)
    

    这里是一个池化操作的例子

    model = Sequential()
    model.add(LSTM(4, return_sequences=True, input_shape=(n_input, 12)))
    model.add(MaxPool1D(2)) # also AvgPool1D is ok
    model.add(Dense(12))
    model.compile(loss='mean_squared_error', optimizer='adam')
    
    model.summary()
    model.fit(generator, epochs=2)
    

    这里是 return_sequences=False 和重复向量的示例

    model = Sequential()
    model.add(LSTM(4, return_sequences=False, input_shape=(n_input, 12)))
    model.add(RepeatVector(3))
    model.add(Dense(12))
    model.compile(loss='mean_squared_error', optimizer='adam')
    
    model.summary()
    model.fit(generator, epochs=2)
    

    【讨论】:

    • 谢谢,如果你能提供一个带有“池等”的工作版本,我可以接受你的回答是正确的。我想您提供的示例出于功能考虑会忽略一些训练数据
    • @NeStack 我通过添加其他示例来编辑答案...试一试所有尝试使用您的网络结构。不要忘记投票并接受作为答案;-)
    • @NeStack 如果有问题请告诉我
    • 谢谢,您的建议确实有效!我推迟了回复,因为我正在研究下一个可能会问的问题:MaxPool1DAvgPool1DRepeatVector 之间有什么区别? model.add(LSTM(N) 中的 N 应该是什么;我应该添加 dropout 和更密集的层吗?最重要的是,什么将是一个很好的最先进的架构来应用于我的时间序列预测。所以,这都是我最初问的范围之外的问题,但会帮助我完成我的预测任务。所以,如果你想给他们你的意见:)
    • 参数、层深度、结构的选择是与你的数据相关的选择。最好的办法是使用有价值的验证模式进行一些调整。有最先进的模型/结构,如 wavenet 或时间序列的 inception,您可以在互联网上轻松找到它们
    【解决方案2】:

    最终(全连接)层的形状是 (None, 1),输出的形状是 (None, 3, 12)。数据的输出形状和网络必须匹配。

    我会使用 the Functional API 并创建 3 个单独的 Dense 层并将它们连接起来。像这样:

    inp = tf.keras.Input(shape=(7, 12))
    x = tf.keras.layers.LSTM(4)(inp)
    
    y1 = tf.keras.layers.Dense(12)(x)
    y2 = tf.keras.layers.Dense(12)(x)
    y3 = tf.keras.layers.Dense(12)(x)
    
    y1 = tf.keras.backend.expand_dims(y1, axis=1)
    y2 = tf.keras.backend.expand_dims(y2, axis=1)
    y3 = tf.keras.backend.expand_dims(y3, axis=1)
    
    output = tf.keras.layers.Concatenate(axis=1)([y1, y2, y3])
    
    mdl = tf.keras.Model(inp, output)
    mdl.summary()
    

    返回: Model Summary

    【讨论】:

    • 感谢您的回答!我接受了 Marco 的回答,因为他看起来对我的技能水平更直观,并且更容易实施。无论如何,我赞成你的回答:)
    • 谢谢,这是我的第一个答案!我没有使用 LTSM 的经验,我只是想修复我看到的错误。我认为他的回答对你的情况也更有意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-09
    • 2018-04-03
    • 2023-04-08
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    相关资源
    最近更新 更多