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

Keras转PyTorch:3层CNN模型迁移遇维度匹配错误求助

解决PyTorch双输入CNN模型维度不匹配问题

错误原因分析

你遇到的mat1 and mat2 shapes cannot be multiplied错误,本质是全连接层的输入特征维度与权重矩阵的输入维度不匹配。以你给出的报错信息来看:

  • 2048x1920是批量数据的特征形状(2048是batch_size,1920是单样本的总特征数)
  • 128000x1是全连接层的权重形状(128000是权重的输入维度,1是输出维度)
    显然你把全连接层的in_features设成了128000,但实际输入的特征数只有1920,导致矩阵乘法无法执行。

核心解决思路

要修复这个问题,你需要精准计算两个输入分支拼接后的总特征维度,再对应设置全连接层的in_features参数。具体步骤如下:

1. 明确原Keras模型的核心参数

先把原Keras模型的关键参数列出来(以下是基于常见DNA序列预测模型的假设,你需要替换成自己的实际参数):

  • 独热编码输入形状:input_shape_hot = (seq_len, 4)(比如seq_len=1000,4种碱基独热)
  • 数值输入形状:input_shape_val = (n_val_features,)(比如n_val_features=20)
  • CNN层参数:
    • 第一层:filters=64, kernel_size=9, padding='same', pool_size=2
    • 第二层:filters=128, kernel_size=9, padding='same', pool_size=2
    • 第三层:filters=256, kernel_size=9, padding='same', pool_size=2
  • Dropout率:0.2
  • 全连接层:第一层比如1024,第二层1(输出表达值)

2. 对应编写PyTorch模型(含维度计算)

PyTorch的张量是通道在前(与Keras的通道在后不同),所以输入要调整为(batch_size, 4, seq_len)。以下是完整的模型代码,重点标注维度计算过程:

import torch
import torch.nn as nn
import torch.nn.functional as F

class DNAExpressionPredictor(nn.Module):
    def __init__(self, seq_len, n_val_features):
        super().__init__()
        # CNN分支(处理独热编码DNA序列)
        self.cnn_layers = nn.Sequential(
            # 第一层CNN
            nn.Conv1d(in_channels=4, out_channels=64, kernel_size=9, padding='same'),
            nn.BatchNorm1d(64),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.MaxPool1d(kernel_size=2),
            # 第二层CNN
            nn.Conv1d(in_channels=64, out_channels=128, kernel_size=9, padding='same'),
            nn.BatchNorm1d(128),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.MaxPool1d(kernel_size=2),
            # 第三层CNN
            nn.Conv1d(in_channels=128, out_channels=256, kernel_size=9, padding='same'),
            nn.BatchNorm1d(256),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.MaxPool1d(kernel_size=2)
        )
        
        # 计算CNN分支输出的特征数:256 * (seq_len // (2*2*2))
        # 比如seq_len=1000,1000//8=125,所以256*125=32000
        self.cnn_feature_dim = 256 * (seq_len // 8)
        # 拼接后的总特征数:CNN特征数 + 数值输入特征数
        self.total_feature_dim = self.cnn_feature_dim + n_val_features
        
        # 全连接层
        self.fc_layers = nn.Sequential(
            nn.Linear(self.total_feature_dim, 1024),
            nn.ReLU(),
            nn.Linear(1024, 1)
        )
    
    def forward(self, hot_input, val_input):
        # 处理CNN分支:hot_input形状是(batch_size, 4, seq_len)
        cnn_out = self.cnn_layers(hot_input)
        # 展平CNN输出:(batch_size, 256, seq_len//8) → (batch_size, 256*(seq_len//8))
        cnn_out_flat = torch.flatten(cnn_out, start_dim=1)
        
        # 处理数值输入:val_input形状是(batch_size, n_val_features),无需展平
        # 拼接两个分支的特征
        concatenated = torch.cat([cnn_out_flat, val_input], dim=1)
        
        # 全连接层输出
        output = self.fc_layers(concatenated)
        return output

# 实例化模型(替换成你的实际seq_len和n_val_features)
model = DNAExpressionPredictor(seq_len=1000, n_val_features=20)
# 测试前向传播
batch_size = 32
hot_input = torch.randn(batch_size, 4, 1000)
val_input = torch.randn(batch_size, 20)
output = model(hot_input, val_input)
print(output.shape)  # 应该输出torch.Size([32, 1])

3. 调试技巧

如果还是不确定维度,可以在forward函数中添加打印语句,查看每一步的张量形状:

def forward(self, hot_input, val_input):
    print("初始hot_input形状:", hot_input.shape)
    cnn_out = self.cnn_layers(hot_input)
    print("CNN输出形状:", cnn_out.shape)
    cnn_out_flat = torch.flatten(cnn_out, start_dim=1)
    print("展平后CNN特征形状:", cnn_out_flat.shape)
    print("数值输入形状:", val_input.shape)
    concatenated = torch.cat([cnn_out_flat, val_input], dim=1)
    print("拼接后总特征形状:", concatenated.shape)
    output = self.fc_layers(concatenated)
    return output

运行测试代码后,根据打印出的拼接后总特征形状的第二个维度(比如1920),把全连接层的第一个Linear的in_features设为这个数值即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:22:06