Python 在LSTM中输入CNN的输出
这是我第一次与LSTM网络合作。我有一个帧速率为30 fps的视频。我有一个CNN网络(基于AlexNet),我想将CNN网络的最后一层输入到循环网络(我使用的是tensorflow)。假设我的Python 在LSTM中输入CNN的输出,python,tensorflow,deep-learning,lstm,Python,Tensorflow,Deep Learning,Lstm,这是我第一次与LSTM网络合作。我有一个帧速率为30 fps的视频。我有一个CNN网络(基于AlexNet),我想将CNN网络的最后一层输入到循环网络(我使用的是tensorflow)。假设我的batch_size=30,因此等于fps,并且我希望有一个1秒的时间步长(因此,每30帧)。我的网络最后一层的输出将是[bast\u size,1000],因此在我的情况下[30,1000],现在我是否必须将输出的大小重塑为[batch\u size,time\u steps,features](在我的
batch_size=30
,因此等于fps,并且我希望有一个1秒的时间步长(因此,每30帧)。我的网络最后一层的输出将是[bast\u size,1000]
,因此在我的情况下[30,1000]
,现在我是否必须将输出的大小重塑为[batch\u size,time\u steps,features]
(在我的情况下:[30,30,1000]
)?对吗?还是我错了?如果您合并来自不同视频的多个小序列以形成一个批,则模型最后一层(RNN)的输出应该已经是[批大小、窗口大小、数量类]。基本上,您希望用重塑层包裹CNN,重塑层将连接每个批次的帧:
- 输入->[批次大小、窗口大小、通道、高度、宽度]
- 重塑->[批次大小*窗口大小,通道,高度,宽度]
- CNN->[批量大小*窗口大小,专长大小]
- 重塑->[批量大小、窗口大小、专长大小]
- RNN->[批处理大小、窗口大小、输出数量](假设按帧预测)
但这将占用大量内存,所以您可以将batch size设置为1,如果我理解正确的话,您似乎正在这样做。在这种情况下,可以保留第一次重塑
我不确定上面的轴的顺序,但一般逻辑保持不变
作为旁注:如果您计划在某个时候使用批规格化,您可能希望提高批大小,因为来自单个片段的连续帧本身可能不包含很多变化。还要仔细检查批次规格化轴,该轴应包括时间轴和批次轴。考虑使用Conv2D和MaxPool2D层构建CNN模型,直到到达展平层,因为展平层的矢量化输出将是结构的LSTM部分的输入数据
因此,构建您的CNN模型如下:
model_cnn = Sequential()
model_cnn.add(Conv2D...)
model_cnn.add(MaxPooling2D...)
...
model_cnn.add(Flatten())
现在,这是一个有趣的观点,Keras的当前版本与一些TensorFlow结构不兼容,这些结构不允许将整个层堆叠在一个连续对象中
因此,是时候使用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(...)
现在,在我们的OpenCV部分中,使用如下所示的算法直接对视频进行预处理,以便在网络中构建一个大的帧张量:
video_folder = '/path.../'
X_data = []
y_data = []
list_of_videos = os.listdir(vide_folder)
for i in list_of_videos:
#Video Path
vid = str(video_folder + i) #path to each video from list1 = os.listdir(path)
#Reading the Video
cap = cv2.VideoCapture(vid)
#Reading Frames
#fps = vcap.get(5)
#To Store Frames
frames = []
for j in range(40): #here we get 40 frames, for example
ret, frame = cap.read()
if ret == True:
print('Class 1 - Success!')
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #converting to gray
frame = cv2.resize(frame,(30,30),interpolation=cv2.INTER_AREA)
frames.append(frame)
else:
print('Error!')
X_data.append(frames) #appending each tensor of 40 frames resized for 30x30
y_data.append(1) #appending a class label to the set of 40 frames
X_data = np.array(X_data)
y_data = np.array(y_data) #ready to split! :)
就训练它吧!:) 谢谢你的回答。因此,每个批次将包含与同一视频相关的序列,因此,如果批次大小为30,则30帧与同一视频相关。我没听清楚你的解释窗口大小代表什么。如果我有一个由30帧组成的批次,可能在我的CNN最后一层(输出:[批次大小,特征数量])之后,每30帧和每1秒进行一次分类,那么我是否必须将其重塑为[1,30,特征数量]?谢谢你的帮助