将CNN功能馈送到LSTM



我想构建一个具有以下专有权的端到端可训练模型:

  • CNN从图像中提取特征
  • 将功能重塑为矩阵
  • 然后将此矩阵的每一行馈送到LSTM1
  • 然后将此矩阵的每一列喂入LSTM2
  • 最终输出的LSTM1和LSTM2的输出是连接的

(或多或少与本文的图2相似:https://arxiv.org/pdf/1611.07890.pdf(

我现在的问题是在重塑之后,如何用keras或tensorflow将特征矩阵的值馈送值?

这是我到目前为止使用VGG16 NET的代码(也是指向KERAS问题的链接(:

# VGG16
model = Sequential()
model.add(Conv2D(64, (3, 3), activation='relu', padding='same', input_shape=(224, 224, 3)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
# block 2
model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
# block 3
model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(256, (3, 3), activation='relu'))
model.add(Conv2D(256, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
# block 4
model.add(Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(512, (3, 3), activation='relu'))
model.add(Conv2D(512, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
# block 5
model.add(Conv2D(512, (3, 3), activation='relu', padding='same'))
model.add(Conv2D(512, (3, 3), activation='relu'))
model.add(Conv2D(512, (3, 3), activation='relu'))
model.add(MaxPooling2D((2, 2)))
# block 6
model.add(Flatten())
model.add(Dense(4096, activation='relu'))
model.add(Dense(4096, activation='relu'))
# reshape the  feature 4096 = 64 * 64
model.add(Reshape((64, 64)))
# How to feed each row of this to LSTM?
# This is my first solution but it doesn’t look correct: 
# model.add(LSTM(256, input_shape=(64, 1)))  # 256 hidden units, sequence length = 64, feature dim = 1

考虑使用Conv2D和MaxPool2D层构建CNN模型,直到您达到平坦的层为止,因为从平坦的层中的矢量输出将您输入到结构的LSTM部分。

所以,以这样的方式构建您的CNN模型:

model_cnn = Sequential()
model_cnn.add(Conv2D...)
model_cnn.add(MaxPooling2D...)
...
model_cnn.add(Flatten())

现在,这是一个有趣的观点,当前版本的keras与某些张量流结构不兼容,这些结构不会让您将整个层仅在一个顺序对象中堆叠。

是时候使用keras模型对象以一个技巧来完成神经网络:

input_lay = Input(shape=(None, ?, ?, ?)) #dimensions of your data
time_distribute = TimeDistributed(Lambda(lambda x: model_cnn(x)))(input_lay) # keras.layers.Lambda is essential to make our trick work :)
lstm_lay = LSTM(?)(time_distribute)
output_lay = Dense(?, activation='?')(lstm_lay)

最后,现在是时候将我们的两个分开模型放在一起了:

model = Model(inputs=[input_lay], outputs=[output_lay])
model.compile(...)

obs:请注意,一旦VGG平面层的矢量输出将是LSTM模型的输入,您可以通过VGG替换我的Model_cnn示例,而无需包括顶层。

最新更新