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

动作识别场景下如何将3DCNN输出的5D张量输入至LSTM?模型实现求助

解决3DCNN与LSTM结合的维度适配问题

我明白你在动作识别研究中结合3DCNN和LSTM时遇到的维度匹配卡点——这是这类混合模型非常常见的问题,核心就是3DCNN的输出形状和LSTM的输入要求不匹配。下面我帮你拆解问题,给出可直接运行的修改方案。

先理清核心问题:维度不匹配

你的输入是[1, 3, 16, 112, 112],对应[batch_size, channels, frames, height, width]。按照你原有的3DCNN架构,经过pool5后,时间维度(frames)会被压缩到1,这样LSTM根本没有序列可以处理;而且3DCNN输出的5维张量也不符合LSTM需要的3维(或带batch的3维)输入格式。

修改后的完整代码方案

我调整了pool5的池化参数保留时间维度,同时添加了LSTM层和维度转换的逻辑:

import torch
import torch.nn as nn

class C3D_LSTM(nn.Module):
    def __init__(self, num_classes=10):
        super(C3D_LSTM, self).__init__()
        # 原有的3DCNN层
        self.conv1 = nn.Conv3d(3, 64, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool1 = nn.MaxPool3d(kernel_size=(1, 2, 2), stride=(1, 2, 2))
        self.conv2 = nn.Conv3d(64, 128, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool2 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2))
        self.conv3a = nn.Conv3d(128, 256, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.conv3b = nn.Conv3d(256, 256, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool3 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2))
        self.conv4a = nn.Conv3d(256, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.conv4b = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.pool4 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2))
        self.conv5a = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        self.conv5b = nn.Conv3d(512, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1))
        
        # 关键调整:修改pool5的时间维度池化参数,保留序列长度(原参数会把frames压到1)
        self.pool5 = nn.MaxPool3d(kernel_size=(1, 2, 2), stride=(1, 2, 2), padding=(0, 1, 1))
        self.relu = nn.ReLU()
        
        # 添加LSTM层:input_size是3DCNN输出的通道数×空间维度乘积(512*4*4)
        # batch_first=True让输入格式为[batch_size, seq_len, input_size],更符合我们的习惯
        self.lstm = nn.LSTM(input_size=512*4*4, hidden_size=256, num_layers=2, batch_first=True)
        # 最后分类的全连接层
        self.fc = nn.Linear(256, num_classes)

    def forward(self, x):
        # 3DCNN前向传播
        x = self.relu(self.conv1(x))
        x = self.pool1(x)
        
        x = self.relu(self.conv2(x))
        x = self.pool2(x)
        
        x = self.relu(self.conv3a(x))
        x = self.relu(self.conv3b(x))
        x = self.pool3(x)
        
        x = self.relu(self.conv4a(x))
        x = self.relu(self.conv4b(x))
        x = self.pool4(x)
        
        x = self.relu(self.conv5a(x))
        x = self.relu(self.conv5b(x))
        x = self.pool5(x)  # 此时形状:[batch_size, 512, seq_len, 4, 4]
        
        # 维度转换:把5维3DCNN输出转换成LSTM需要的3维格式
        batch_size = x.size(0)
        seq_len = x.size(2)
        # 展平空间维度,并调整维度顺序
        x = x.permute(0, 2, 1, 3, 4).contiguous()  # 变成[batch_size, seq_len, 512, 4, 4]
        x = x.view(batch_size, seq_len, -1)  # 展平空间维度,最终形状:[batch_size, seq_len, 512*4*4]
        
        # LSTM前向传播:初始化隐藏状态和细胞状态(可选,PyTorch会默认初始化0)
        h0 = torch.zeros(self.lstm.num_layers, batch_size, self.lstm.hidden_size).to(x.device)
        c0 = torch.zeros(self.lstm.num_layers, batch_size, self.lstm.hidden_size).to(x.device)
        lstm_out, _ = self.lstm(x, (h0, c0))
        
        # 取LSTM最后一个时间步的输出做分类(也可以取所有时间步输出做平均)
        out = lstm_out[:, -1, :]
        out = self.fc(out)
        
        return out

# 测试一下模型
if __name__ == "__main__":
    model = C3D_LSTM(num_classes=10)
    input_tensor = torch.randn(1, 3, 16, 112, 112)  # 你的输入尺寸
    output = model(input_tensor)
    print(f"输入形状: {input_tensor.shape}")
    print(f"输出形状: {output.shape}")  # 应该是[1,10],对应batch_size=1,10个类别

关键注意事项

  • 序列长度保留:原pool5的(2,2,2)池化会把时间维度从2压缩到1,完全失去时序信息。我改成了(1,2,2),保留了时间维度长度为2,你也可以调整前面的pool4为(1,2,2),让序列长度变成4,增强LSTM的时序捕捉能力。
  • 维度转换逻辑:通过permute调整维度顺序,再用view展平空间维度,确保输入LSTM的格式是[batch_size, seq_len, input_size]。
  • 设备对齐:初始化LSTM的隐藏状态时,一定要和输入张量在同一个设备(CPU/GPU)上,避免运行时报错。
  • LSTM输出选择:这里取最后一个时间步的输出做分类,你也可以根据任务需求,对所有时间步的输出做平均、最大池化等操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:04:09