【问题标题】:Use keras(TensorFlow) to build a Conv2D+LSTM model使用keras(TensorFlow)搭建Conv2D+LSTM模型
【发布时间】:2018-05-08 07:09:31
【问题描述】:

数据为10个视频,每个视频分成86帧,每帧28*28像素,

video_num = 10
frame_num = 86
pixel_num = 28*28

我想使用 Conv2D+LSDM 来构建模型,并且在每个 time_steps(=frame_num=86) 发送模型中的像素数据 (=INPUT_SIZE=28*28)。所以以下是我关于模型的代码

BATCH_SIZE = 2 (just try)
TIME_STEPS=frame_num (=86)
INPUT_SIZE=pixel_num (=28*28)

model = Sequential()
model.add(InputLayer(batch_input_shape=(BATCH_SIZE, TIME_STEPS,     
INPUT_SIZE)))
print (model.output_shape)

model.add(TimeDistributed(Conv2D(64,(1,3),strides=(1,1), padding='same', 
data_format='channels_last')))  ##always the error here
print (model.output_shape)

model.add(TimeDistributed(MaxPooling2D(pool_size=(2,2),padding='same')))
print (model.output_shape)

model.add(TimeDistributed(Conv2D(64,(1,3),strides=(1,1), 
data_format='channels_last', padding='same')))
print (model.output_shape)

model.add(TimeDistributed(MaxPooling2D(pool_size=(2,2),padding='same')))
print (model.output_shape)

model.add(TimeDistributed(Flatten()))
print (model.output_shape)

model.add(TimeDistributed(Dense(4096, activation='relu')))
print (model.output_shape)

model.add(LSTM(100, stateful=True, return_sequences=True))
print (model.output_shape)

model.add(Dense(1, activation='sigmoid'))
print (model.output_shape)

下图显示了来自命令行的错误

https://imgur.com/a/yAPQO 说“列表索引超出范围”

我认为错误与 TimeDistributed() 中的输入形状有关,它从上层 (InputLayer()) 获取输入,但我不知道如何修复错误。 我试图删除 InputLayer(),并使用

TimeDistributed(Conv2D(...), input_shape=(TIME_STEPS, INPUT_SIZE))

作为第一层,也报同样的错误...

如果有人知道这个错误,请分享你的想法,我将不胜感激。另外,我还是不太清楚batch_input_shape和input_shape的区别,有没有人用过这两个? 谢谢。

【问题讨论】:

    标签: python keras lstm


    【解决方案1】:

    Conv2D 层需要四个维度,而不是三个:

    • (batch_size, height, width, channels)

    TimeDistributed 将需要一个额外的维度:

    • (batch_size, frames, height, width, channels)

    所以,如果你真的要使用 TimeDistributed+Conv2D,你需要 5 个维度。你的 input_shape=(86,28,28,3)batch_input_shape=(batch_size,86,28,28,3),我假设你有一个 RGB 视频(3 个颜色通道)。

    通常,您只需将输入形状传递给TimeDistributed

    model.add(TimeDistributed(Dense(....), input_shape=(86,28,28,3))
    

    只有在使用stateful=True LSTM 的情况下才需要batch_input_shape。然后,您只需将 input_shape 替换为 batch_input_shape。


    请注意,只有卷积 2D 层才能看到图像的高度和宽度。当您添加 LSTM 时,您需要重塑数据以将高度、宽度和通道整合到一个维度中。

    对于一个形状(框架、h、w、ch):

    model.add(Reshape((frames,h*w*ch)))
    

    您不应该将TimeDistributed 与这些 LSTM 一起使用,而只能与卷积层一起使用。

    您使用model.add(TimeDistributed(Flatten())) 的方法是可以的,而不是重塑。


    另请注意,Keras 最近实现了 ConvLSTM2D 层,这可能对您的情况有用:https://keras.io/layers/recurrent/#convlstm2d

    【讨论】:

    • 这里我遇到了另一个问题,如何使我的输入数据为 5D 形式,这也使最后一个维度为“通道”
    • frame_all_train[video_count][frame_count][pixel_height_count] [pixel_width_count] = frame[pixel_height_count,pixel_width_count] 我只能用我的数据形成一个 4D 表格,我不知道如何增加一个维度因为我不知道我应该在第 5 维中赋予什么价值……
    • 例如,如果您有一个黑白视频,那么您只有一个频道。在 numpy 数组中,您可以简单地重塑它。假设您有一个数组x_train,其形状为(10,86,28,28)。然后:x_train=x_train.reshape((10,86,28,28,1)).
    • 哦!我明白了,让我试试看这是否适合我!
    • 它又对我有用了!!太感谢你了!!!你知道“有状态”是什么意思吗?我在其他帖子上看到有人讨论过这个问题,在我看来,我认为“有状态”意味着 LSTM 中的隐藏状态可以在每批中更新一次并在一批后初始化,但我不太确定会不会是有可能我可以使隐藏状态从上一批结束传递到下一批开始(我不想在开始训练后再初始化隐藏状态)?如果使用 LSTM 是不可能的,有没有其他方法可以使它成为可能
    猜你喜欢
    • 2020-05-23
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 2018-01-30
    • 2020-04-16
    相关资源
    最近更新 更多