Keras LSTM多输入多输出

Pan*_*nos 5 python keras tensorflow

我正在尝试训练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)
Run Code Online (Sandbox Code Playgroud)

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

非常感谢。

mod*_*itt 6

让我们退后一步,看看完成了什么,为什么不起作用。

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

(samples, timesteps, features)
Run Code Online (Sandbox Code Playgroud)

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

(samples, future_timesteps, 1)
Run Code Online (Sandbox Code Playgroud)

这种体系结构称为序列到序列学习(俗称Seq2Seq)。

那么我们如何做一个Seq2Seq?您可能需要阅读几种方法,但这仍然是非常活跃的研究领域。这里有一些想法。

请注意,这是通过keras功能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)
Run Code Online (Sandbox Code Playgroud)

其中Y_train被整形来(430, 10)代替(430, 10, 1)。在回应评论时,这不会Y_train以任何有意义的方式更改标签()。这是因为(x,y,1)与(x,y)之间的差异如下:

[[[1],[2],[3]],
 [[4],[5],[6]]]
Run Code Online (Sandbox Code Playgroud)

代替

[[1,2,3],
 [4,5,6]]
Run Code Online (Sandbox Code Playgroud)

像这样的电话:

Y_train = np.reshape(Y_train, Y_train.shape[:2])
Run Code Online (Sandbox Code Playgroud)

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

但是,这可能不是最佳的架构。这是因为单个致密层将从前进和后退方向进入最后的隐藏状态,而不是在每个时间步长都馈送每个隐藏状态(从两个方向)。实际上,上面的模型没有意识到下面的模型中提供的更多信息。我建议以下替代方法。

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)
Run Code Online (Sandbox Code Playgroud)

其中Y_train的格式为(430, 60, 1)。如果您只关心下一个10条目,sample weighting则将10th时间索引之后的所有内容传递为适合和加权的值0(如果需要,甚至可以在训练时将其填充为垃圾)。可以这样进行:

Y_train = np.hstack([Y_train]*6) 
Run Code Online (Sandbox Code Playgroud)

然后,您将创建一个示例重量蒙版,如下所示:

W = np.zeros(Y_train.shape)
W[:,np.arange(W.shape[1]) < 10,:] = 1
Run Code Online (Sandbox Code Playgroud)

即,仅沿第二轴的前10个条目为1,而所有其他均为零的掩码。传递this W作为sample_weights参数model.fit

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

最后,并不是说附加的LSTMS(堆叠)不一定是坏的,而是在改进这种性质的模型时充其量只能看作是增量的,确实会增加大量的复杂性并严重增加培训时间。获得一个单一模型以使用深度为1的递归深度(不堆叠),然后您可以堆叠单个lstm或在我给您的第二个结构中堆叠编码器/解码器。

有关您正在做什么的其他提示:

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

我希望这有帮助!