我正在尝试训练 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 或堆叠编码器/解码器。
关于您正在做的事情的一些额外提示:
我希望这有帮助!
关于python - Keras LSTM 多输入多输出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49661708/