PyTorch自定义Dataset/DataLoader报str无to属性错误咨询
PyTorch自定义DataLoader训练报'str' object has no attribute 'to'排查方案
问题复现
参照PyTorch官方数据加载教程构建包含图像、48个关键点标注、30类分类标签的人脸关键点数据集,自定义DataLoader经校验返回的图像、关键点字段均为torch.float64类型,接入训练流程时在张量移至设备的代码行触发报错:
AttributeError: ‘str’ object has no attribute 'to'
涉及的核心代码如下:
训练循环片段:
class Trainer(): def __init__(self,criterion = None,optimizer = None,schedular = None): self.criterion = criterion self.optimizer = optimizer self.schedular = schedular def train_batch_loop(self,model,train_dataloader): train_loss = 0.0 train_acc = 0.0 for images,landmarks, labels in train_dataloader: images = images.to(device) landmarks = landmarks.to(device) labels = labels.to(device) self.optimizer.zero_grad()
自定义数据集片段:
class FaceLandmarksDataset(Dataset): def __init__(self, data_frame, root_dir, transform=None): self.data_frame = data_frame self.root_dir = root_dir self.transform = transform def __len__(self): return len(self.data_frame) def __getitem__(self, idx): if torch.is_tensor(idx): idx = idx.tolist() img_name = os.path.join(self.root_dir, self.data_frame.iloc[idx, 2]) image = io.imread(img_name) landmarks = self.data_frame.iloc[idx, 3:] landmarks = np.array([landmarks]) landmarks = landmarks.astype('float').reshape(-1, 2) labels = self.data_frame.iloc[idx, 1].reshape(1) sample = {'image': image, 'landmarks': landmarks, 'labels': labels} if self.transform: sample = self.transform(sample) return sample
错误截图:
根因定位与排查点
这个报错是Dataset返回值结构和训练循环的解包逻辑不匹配导致的,不需要逐行溯源数据表字段:
- 你的
__getitem__方法最终返回的是字典类型的sample,但训练循环里直接用images, landmarks, labels三元组对DataLoader返回的batch做顺序解包。PyTorch默认的批拼接逻辑不会自动把字典拆成独立张量,直接对字典做顺序解包时,拿到的前三个元素是字典的键字符串'image'、'landmarks'、'labels',所以第一个赋值给images的变量实际是字符串'image',调用.to(device)自然会触发属性错误。 - 你之前做的DataLoader数据类型校验逻辑有漏洞:只校验了字典内部的value类型,没校验DataLoader迭代返回的顶层对象类型,才会误以为所有返回组件都是张量。
修复方案
二选一即可:
- 修改Dataset返回值格式,和训练循环解包逻辑对齐:把
__getitem__方法最后返回字典的逻辑改为直接返回元组# 替换原来return sample的逻辑 return sample['image'], sample['landmarks'], sample['labels'] - 保留字典返回格式,修改训练循环的取值逻辑,按键从batch字典中取对应张量
for batch in train_dataloader: images = batch['image'].to(device) landmarks = batch['landmarks'].to(device) labels = batch['labels'].to(device) self.optimizer.zero_grad() # 后续训练逻辑保持不变
额外校验项
修复结构问题后,还要确认transform流水线中已经将numpy格式的关键点、标签字段转换为torch张量:官方教程提供的ToTensor类仅会处理图像字段的格式转换,关键点、标签如果没有手动转张量,后续会触发新的类型错误。
内容的提问来源于stack exchange,提问作者A_Inb
相关产品推荐
相关产品推荐

