PyTorch模型定义报错:npy数据集输入尺寸与形状不匹配求助
解决PyTorch模型输入尺寸与形状不匹配问题
错误原因分析
- 全连接层输入尺寸计算错误:你直接用原始数据的总元素数作为全连接层输入尺寸,但经过卷积和池化后,张量尺寸已被压缩,两者不匹配导致
view操作失败。 - 标签形状不符合损失函数要求:若为分类任务,
CrossEntropyLoss要求标签是每个样本对应的类别索引(形状应为(batch_size,)),但你的标签形状与输入数据完全一致,明显不匹配;若为语义分割任务,当前模型是分类结构,无法输出与输入尺寸一致的结果。
修正方案(分两种任务场景)
场景1:图像分类任务(每个样本对应一个标签)
假设data.npy包含401个701×255的单通道图像,标签应为401个类别索引(0或1)。
修正后的代码:
import numpy as np import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset import torch.nn.functional as f # 加载数据 data = np.load("other py files/project_files/data/train/data.npy") # (401, 701, 255) labels = np.load("other py files/project_files/data/train/label.npy") # 调整标签形状为(401,),需根据实际任务逻辑修改,此处为示例 labels = labels[:, 0, 0] # 转换为张量并调整维度:PyTorch卷积层要求输入格式为(batch_size, channels, height, width) data_tensor = torch.Tensor(data).unsqueeze(1) # (401, 1, 701, 255) labels_tensor = torch.LongTensor(labels) # CrossEntropyLoss要求标签为Long类型 class MyModel(nn.Module): def __init__(self): super(MyModel, self).__init__() self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) # 计算两次池化后的特征图尺寸:701→350→175,255→127→63 self.fc_input_size = 64 * 175 * 63 self.fc = nn.Linear(self.fc_input_size, 2) def forward(self, x): x = self.pool(f.relu(self.conv1(x))) x = self.pool(f.relu(self.conv2(x))) x = x.view(-1, self.fc_input_size) x = self.fc(x) return x model = MyModel() print(model) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) dataset = TensorDataset(data_tensor, labels_tensor) dataloader = DataLoader(dataset, batch_size=32, shuffle=True) num_epochs = 10 for epoch in range(num_epochs): running_loss = 0.0 for i, (inputs, labels) in enumerate(dataloader, 0): optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 100 == 99: print(f"[{epoch + 1}, {i + 1}] 损失值:{running_loss / 100}") running_loss = 0.0 with torch.no_grad(): predictions = model(data_tensor)
场景2:语义分割任务(逐像素分类)
若任务是逐像素分类,模型需输出与输入尺寸一致的特征图,需用转置卷积恢复尺寸,而非全连接层:
修正后的代码:
import numpy as np import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset import torch.nn.functional as f # 加载数据 data = np.load("other py files/project_files/data/train/data.npy") # (401, 701, 255) labels = np.load("other py files/project_files/data/train/label.npy") # (401, 701, 255) # 转换为张量并调整维度 data_tensor = torch.Tensor(data).unsqueeze(1) # (401, 1, 701, 255) labels_tensor = torch.LongTensor(labels) # 标签为Long类型 class SegmentationModel(nn.Module): def __init__(self): super(SegmentationModel, self).__init__() # 编码层:卷积+池化压缩特征 self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1) # 解码层:转置卷积恢复原始尺寸 self.deconv1 = nn.ConvTranspose2d(64, 32, kernel_size=2, stride=2) self.deconv2 = nn.ConvTranspose2d(32, 2, kernel_size=2, stride=2) # 输出2通道对应2类 def forward(self, x): # 编码过程 x1 = f.relu(self.conv1(x)) x_pool1 = self.pool(x1) x2 = f.relu(self.conv2(x_pool1)) x_pool2 = self.pool(x2) # 解码过程 x_deconv1 = f.relu(self.deconv1(x_pool2)) x_out = self.deconv2(x_deconv1) return x_out model = SegmentationModel() print(model) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # 分割任务显存占用高,调小batch_size dataset = TensorDataset(data_tensor, labels_tensor) dataloader = DataLoader(dataset, batch_size=8, shuffle=True) num_epochs = 10 for epoch in range(num_epochs): running_loss = 0.0 for i, (inputs, labels) in enumerate(dataloader, 0): optimizer.zero_grad() outputs = model(inputs) # 调整形状以匹配损失函数要求 loss = criterion(outputs.view(-1, 2), labels.view(-1)) loss.backward() optimizer.step() running_loss += loss.item() if i % 10 == 9: print(f"[{epoch + 1}, {i + 1}] 损失值:{running_loss / 10}") running_loss = 0.0 with torch.no_grad(): predictions = model(data_tensor)
关键注意事项
- 跟踪张量形状:在模型前向传播中可添加
print(x.shape),实时查看每一步张量尺寸,确保后续操作匹配。 - 匹配损失函数要求:分类任务中输出为
(batch_size, num_classes)、标签为(batch_size,);分割任务中输出为(batch_size, num_classes, height, width)、标签为(batch_size, height, width)。 - 明确数据维度含义:确认数据集各维度代表的意义(样本数、通道数、高、宽),PyTorch卷积层默认输入格式为
(batch_size, channels, height, width)。
内容的提问来源于stack exchange,提问作者Hanzo Hasashi
相关产品推荐
相关产品推荐

