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

PyTorch模型输出形状不匹配求助:期望[64,1]却得到[64,64,1]

问题描述

运行batch size为64、DNA序列长度1000的神经网络模型,DNA序列采用独热编码(张量结构为(1000,4)),训练时触发以下警告:

UserWarning: Using a target size (torch.Size([64, 1])) that is different to the input size (torch.Size([64, 64, 1]))

期望模型输出形状为torch.Size([64,1]),但实际输出为torch.Size([64,64,1])。

模型代码如下:

class model_test(nn.Module): # deepcre model  
def __init__(self,
             seq_len: int =1000,
             kernel_size: int = 8,
             p = 0.25): # drop out value 
    super().__init__()
    self.seq_len = seq_len
    # adjusting window size corresponding to sequence length 
    window_size = int(seq_len*(8/3000)) # 8/3 =^ 2.6 
    
    # CNN module
    self.conv11 = Conv1d(4,64,kernel_size=(kernel_size),stride = 1,padding = 1)
    self.relu11 = ReLU()
    self.maxpool1 = MaxPool1d(kernel_size=window_size)
    self.Dropout1 = Dropout(p)
    self.fc1 =Linear(497,1) #batch_size_init*(seq_len//window_size) , 1) # 1000-2*1-1/2 

def forward(self, x):
    """Forward pass."""
    
    x = x.permute(0,2,1)
    x = self.conv11(x)
    x = self.relu11(x)
    x = self.maxpool1(x)
    x = self.Dropout1(x)
    x = self.fc1(x)

    return x
问题分析

输出维度不匹配的核心原因是全连接层的输入维度逻辑错误:

  1. 输入张量经过permute(0,2,1)后,形状变为(64,4,1000)(batch_size=64,通道数4,序列长度1000)
  2. 经过Conv1d后,输出序列长度计算为(1000 -8 +2*1)//1 +1 = 995,形状变为(64,64,995)
  3. MaxPool1d使用window_size=2,池化后序列长度为995//2=497,形状变为(64,64,497)
  4. 此时直接接入Linear(497,1),PyTorch的Linear仅对最后一个维度做变换,输出形状变为(64,64,1),与目标(64,1)不匹配。
解决方法

方案1:全局池化压缩通道维度(推荐)

在Dropout后添加全局平均/最大池化,将通道维度的特征压缩为单值,再接入全连接层:

修改forward函数:

def forward(self, x):
    """Forward pass."""
    
    x = x.permute(0,2,1)
    x = self.conv11(x)
    x = self.relu11(x)
    x = self.maxpool1(x)
    x = self.Dropout1(x)
    # 全局平均池化,将(64,64,497)转为(64,64)
    x = torch.mean(x, dim=2)
    # 也可使用全局最大池化:x = torch.max(x, dim=2)[0]
    x = self.fc1(x)

    return x

修改全连接层输入维度:

self.fc1 = Linear(64,1)

最终输出形状为(64,1),符合要求,且参数数量适中,避免过拟合。

方案2:展平维度后接入全连接层

将池化后的三维张量展平为二维,再用对应输入维度的全连接层输出单值:

修改forward函数:

def forward(self, x):
    """Forward pass."""
    
    x = x.permute(0,2,1)
    x = self.conv11(x)
    x = self.relu11(x)
    x = self.maxpool1(x)
    x = self.Dropout1(x)
    # 展平通道与序列维度:(64,64,497) -> (64,64*497)
    x = x.flatten(start_dim=1)
    x = self.fc1(x)

    return x

修改全连接层输入维度:

self.fc1 = Linear(64*497,1)

此方法保留所有空间特征,但参数数量大幅增加,容易引发过拟合,需配合更强的正则化手段。

方案3:调整池化窗口至序列长度为1

修改池化窗口大小,让池化后序列长度变为1,再挤压通道维度:

修改__init__中的池化层:

self.maxpool1 = MaxPool1d(kernel_size=497) # 池化后序列长度为1

修改forward函数:

def forward(self, x):
    """Forward pass."""
    
    x = x.permute(0,2,1)
    x = self.conv11(x)
    x = self.relu11(x)
    x = self.maxpool1(x)
    x = self.Dropout1(x)
    x = self.fc1(x) # 输出形状(64,64,1)
    x = torch.mean(x, dim=1) # 挤压通道维度至(64,1)

    return x

修改全连接层:

self.fc1 = Linear(1,1)

此方法逻辑繁琐,灵活性差,不推荐使用。

内容的提问来源于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.13 05:09:51