使用keras(TensorFlow)构建Conv2D + LSTM模型

7
数据包括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 显示 "list index out of range".
我认为这个错误与TimeDistributed()中的输入形状有关,该函数从上一层(InputLayer())获取输入,但我不知道如何修复此错误。 我已经尝试过删除InputLayer()并使用其他方法,但问题仍未得到解决。
TimeDistributed(Conv2D(...), input_shape=(TIME_STEPS, INPUT_SIZE))

作为第一层,但是同样出现了错误...
如果有人知道这个错误的原因,请分享您的想法,我将非常感激。此外,我仍然不太清楚batch_input_shape和input_shape之间的区别,有人使用过这两个吗?谢谢。
1个回答

11
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 时,您需要重塑数据,将高度、宽度和通道带入单个维度。

对于形状 (frames, h, w, ch):

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

在这些LSTM中,您不应使用TimeDistributed,只能与卷积层一起使用。

您使用的model.add(TimeDistributed(Flatten()))方法来代替重塑是可以的。


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


这里我又遇到了一个问题,如何将我的输入数据变成5D形式,并且使最后一维成为“通道”。 - Edward Chang
frame_all_train[video_count][frame_count][pixel_height_count][pixel_width_count] = frame[pixel_height_count,pixel_width_count]我只能用我的数据形成一个4D形式,我不确定如何添加一个维度,因为我不知道应该将什么值放入第五个维度... - Edward Chang
如果你有一段黑白视频,那么你只有一个通道。在numpy数组中,你可以简单地改变它的形状。假设你有一个形状为(10,86,28,28)的数组x_train。那么:x_train=x_train.reshape((10,86,28,28,1)) - Daniel Möller
它又可以用了!!!非常感谢!!!你知道“Stateful”是什么意思吗?我在其他帖子上看到有人讨论过这个问题,我认为“Stateful”意味着LSTM中的隐藏状态可以在每个批次中更新一次,并在一个批次后初始化,但我不确定是否可能使隐藏状态从上一个批次的结尾传递到下一个批次的开头(我不想在开始训练后再次初始化隐藏状态)。如果在使用LSTM时无法实现,是否有其他方法可以实现? - Edward Chang
请看这里 :) - https://dev59.com/JlcP5IYBdhLWcg3ww8qS - Daniel Möller
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接