PyTorch汽车品牌分类模型训练报错:'Image' object不可下标访问
解决PyTorch汽车品牌分类模型中的'TypeError: Image object is not subscriptable'错误
错误原因分析
从错误栈可定位问题出在CarBrandDataset的__getitem__方法中:
image.transform(image.size, Image.AFFINE, image)
这行代码误用了PIL库的Image.transform方法:该方法的第三个参数data需要传入长度为6的仿射变换参数序列,但你直接传入了Image对象本身。当PIL内部尝试执行data[:6]时,Image对象不支持下标操作,因此触发TypeError: 'Image' object is not subscriptable。
更关键的是,这行代码完全违背你的初衷——你本来应该应用定义好的PyTorch Transform组合,而非调用PIL的底层变换方法。
解决方案
1. 修正Transform的应用方式
修改CarBrandDataset的__getitem__方法,将错误的变换调用替换为正确的PyTorch Transform应用:
def __getitem__(self, index): image_path = os.path.join(self.data_dir, self.image_paths[index]) xml_path = os.path.splitext(image_path)[0] + '.xml' image = Image.open(image_path).convert('L') # 转为灰度图 # 修正:应用PyTorch Transform组合 if self.transform: image = self.transform(image) # 解析XML tree = ET.parse(xml_path) root = tree.getroot() brand_label_mapping = { 'bmw': 0, 'citroen': 1, 'mercedes': 2, 'maserati': 3, 'audi': 4, 'honda': 5 } # 注意:此处需根据XML实际结构调整,示例假设品牌标签在<brand>节点中 brand_label_str = root.find('brand').text.strip() brand_label = brand_label_mapping.get(brand_label_str, -1) return image, brand_label
2. 修正模型全连接层的输入维度
你的CarBrand模型中fc1的输入维度计算错误:
初始输入为300×300的灰度图,经过三次MaxPool2d(kernel_size=2, stride=2)后,尺寸会连续减半三次:
- 第一次池化后:150×150
- 第二次池化后:75×75
- 第三次池化后:37×37(整数除法向下取整)
因此fc1的输入维度应为128 * 37 * 37,而非128*300*300*1,修改模型代码:
self.fc1 = nn.Linear(128 * 37 * 37, 512) # 修正全连接层输入维度
3. 调整Transform的顺序(可选但推荐)
当前Transform的顺序是ToTensor()→Normalize()→Resize(),正确顺序应先调整尺寸,再转张量、归一化,避免归一化后的数据被Resize操作破坏:
transform = transforms.Compose([ transforms.Resize(300), transforms.ToTensor(), transforms.Normalize(mean=[0.5], std=[0.5]), ])
额外注意事项
- 确保XML文件中品牌标签路径正确:原代码中的
root.text大概率无法正确提取品牌名称,需根据你的XML结构调整(比如root.find('brand').text),否则会导致标签为-1,训练无效。 - 检查标签映射覆盖性:确保所有XML中的品牌名称都在
brand_label_mapping中,避免出现无效标签。
内容的提问来源于stack exchange,提问作者Cihan Yalçın
相关产品推荐
相关产品推荐

