Keras LSTM多输入多输出

时间:2018-04-04 23:01:35

标签: python tensorflow keras

我正在努力训练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)

非常感谢。

1 个答案:

答案 0 :(得分:4)

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

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

(samples, timesteps, features)

其次,您希望您的outbut数据具有以下形状:

(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调整为适合并将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,无论如何,您将受到消失或爆炸梯度问题的影响。

我希望这有帮助!