原帖的训练变换先 ToTensor,再 RandomHorizontalFlip;旧接口仍要求翻转输入为 PIL:
TypeError: img should be PIL Image. Got <class 'torch.Tensor'>
旧变换链应在类型边界两侧安排操作
原题 RandomHorizontalFlip 在 ToTensor 后收到 Tensor,旧实现却要求 PIL。反复追加 ToPILImage/ToTensor 会让数据类型来回变化,也可能改变数值范围。先逐步打印每个操作前的类型,再移动真正不兼容的几何变换。
先不要反复在末尾添加 ToPILImage 和 ToTensor。应沿变换序列查清每一步收到什么类型。
train_data 是原题 ImageFolder。先用 loader 读取一张未变换图,逐步执行:
image = train_data.loader(train_data.samples[0][0])
print("josh050608")
print("loaded:", type(image), getattr(image, "size", None))
for operation in train_transforms.transforms:
print("before:", type(operation).__name__, type(image))
image = operation(image)
在原帖旧版接口中,把图像几何变换集中到 ToTensor 前:
from torchvision import transforms
train_transforms = transforms.Compose([
transforms.Resize(255),
transforms.CenterCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])
train_data.transform = train_transforms
修改后重建多进程 loader/迭代器。Normalize 接收张量,不能再移到 ToTensor 前;而现代 torchvision 的某些几何变换也支持 Tensor,是否允许另一种顺序应按实际版本核对,不能用新版能力解释旧报错。
验证单张数据变换通过,再取第一个 batch,检查为 [N,3,224,224]。要显示 images[0],还需先反归一化并从 CHW 转 HWC;直接 plt.imshow(images[0]) 是后续另一个布局问题。
用内存图片检查完整变换顺序
下面示例需要兼容的 torchvision 与 Pillow,生成合成 RGB 图片,不读取 flowers 数据集。顺序面向传统 PIL 几何变换,再转 Tensor、Normalize:
from PIL import Image
import torch
from torchvision import transforms
image = Image.new("RGB", (300, 260), color=(128, 64, 32))
pipeline = transforms.Compose([
transforms.Resize(255), transforms.CenterCrop(224),
transforms.RandomHorizontalFlip(p=1.0), transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]),
])
for operation in pipeline.transforms:
print("before:", type(operation).__name__, type(image).__name__)
image = operation(image)
assert isinstance(image, torch.Tensor)
assert image.shape == (3, 224, 224)
assert torch.isfinite(image).all()
print("final:", image.shape, image.dtype)
Normalize 必须在 Tensor 阶段,mean/std 应对应所用模型与数据,而不是为消除类型异常任意更换。示例沿用原题三通道数值,维护真实预训练模型时仍应核对其配套预处理。
修改 Compose 后,确认 ImageFolder 真正持有新 transform,并重建旧 worker 或迭代器。只更改一个同名全局变量,不保证已有 dataset 引用了新对象。
现代 torchvision 的部分几何操作支持 Tensor,不能拿现代成功结果反推旧版不可能报错。最终先验证单图,再验证真实 batch 与模型输入;显示图片另需反归一化与 CHW→HWC,属于下一步布局检查。
参考:原始求助帖;技术依据:torchvision 0.8 变换文档、torchvision ToTensor(0.20)、torchvision Normalize(0.20)、torchvision 0.2.2 变换顺序、torchvision 0.2.2 变换源码。