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
相关产品推荐
相关产品推荐

