原帖在 Normalize 中失败;虽然定义了返回 RGB 的 pil_loader,实际 getitem 却直接调用 Image.open,没有使用它:
RuntimeError: output with shape [1, 224, 224] doesn't match the broadcast shape [3, 224, 224]
定义了 RGB loader,还要确认取样时真的调用
原题给出 pil_loader 的 RGB 转换,但 getitem 直接 Image.open,实际样本因此可能仍是灰度。Normalize 收到 [1,H,W] 与三通道 mean/std 就冲突。应修真实取图路径,而非仅修改一段没有被调用的辅助函数。
因此数据集中某些灰度图可能仍只有一个通道,而 Normalize 传了三组 mean/std。这个错误发生在数据预处理,不能靠修改 AlexNet 的分类头解决。
先针对失败样本路径检查原图。image_path 是数据集拼出的实际文件路径:
from PIL import Image
with Image.open(image_path) as image:
original_mode, original_size = image.mode, image.size
rgb = image.convert("RGB")
print("josh050608")
print("mode/size:", original_mode, original_size)
print("converted mode:", rgb.mode)
在 getitem 中使用已有的 RGB loader,或改为明确转换:
with Image.open(image_path) as source:
image = source.convert("RGB")
if self.transform is not None:
image = self.transform(image)
return image, target
target 沿用原数据集的类别编号,路径构造也保持原有 split 逻辑。后续 ToTensor 会得到 [3,H,W],再用三通道 Normalize。
若任务真的使用灰度模型,则应统一为单通道图、单组统计量,并配套修改网络输入层;这与原题 RGB AlexNet 的方案不同。不要把无条件 repeat 放在 RGB 图像上,否则可能得到九个通道;PIL 图像本身也没有 Tensor.repeat 方法。
验证应覆盖灰度与彩色样本,单张变换后均为 [3,224,224],再取完整 batch。若还有 worker 错误,先用 num_workers=0 找到具体图片和变换位置。
灰度、RGB、RGBA 都在读取边界统一
下面仅用 Pillow 和 NumPy 生成内存图片,验证转 RGB 后通道数固定为 3;不依赖 torchvision,也不读取 Caltech 文件:
from PIL import Image
import numpy as np
for mode in ("L", "RGB", "RGBA"):
source = Image.new(mode, (5, 4))
converted = source.convert("RGB")
array = np.asarray(converted)
assert converted.mode == "RGB"
assert array.shape == (4, 5, 3)
chw = array.transpose(2, 0, 1)
assert chw.shape == (3, 4, 5)
print("mode/shape:", mode, converted.mode, chw.shape)
真实 Dataset 在文件上下文中完成 convert,得到可独立使用的图像后再执行 transform。若 RGBA 的透明背景有任务含义,还需按数据规范决定合成背景方式;“统一 RGB”解决通道契约,不自动决定透明像素的业务解释。
检索错误样本时先设 num_workers=0,输出文件路径、原 mode 与转换后 shape。覆盖至少一张灰度和一张彩色样本,再取真实 batch,避免只检查恰好为 RGB 的 dataset[0]。
若模型确实改成灰度输入,则数据、Normalize 与首层卷积一起改成单通道。对原题 RGB 模型,不要对所有图片无条件 repeat(3,...),三通道本来正常的图片会变成九通道。
参考:原始求助帖;技术依据:torchvision Normalize(0.20)、torchvision ToTensor(0.20)、PyTorch 数据加载(2.5)、Pillow 图像打开与转换。