使用s3torchconnector加载S3数据报错:'list'对象无'to'属性
samples.to(device)报错问题 问题根源
你的load_image函数返回了(object.key, 图像张量)的元组,S3MapDataset会将这个元组作为单个样本输出。DataLoader在批量打包时,会把所有样本的对应位置元素分别聚合,最终生成的batch是两个列表:一个是所有样本的key组成的列表,另一个是所有图像张量组成的列表。而你后续代码直接对这个batch调用.to(device),自然会触发'list' object has no attribute 'to'错误——列表没有张量的方法。
之前本地代码能正常运行,是因为本地数据集的transform只返回图像张量,DataLoader打包后得到的是单个张量batch,.to(device)可以直接执行。
解决方案
方案1:不需要保留S3对象key时,修改transform只返回图像张量
直接调整load_image的返回值,去掉object.key,仅返回处理后的图像张量:
def load_image(object): img = Image.open(object) resize = transforms.Resize(size=(224, 224)) img = resize(img) img = transforms.functional.pil_to_tensor(img) # 仅返回图像张量 return torchvision.transforms.functional.convert_image_dtype(img, dtype=torch.float32)
修改后,DataLoader输出的batch就是单个张量,samples.to(device, non_blocking=True)可以正常执行。
方案2:需要保留S3对象key时,在训练循环中拆分batch并处理张量
如果训练过程必须用到S3对象的key,就在train_one_epoch函数中拆分batch,单独处理张量部分:
假设原训练循环中处理batch的代码是:
for samples, targets in data_loader: samples = samples.to(device, non_blocking=True) # ... 后续训练逻辑
修改为:
for batch in data_loader: # 拆分key列表与图像张量列表 keys, samples = batch # 将张量列表堆叠成批量张量,再移至设备 samples = torch.stack(samples).to(device, non_blocking=True) # ... 后续训练逻辑,keys可按需使用
注:由于你的transform已经将图像统一resize到224x224,torch.stack可以直接将列表转为张量。
这并非s3torchconnector的固有特性,只是自定义transform的返回结构与原本地代码不一致导致的适配问题,调整返回值或batch处理逻辑即可解决。
内容的提问来源于stack exchange,提问作者AlternativeWaltz

