CNN层应该在Bi-LSTM之前还是之后?

时间:2020-07-16 11:28:58

标签: keras lstm cnn

我正在尝试建立单变量时间序列预测模型。当前的架构正在寻找 像这样:

model = Sequential()
model.add(Bidirectional(LSTM(20, return_sequences=True), input_shape=(n_steps_in, n_features)))
model.add(Bidirectional(LSTM(20, return_sequences=True)))
model.add(Conv1D(64, 3, activation='relu', input_shape=(n_steps_in, n_features)))
model.add(Conv1D(64, 3, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(n_steps_out))

然后,我尝试了以下操作,该操作将所有CNN层放置在Bi-LSTM层之前(但不起作用):

model = Sequential()
model.add(Conv1D(64, 3, activation='relu', input_shape=(n_steps_in, n_features)))
model.add(Conv1D(64, 3, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Bidirectional(LSTM(20, input_shape=(n_steps_in, n_features), return_sequences=True)))
model.add(Bidirectional(LSTM(20, return_sequences=True)))
model.add(Dense(100, activation='relu'))
model.add(Dense(n_steps_out))

最新的实现似乎无效。有什么建议解决这个问题吗?我遇到的另一个问题是,是否有一种方法可以确定CNN是否应在Bi-LSTM之前进行,反之亦然?

2 个答案:

答案 0 :(得分:2)

我可以通过说它似乎不起作用来确切地理解您的意思吗?

因为我希望您像在第二种方法中所做的那样,在LSTM之前进行任何卷积。但是这里有几件事要注意。

首先,仅当下一层也是LSTM时,才应从LSTM层返回序列:

model.add(Bidirectional(LSTM(20, input_shape=(n_steps_in, n_features), return_sequences=True)))
model.add(Bidirectional(LSTM(20)))
model.add(Dense(1))

第二,您可以尝试使用GlobalAveragePooling1D代替MaxPooling1D,因为后者考虑了所有功能(例如,与对图像进行分类相比,要注意的重要因素):

model.add(GlobalAveragePooling1D(pool_size=2))

答案 1 :(得分:1)

您的网络接收输入序列和输出序列,因此您需要注意维数。为此,您必须使用卷积层中的填充以及池化操作。您还需要在最后一个LSTM单元格中设置return_sequences = True(您正在预测序列)。在下面的示例中,我将您的网络与填充一起使用,并延迟了会破坏3D尺寸的展平

您可以在LSTM之前或之后应用卷积。最好的方法是尝试两者并使用可信赖的验证集评估性能

CNN + LSTM

n_sample = 100
n_steps_in, n_steps_out, n_features = 30, 15, 1
X = np.random.uniform(0,1, (n_sample, n_steps_in, n_features))
y = np.random.uniform(0,1, (n_sample, n_steps_out, n_features))

model = Sequential()
model.add(Conv1D(64, 3, activation='relu', padding='same',
                 input_shape=(n_steps_in, n_features)))
model.add(Conv1D(64, 3, padding='same', activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Bidirectional(LSTM(20, return_sequences=True)))
model.add(Bidirectional(LSTM(20, return_sequences=True)))
model.add(Dense(1))
model.compile('adam', 'mse')
model.summary()

model.fit(X,y, epochs=3)

LSTM + CNN

model = Sequential()
model.add(Bidirectional(LSTM(20, return_sequences=True), 
                 input_shape=(n_steps_in, n_features)))
model.add(Bidirectional(LSTM(20, return_sequences=True)))
model.add(MaxPooling1D(pool_size=2))
model.add(Conv1D(64, 3, activation='relu', padding='same'))
model.add(Conv1D(64, 3, padding='same', activation='relu'))
model.add(Dense(1))
model.compile('adam', 'mse')
model.summary()

model.fit(X,y, epochs=3)