You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

3DCNN转LSTM实现唇读模型:报错解决后仍存结构转换疑惑

3DCNN+LSTM唇读模型:报错解决与跨层数据传递原理

问题场景与报错

学习循环神经网络时,尝试搭建3DCNN+LSTM的自动唇读模型,采用Kaggle上的代码:

model = Sequential()

# 1st layer group
model.add(Conv3D(32, (3, 3, 3), strides = 1, input_shape=(22, 100, 100, 1), activation='relu', padding='valid'))
model.add(MaxPooling3D(pool_size=(2, 2, 2), strides=2))

model.add(Conv3D(64, (3, 3, 3), activation='relu', strides=1))
model.add(MaxPooling3D(pool_size=(2, 2, 2), strides=2))

model.add(Conv3D(128, (3, 3, 3), activation='relu', strides=1))
model.add(MaxPooling3D(pool_size=(2, 2, 2), strides=2))

shape = model.get_output_shape_at(0)
model.add(Reshape((shape[-1],shape[1]*shape[2]*shape[3])))

# LSTMS - Recurrent Network Layer
model.add(LSTM(32, return_sequences=True))
model.add(Dropout(.5))

model.add((Flatten()))

# # FC layers group
model.add(Dense(2048, activation='relu'))
model.add(Dropout(.5))
model.add(Dense(1024, activation='relu'))
model.add(Dropout(.5))

model.add(Dense(10, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='Adam', metrics=['accuracy'])
model.summary()

运行时出现报错:

11 model.add(MaxPooling3D(pool_size=(2, 2, 2), strides=2))
     12 
---> 13 shape = model.get_output_shape_at(0)
     14 model.add(Reshape((shape[-1],shape[1]*shape[2]*shape[3])))
     15 
RuntimeError: The layer sequential_2 has never been called and thus has no defined output shape.

将代码修改为以下内容后,错误解决:

shape = model.layers[-1].output_shape
# shape = model.get_output_shape_at(0)

错误原因解析

  • model.get_output_shape_at(0)需要模型已经接收过输入数据(即被调用过),才能生成实际的输出形状。在模型构建阶段还未传入数据,因此无法获取形状,触发报错。
  • model.layers[-1].output_shape是通过层的定义(如卷积核大小、步长、池化规则)推导出来的理论输出形状,不需要模型实际运行,因此在构建阶段即可正常获取。

3DCNN输出转LSTM输入的核心逻辑

唇读模型中,3DCNN负责提取视频序列的时空特征,LSTM负责处理序列的时间依赖关系,两者的输入输出格式不同,需要通过Reshape层完成适配:

1. 3DCNN的输出格式

3DCNN处理的是视频数据,输入形状为(帧数, 图像高度, 图像宽度, 通道数)(对应代码中的input_shape=(22,100,100,1),22是视频帧数)。经过多轮卷积+池化后,最后一层输出是5维张量:
(批量大小, 处理后的帧数, 特征图高度, 特征图宽度, 通道数)

2. LSTM的输入要求

LSTM需要3维张量作为输入:
(批量大小, 时间步长, 特征向量维度)
其中时间步长对应序列的连续单元(唇读场景下通常是视频帧数),每个时间步需要传入一个一维的特征向量。

3. Reshape层的作用

通过model.layers[-1].output_shape获取3DCNN最后一层的输出形状后,代码做了两个计算:

  • shape[-1]:取3DCNN输出的通道数
  • shape[1]*shape[2]*shape[3]:计算每个通道对应的空间特征总维度(处理后的帧数×特征图高度×特征图宽度)

Reshape层将5维的时空特征张量转换为3维张量,让LSTM可以按通道维度作为"时间步长",每个时间步对应一组展平后的空间特征,从而完成3DCNN到LSTM的数据传递。

注:从唇读的逻辑来看,更合理的转换应该是将帧数作为时间步长,此时Reshape参数应为(shape[1], shape[2]*shape[3]*shape[4]),原代码的参数可能存在维度顺序的笔误,但核心适配逻辑是一致的——将空间特征展平为一维向量,匹配LSTM的输入格式。

内容的提问来源于stack exchange,提问作者Deepak Pawade

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 19:30:54