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

如何解决PyTorch训练时报ValueError: too many values to unpack (expected 2)错误?

错误原因

你遇到的报错核心是两个问题叠加导致的:

  1. 自定义Col数据集类的__getitem__方法仅返回单张图像张量,而训练代码中尝试将每个batch解包为inputs, targets两个值,返回值数量不匹配触发报错。
  2. 数据集划分逻辑错误:torch.utils.data.random_split接收的参数应为Dataset实例,你错误传入了DataLoader实例,且后续调用train函数时额外追加了.dataset属性,导致遍历对象不符合预期。
解决步骤

步骤1:修改自定义Dataset类,补充标签返回逻辑

默认假设你的图片按类别存放在root_dir的子文件夹下(例如./images/cat/xxx.jpg、./images/dog/xxx.jpg),修改Col类代码如下:

class Col(Dataset):
    def __init__(self, main_dir, transform):
        self.main_dir = main_dir
        self.transform = transform
        # 生成类别到数字ID的映射
        self.class_names = sorted([d for d in os.listdir(main_dir) if os.path.isdir(os.path.join(main_dir, d))])
        self.class_to_idx = {cls_name: idx for idx, cls_name in enumerate(self.class_names)}
        all_images = self.all_img(main_dir = main_dir)
        self.total_imges = natsort.natsorted(all_images)
 
    def __len__(self):
        return len(self.total_imges)
 
    def __getitem__(self, idx):
        img_loc = os.path.join(self.total_imges[idx])
        image = Image.open(img_loc).convert("RGB")
        tensor_image = self.transform(image)
        # 提取当前图片所属类别,转换为数字标签
        cls_name = os.path.basename(os.path.dirname(img_loc))
        target = self.class_to_idx[cls_name]
        # 返回二元组,匹配训练代码的解包逻辑
        return tensor_image, target
 
    def all_img(self, main_dir):
        img = []     
        for path, subdirs, files in os.walk(main_dir):
            for name in files:
                img.append(os.path.join(path, name))
        return img

如果你的标签存储逻辑和上述按子文件夹分类的方式不同,只需保证__getitem__返回(图像张量, 标签)的二元组即可。


步骤2:修正数据集划分与DataLoader创建逻辑

将原有的数据集划分代码替换为如下内容:

transform = transforms.Compose([
    transforms.Resize((224, 224)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5457, 0.5457, 0.5457], std=[0.2342, 0.2342, 0.2342])    
])
 
data = Col(main_dir=root_dir, transform=transform)
# 先对Dataset做划分,再分别创建训练、验证的DataLoader
train_dataset, val_dataset = torch.utils.data.random_split(
    data, 
    [round(len(data)*0.7), len(data) - round(len(data)*0.7)]
)
train_loader = DataLoader(train_dataset, batch_size=130, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=130, shuffle=False)

步骤3:修正train函数调用参数

调用train函数时直接传入创建好的DataLoader对象即可,不需要追加.dataset:

train(model, optimizer, torch.nn.CrossEntropyLoss(), train_loader, val_loader, epochs=100, device=device)

内容的提问来源于stack exchange,提问作者ZealotTV

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:51:02