【问题标题】:Keras LSTM Multiple Input Multiple OutputKeras LSTM 多输入多输出
【发布时间】:2018-09-14 15:31:59
【问题描述】:

我正在尝试训练一个 RNN 来预测未来的股票价格。

我的目标是使用两个数据集训练模型:X_train 和 y_train。

X_train 是一个 3D 数组,包括(观察次数、先前蜡烛的数量、每个蜡烛的属性)

y_train 是一个 3D 数组,包括(观察次数、未来观察次数、价格)。

因此,如果我有来自 500 根蜡烛的数据,我的 X_train 将是 (430,60,6):对于 430 次观察(每次当前蜡烛),获取之前的 60 次观察和 6 个特征(收盘价、成交量等) .) 并尝试使用该数据(通过 RNN)来预测 y_train(430, 10,1):对于 430 次观察,预测接下来 10 根蜡烛的收盘价(对应于 1)。 在我的一生中,我无法获得正确输入模型的尺寸。 我对模型使用以下代码:

regressor = Sequential()

regressor.add(LSTM(units = 50, return_sequences = True, input_shape = ( 
X_train.shape[1], 6)))
regressor.add(Dropout(0.2))

regressor.add(LSTM(units = 50, return_sequences = True))
regressor.add(Dropout(0.2))

regressor.add(LSTM(units = 50, return_sequences = True))
regressor.add(Dropout(0.2))

regressor.add(LSTM(units = 50, return_sequences = True))
regressor.add(Dropout(0.2))

regressor.add(LSTM(units = 50, return_sequences=True))
regressor.add(Dropout(0.2))

regressor.add(LSTM(units = 1))

regressor.compile(optimizer = 'adam', loss = 'mean_squared_error')
regressor.fit(X_train, y_train, epochs = 20, batch_size = 32)

我收到ValueError: Error when checking target: expected lstm_6 to have 2 dimensions, but got array with shape (430, 10, 1)

非常感谢。

【问题讨论】:

  • 首先,这种堆叠的 lstm 结构至少可以说是非常不寻常的。

标签: python tensorflow keras


【解决方案1】:

让我们退后一步,看看做了什么以及为什么它不起作用。

首先,您的输入数据具有以下形状:

(samples, timesteps, features)

其次,您希望输出数据具有以下形状:

(samples, future_timesteps, 1)

这种架构被称为sequence to sequence learning(俗称Seq2Seq)。

那么我们如何进行 Seq2Seq?您可能想了解几种方法,这仍然是一个非常活跃的研究领域。这里有一些想法。

请注意,这是通过 keras functional api 完成的。更好。

从两个方向读取输入序列,然后通过具有 30 个单元的最终密集层预测接下来的 30 个单元进行定价。

input_layer = Input(shape=(600,6,))

lstm = Bidirectional(
    LSTM(250),
    merge_mode='concat'
)(input_layer)

pred = Dense(10)(lstm)
model = Model(inputs=input_layer, outputs=pred)
model.compile(optimizer = 'adam', loss = 'mean_squared_error')

model.fit(X_train, Y_train, epochs = 20, batch_size = 32)

其中Y_train 被重新整形为(430, 10) 而不是(430, 10, 1)。作为对评论的回应,这不会以任何有意义的方式更改标签 (Y_train)。这是因为 (x, y, 1) 和 (x,y) 的区别如下:

[[[1],[2],[3]],
 [[4],[5],[6]]]

而不是

[[1,2,3],
 [4,5,6]]

所以这样的调用:

Y_train = np.reshape(Y_train, Y_train.shape[:2])

不会对训练数据产生有意义的影响。

但是,这可能不是最好的架构。这是因为单个密集层将从前向和后向方向获取最后的隐藏状态,而不是在每个时间步长输入每个隐藏状态(从两个方向)。实际上,上述模型不知道以下模型中提供的更多信息。我建议以下作为替代方案。

input_layer = Input(shape=(600,6,))

encoder = Bidirectional(
    LSTM(250),
    merge_mode='concat',
    return_sequences=True
)(input_layer)
decoder = LSTM(250, return_sequences=True)(encoder)
pred = TimeDistributed(Dense(1))(decoder)
model = Model(inputs=input_layer, outputs=pred)
model.compile(optimizer = 'adam', loss = 'mean_squared_error')

model.fit(X_train, Y_train, epochs = 20, batch_size = 32)

其中Y_train 的格式为(430, 60, 1)。如果您只关心下一个 10 条目,请将 sample weighting 传递给 fit 并将 10th 时间索引之后的所有内容加权为 0 (如果需要,您甚至可以在训练时用垃圾填充它)。这将按如下方式完成:

Y_train = np.hstack([Y_train]*6) 

然后您将创建一个示例权重掩码,例如:

W = np.zeros(Y_train.shape)
W[:,np.arange(W.shape[1]) < 10,:] = 1

也就是说,只有沿第二个轴的前 10 个条目为 1,其他所有条目为零的掩码。传递这个W,作为model.fit 中的sample_weights 参数

这样,模型可以在编码器/解码器范式中具有真正的序列到序列概念。

最后,额外的 LSTMS(堆叠)并不是一定不好,但它被认为在改进这种性质的模型方面充其量是增量的,并且确实增加了大量的复杂性以及严重增加训练时间。获取一个模型以使用循环深度为 1(无堆叠),然后您可以在我给您的第二个结构中堆叠您的单个 lstm 或堆叠编码器/解码器。

一些关于你正在做的事情的额外提示:

  • 扩展您的数据。 StandardScaler、MinMaxScaler 等等。不要将原始价格数据传递给 LSTM(或任何深度学习模型),因为激活函数会将这些值粉碎为 -1、1、0 等等,您将遇到梯度消失或爆炸的问题。

我希望这会有所帮助!

【讨论】:

  • 非常感谢您提供非常详细的答案。它真的帮助我前进。我有一些后续问题。为什么堆叠 LSTM RNN 在这种情况下不起作用?根据您的第一个建议,将 Y_train 重新整形为 (430, 10) 而不是 (430, 10, 1)。如果没有实际数据,如何训练 RNN,因为最后一个维度是我们感兴趣的收盘价?第二个建议从哪个方面更好?最后,sample_weighting 中的一个示例将非常受欢迎。非常感谢。我已经习惯了好几天了,我无法表达对帮助的感激之情。
  • 不用担心。 @PnerFlner 我现在将在我的实际答案中添加您问题的答案。
  • 您的回答很有帮助。非常感谢。最后,您是否有资源可以从 Keras 重新开始,无论是一本书、一系列视频还是讲座?我一直在从一些在线教程中学习,但至少可以说它们是不够的。您可以快速开始一些事情,尽管要以真正的理解为代价。
猜你喜欢
  • 2017-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-22
  • 2019-01-07
  • 1970-01-01
  • 2018-02-16
  • 2020-04-14
相关资源
最近更新 更多