基于论文实现InceptionEEGNet时torch.cat尺寸匹配报错求助
问题分析与修复方案
错误核心原因
torch.cat拼接时,除通道维度(dim=1)外的时间维度尺寸不匹配:
- x1、x2经过
padding='same'的卷积后,时间维度保持为128 - x3通过
AvgPool2d((1,2))、x4通过stride=(1,2)将时间维度压缩为64
两者维度冲突导致拼接失败。同时还有隐藏问题:拼接后通道数为64×4=256,但batchnorm2d_elu_2中的BatchNorm2d设置为64,会引发后续通道不匹配错误。
修复步骤
1. 统一Inception分支的时间维度
给x1、x2的第二个卷积层添加stride=(1,2),让它们的时间维度和x3、x4一致(压缩为64):
self.inception_block_1 = nn.Sequential( nn.Conv2d(256,64,(1,1),padding='same'), nn.Conv2d(64,64,(1,7),padding='same', stride=(1,2)), # 添加stride压缩时间维度 ) self.inception_block_2 = nn.Sequential( nn.Conv2d(256,64,(1,1),padding='same'), nn.Conv2d(64,64,(1,9),padding='same', stride=(1,2)), # 添加stride压缩时间维度 )
2. 修正BatchNorm的通道数
将batchnorm2d_elu_2中的BatchNorm2d改为256,匹配拼接后的总通道数:
self.batchnorm2d_elu_2 = nn.Sequential( nn.BatchNorm2d(256), # 从64改为256 nn.ELU(), nn.Dropout2d(p=0.5) )
3. 优化自适应池化层(可选)
原代码用F.adaptive_avg_pool3d处理4D张量不合理,改为F.adaptive_avg_pool2d更贴合输入维度:
x = F.adaptive_avg_pool2d(x, (1,3))
完整修复代码
import torch from torch import nn import torch.nn.functional as F class DepthwiseConv2d(torch.nn.Conv2d): def __init__(self, in_channels, depth_multiplier=1, kernel_size=3, stride=1, padding=0, dilation=1, bias=True, padding_mode='zeros' ): out_channels = in_channels * depth_multiplier super().__init__( in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, stride=stride, padding=padding, dilation=dilation, groups=in_channels, bias=bias, padding_mode=padding_mode ) class InceptionEEGNet(nn.Module): def __init__(self, bathsize): # input = (1,22,256) super().__init__() self.bathsize = bathsize self.conv2d_1 = nn.Conv2d(1,64,(1,16),padding='same') self.batchnorm2d_1 = nn.BatchNorm2d(64) self.conv2d_2 = DepthwiseConv2d(64,depth_multiplier=4,kernel_size=(22,1),padding='valid') self.batchnorm2d_elu_1 = nn.Sequential( nn.BatchNorm2d(256), nn.ELU() ) self.averagepooling = nn.Sequential( nn.AvgPool2d((1,2)), nn.Dropout2d(p=0.5) ) self.inception_block_1 = nn.Sequential( nn.Conv2d(256,64,(1,1),padding='same'), nn.Conv2d(64,64,(1,7),padding='same', stride=(1,2)), ) self.inception_block_2 = nn.Sequential( nn.Conv2d(256,64,(1,1),padding='same'), nn.Conv2d(64,64,(1,9),padding='same', stride=(1,2)), ) self.inception_block_3 = nn.Sequential( nn.AvgPool2d((1,2)), nn.Conv2d(256,64,(1,1),padding='same'), ) self.inception_block_4 = nn.Conv2d(256,64,(1,1),stride=(1,2)) self.batchnorm2d_elu_2 = nn.Sequential( nn.BatchNorm2d(256), nn.ELU(), nn.Dropout2d(p=0.5) ) self.conv2d_3 = nn.Conv2d(256,256,(1,5),padding='same') def forward(self,x): x = self.conv2d_1(x) x = self.batchnorm2d_1(x) x = self.conv2d_2(x) x = self.batchnorm2d_elu_1(x) x = self.averagepooling(x) x1 = self.inception_block_1(x) x2 = self.inception_block_2(x) x3 = self.inception_block_3(x) x4 = self.inception_block_4(x) x = torch.cat((x1, x2, x3, x4), 1) x = self.batchnorm2d_elu_2(x) x = self.conv2d_3(x) x = self.batchnorm2d_elu_2(x) x = F.adaptive_avg_pool2d(x, (1,3)) x = x.squeeze() return x net = InceptionEEGNet(10) x = torch.rand(10,1,22,256) print(net(x).shape) # 输出应为torch.Size([10, 3])
验证说明
修复后四个分支的输出形状均为(10,64,1,64),拼接后得到(10,256,1,64),后续层可正常处理,最终输出符合预期。
内容的提问来源于stack exchange,提问作者assa
相关产品推荐
相关产品推荐

