使用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
相关产品推荐
相关产品推荐

