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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:35:57