如何修复PyTorch报错AttributeError: 'tuple' object has no attribute 'to'
报错原因
- 核心原因1:自定义Dataset返回的标签是字符串类型,没有转换为PyTorch张量,字符串被DataLoader打包后变成字符串元组,自然没有
.to()方法可以调用。同时原代码中__getitem__调用了全局transform而非实例传入的transform参数,属于可优化的小问题。 - 核心原因2:数据划分逻辑错误,
random_split用于切分Dataset实例,你错误传入了DataLoader实例,后续调用训练函数时又传入了.dataset属性,导致遍历逻辑完全混乱。 - 附加错误:验证阶段计算准确率的代码变量名写错,把
labels写成了不存在的targets,修复完当前报错后也会触发该问题。
修复步骤
1. 修改自定义Dataset类,完成标签的数字化和张量转换
先在__init__方法中建立类名到数字索引的映射,再在__getitem__中把标签转为长张量,同时修正transform调用逻辑:
class Col(Dataset): def __init__(self, csv, main_dir, transform): self.df = pd.read_csv(csv) self.main_dir = main_dir self.transform = transform # 建立类名到数字索引的映射,注意此处列名要和CSV实际列名一致,是finding还是Finding注意大小写 self.label_map = {label: idx for idx, label in enumerate(self.df['Finding'].unique())} def __len__(self): return self.df.shape[0] def __getitem__(self, idx): image = self.transform(Image.open(self.df.Image[idx]).convert("RGB")) # 字符串标签转数字,再转成长张量 label = self.label_map[self.df.Finding[idx]] return image, torch.tensor(label, dtype=torch.long)
2. 修正数据划分和加载逻辑
random_split直接切分原始Dataset,切分完成后再分别创建DataLoader:
# 先创建原始Dataset data = Col(main_dir=root_dir, csv=csv_file, transform=transform) # 切分Dataset,不要切DataLoader train_dataset, validate_dataset = torch.utils.data.random_split( data, [round(len(data)*0.7), len(data) - round(len(data)*0.7)] ) # 分别为训练集、验证集创建DataLoader train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=130, shuffle=True) val_loader = torch.utils.data.DataLoader(validate_dataset, batch_size=130, shuffle=False)
3. 修正训练函数验证阶段的变量名错误
把计算准确率那行的targets改为labels:
# 原来的错误代码 # correct = torch.eq(torch.max(F.softmax(output, dim=1), dim=1)[1], targets) # 修改后 correct = torch.eq(torch.max(F.softmax(output, dim=1), dim=1)[1], labels)
4. 修正训练函数调用参数
传入创建好的DataLoader实例,不要传.dataset属性:
train(model, optimizer, torch.nn.CrossEntropyLoss(), train_loader, val_loader, epochs=100, device=device)
内容的提问来源于stack exchange,提问作者ZealotTV
相关产品推荐
相关产品推荐

