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

使用make_grid预览数据集触发异常,寻求技术解决方案

解决DataLoader多进程加载PIL图像时的AttributeError问题

问题场景

尝试通过make_grid()可视化数据集图像,但从DataLoader获取批量数据时触发以下错误:

AttributeError: 'NoneType' object has no attribute 'seek'
AttributeError: 'JpegImageFile' object has no attribute 'load_seek'

错误发生在执行first_batch = next(iter(image_dataloader))时,自定义Dataset基于4000+张PIL图像对象的列表构建,DataLoader设置了num_workers=4。

错误原因

PIL图像对象(如JpegImageFile)不支持跨进程序列化与传递。当DataLoader启用多进程(num_workers>0)时,主进程会尝试将PIL对象传递给子进程,这个过程中对象会失效,导致后续调用出现属性缺失错误。

解决方案

1. 最佳方案:存储图像路径,实时加载

修改Dataset,不再直接存储PIL对象,而是保存图像文件路径,在__getitem__方法中实时加载图像。每个子进程会独立完成图像加载与预处理,避免进程间传递PIL对象的问题。

修改后的代码示例:

from PIL import Image
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms as v2
from torchvision.utils import make_grid, ToPILImage

class CustomDS(Dataset):
    def __init__(self, image_paths, transform=None):
        self.image_paths = image_paths
        self.transform = transform

    def __len__(self):
        return len(self.image_paths)

    def __getitem__(self, idx):
        # 实时加载图像并转成RGB格式(避免灰度图通道数问题)
        pil_img = Image.open(self.image_paths[idx]).convert("RGB")
        if self.transform:
            pil_img = self.transform(pil_img)
        return pil_img

# 定义预处理流程
image_transformations = v2.Compose([
    v2.Resize((224, 224)),
    v2.PILToTensor(),
    v2.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

# 替换为你的图像路径列表
image_dataset = CustomDS(image_paths, image_transformations)
image_dataloader = DataLoader(image_dataset, batch_size=IN_BATCH_SIZES, shuffle=False, num_workers=4)

# 获取批量数据并可视化
first_batch = next(iter(image_dataloader))
grid = make_grid(first_batch, nrow=8)

# 反归一化:将[-1,1]范围的张量转回[0,1],否则PIL显示异常
inv_normalize = v2.Normalize(
    mean=[-0.485/0.229, -0.456/0.224, -0.406/0.225],
    std=[1/0.229, 1/0.224, 1/0.225]
)
grid = inv_normalize(grid)

to_pil = ToPILImage()(grid)
to_pil.show()

2. 临时调试方案:禁用多进程

如果只是临时调试,可以将DataLoader的num_workers设为0,强制在主进程加载数据,避免进程间传递问题。但此方法会降低数据加载效率,不适合大规模数据集:

image_dataloader = DataLoader(image_dataset, batch_size=IN_BATCH_SIZES, shuffle=False, num_workers=0)

额外注意

  • 执行Normalize后,张量值范围为[-1,1],直接转PIL图像会显示异常(全黑或颜色失真),必须先执行反归一化操作。
  • 加载图像时添加.convert("RGB"),确保所有图像都是3通道格式,避免单通道灰度图导致的张量形状不匹配问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 23:08:16