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

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

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

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

因此,如果我有 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)
非常感谢。

最佳答案

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

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

(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 ,作为 sample_weights 中的 model.fit 参数

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

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

关于您正在做的事情的一些额外提示:
  • 缩放您的数据。 StandardScaler、MinMaxScaler 等等。不要将原始价格数据传递给 LSTM(或任何深度学习模型),因为激活函数会将这些值粉碎为 -1、1、0 等,并且您将面临梯度消失或爆炸的问题。

  • 我希望这有帮助!

    关于python - Keras LSTM 多输入多输出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49661708/

    10-12 21:14