img should be PIL Image. Got torch.Tensor:旧 torchvision 把翻转放在 ToTensor 前

简介: 该问题源于`RandomHorizontalFlip`旧版仅支持PIL图像,但被置于`ToTensor`之后导致输入为Tensor而报错。正确做法是将所有几何变换(如Resize、Flip)置于`ToTensor`之前,保持类型兼容;`Normalize`必须在`ToTensor`之后。需检查变换链中每步输入类型,避免冗余转换,并确保Dataset实际应用新transform。

原帖的训练变换先 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 变换源码。

相关文章
|
2天前
|
PyTorch 算法框架/工具 索引
ValueError: only one element tensors can be converted to Python scalars:张量列表先检查形状,再 stack
该文解析PyTorch中`list(tensor)`引发的`ValueError`根源:列表含多元素张量时,不可直接转Python标量。强调应通过`tensor.shape`或遍历打印各张量尺寸来查形状;同形张量用`torch.stack`(增维)而非`cat`或`item`;异形则保留原结构,避免强行转换。
|
2天前
|
缓存 Unix PyTorch
OSError: [Errno 24] Too many open files:两个 DataLoader 可以 zip,先查文件描述符
原帖双Loader并发读取ZIP导致“Too many open files”(Errno 24),实为文件描述符泄漏或生命周期管理不当,非ZIP不支持DataLoader。需排查Dataset中图像/HDF5/ZIP句柄是否及时释放,并优先采用单Loader配对Dataset保障数据一致性与资源可控性。(239字)
|
2天前
|
并行计算 PyTorch 算法框架/工具
Expected all tensors to be on the same device, cuda:0 and cpu:恢复训练时检查 SGD 动量
该问题源于断点续训时优化器状态(如SGD动量缓冲区)未与模型参数同设备,导致`optimizer.step()`中跨设备张量运算失败。前向/反向可正常执行,但动量更新报错“cuda:0 and cpu”。需检查并统一`param`、`grad`及`optimizer.state`中所有Tensor的设备。
|
2天前
|
并行计算 PyTorch Linux
libtorch_python.so: cannot open shared object file:文件缺失时先修复 torch 安装
该问题核心是 PyTorch 1.0.1.post2 安装不完整,`torch/lib/` 下缺失关键文件 `libtorch_python.so`,非环境变量(LD_LIBRARY_PATH)可解决。需先用 `importlib.util.find_spec` 定位真实安装路径,核对文件存在性;再通过 `pip show -f torch` 验证分发完整性。切勿混用版本或复制库文件。
|
2天前
|
并行计算 PyTorch Linux
RuntimeError: CUDA error: device-side assert triggered:Colab 先重启,再找首次断言
该文详解CUDA断言错误调试策略:强调先重启运行时、启用`CUDA_LAUNCH_BLOCKING=1`,用最小张量验证环境;区分“会话已坏”与新操作触发,主张逐段定位而非臆测标签越界,提供实用边界检查函数与验证流程。(239字)
|
2天前
|
并行计算 PyTorch 异构计算
can’t convert CUDA tensor to numpy:只取分类索引时直接用 torch.argmax
原帖因直接对CUDA张量调用`.data.numpy().argmax()`报错:“无法将CUDA张量转为NumPy”。正确做法是:在GPU上用`output.argmax(dim=1).item()`获取单图预测索引,避免全量拷贝,仅传回标量,高效且安全。(239字)
|
2天前
|
数据可视化 PyTorch 算法框架/工具
only batches of spatial targets supported:三通道分割 one-hot 转为每像素类别编号
该报错源于PyTorch交叉熵要求标签为`[N, H, W]`(3D),但输入了`[N, 3, H, W]`(4D)掩码。需先验证三通道是否为互斥one-hot,再用`argmax(dim=1)`转为整型标签,并妥善处理全零未标注像素(设`ignore_index`),避免误判为背景类。(239字)
|
2天前
|
PyTorch 算法框架/工具 异构计算
Expected object of scalar type Float but got scalar type Double for argument #4 'mat1':NumPy 输入与 Linear 权重怎样统一类型
PyTorch中`RuntimeError: Expected Float but got Double`常因输入Tensor(float64)与模型权重(float32)类型不一致导致。关键在第一层Linear的输入与权重dtype需统一:可将数据转为float32(推荐),或模型整体升为float64。务必检查`tensor.dtype`而非数值显示,并确保`loss.backward()`前类型已对齐。(239字)
|
2天前
|
机器学习/深度学习 索引
The size of tensor a (133) must match tensor b (10):分类任务换 MSELoss 后先查标签含义
原帖网络输出133类logits,CrossEntropyLoss支持类别索引输入(如`[10]`),而MSELoss要求`outputs`与`target`形状严格匹配(如`[10,133]`)。报错因`target`为`[10]`,无法广播匹配`[10,133]`输出,本质是两类损失对标签格式约定不同。
|
2天前
|
PyTorch 算法框架/工具 索引
RuntimeError: expected scalar type Long but found Float:NLLLoss 要改 labels,不要把 images 转 long
该问题源于`NLLLoss`要求标签为`torch.long`类型(类别索引),但输入为`float`。需确保标签是整数编号(非概率/小数),并在`DataLoader`中统一配对图像与标签,避免双Loader错位;推荐改用`CrossEntropyLoss`配原始logits,或`LogSoftmax+NLLLoss`组合。(239字)

热门文章

最新文章