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

RuntimeError:矩阵形状不匹配,CNN模型适配频谱输入问题求助

问题分析

报错mat1 and mat2 shapes cannot be multiplied (128x195 and 128x256)的核心原因是全连接层输入维度硬编码,无法适配不同时长音频生成的可变尺寸频谱图。

原模型存在两个明显问题:

  1. 注释与代码逻辑矛盾:卷积池化后注释标注为128x2x2,Flatten后总特征数应为128*2*2=512,但全连接层in_features却写了128,本身就是错误配置。
  2. 硬编码依赖固定输入尺寸:所有卷积、池化层的输出维度绑定输入频谱图的固定尺寸,一旦音频时长变化,频谱图时间轴维度改变,池化后特征尺寸也会变化,导致Flatten后的总特征数与全连接层输入维度不匹配。
彻底解决方案

以下三种方法均可适配任意输入尺寸的频谱图,按需选择:

方法1:自适应池化层(推荐)

使用AdaptiveAvgPool2d或AdaptiveMaxPool2d,强制将卷积后的特征图缩放到固定尺寸(比如(2,2)),这样Flatten后的总特征数固定,全连接层维度无需随输入变化修改。

修改后的模型代码:

model = nn.Sequential(
  nn.Conv2d(1, 32, kernel_size=3, padding=1),
  nn.MaxPool2d(2, 2),
  nn.Conv2d(32, 64, kernel_size=3, padding=1),
  nn.MaxPool2d(2, 2),
  nn.Conv2d(64, 128, kernel_size=3, padding=1),
  # 替换固定池化为自适应池化,强制输出2x2的特征图
  nn.AdaptiveMaxPool2d((2, 2)),
  nn.Flatten(),
  # Flatten后总特征数为128*2*2=512,对应in_features=512
  nn.Linear(in_features=512, out_features=256),
  nn.ReLU(),
  nn.Linear(in_features=256, out_features=80)
)

方法2:全局池化层(极简)

使用全局平均/最大池化,将每个通道的特征图压缩为单个值,Flatten后总特征数等于通道数(128),完全不依赖输入尺寸。

修改后的模型代码:

model = nn.Sequential(
  nn.Conv2d(1, 32, kernel_size=3, padding=1),
  nn.MaxPool2d(2, 2),
  nn.Conv2d(32, 64, kernel_size=3, padding=1),
  nn.MaxPool2d(2, 2),
  nn.Conv2d(64, 128, kernel_size=3, padding=1),
  # 全局平均池化,每个通道输出1个值
  nn.AdaptiveAvgPool2d((1, 1)),
  nn.Flatten(),
  # Flatten后总特征数为128*1*1=128,对应in_features=128
  nn.Linear(in_features=128, out_features=256),
  nn.ReLU(),
  nn.Linear(in_features=256, out_features=80)
)

方法3:动态计算输入维度(兼容原有池化逻辑)

如果不想修改池化层结构,可以在模型初始化时传入一个样例输入,动态计算Flatten后的特征数,再创建全连接层。注意模型保存/加载时需先重构结构再加载参数,避免动态结构导致的加载失败。

示例代码:

# 先定义卷积池化部分
conv_layers = nn.Sequential(
  nn.Conv2d(1, 32, kernel_size=3, padding=1),
  nn.MaxPool2d(2, 2),
  nn.Conv2d(32, 64, kernel_size=3, padding=1),
  nn.MaxPool2d(2, 2),
  nn.Conv2d(64, 128, kernel_size=3, padding=1),
  nn.MaxPool2d(2, 2, padding=1),
  nn.Flatten()
)

# 用样例输入计算Flatten后的维度
sample_input = torch.randn(1, 1, spectrogram.shape[1], spectrogram.shape[2])  # 匹配频谱图的通道、频率、时间维度
flattened_dim = conv_layers(sample_input).shape[1]

# 拼接完整模型
model = nn.Sequential(
  conv_layers,
  nn.Linear(in_features=flattened_dim, out_features=256),
  nn.ReLU(),
  nn.Linear(in_features=256, out_features=80)
)
额外注意事项
  • 模型保存建议用torch.save(model.state_dict(), 'model.pt')而非直接保存模型实例,加载时需先重新构建模型结构,再加载参数,避免动态结构导致的加载失败。
  • 不同音频预处理时,需保证采样率、窗口参数(nperseg/noverlap)一致,否则频谱图的频率轴维度会变化,仍可能导致卷积层维度不匹配(上述方法已解决时间轴的可变问题)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:45:25