Python 建议使用相同的torch数据集类进行培训和预测吗?
我最近开始使用PyTorch,我喜欢它的面向对象风格。然而,我想知道在预测模型时,什么是最好的和建议的工作流。我想使用我编写的自定义数据集类,用于培训和验证我的模型。该类是一个映射样式的数据集,因此我实现了Python 建议使用相同的torch数据集类进行培训和预测吗?,python,pytorch,torch,pytorch-dataloader,Python,Pytorch,Torch,Pytorch Dataloader,我最近开始使用PyTorch,我喜欢它的面向对象风格。然而,我想知道在预测模型时,什么是最好的和建议的工作流。我想使用我编写的自定义数据集类,用于培训和验证我的模型。该类是一个映射样式的数据集,因此我实现了\uuu getitem\uuu方法来返回图像和目标: class CustomDataset: def __init__(self, ...): ... def __getitem__(self, image_id): ....
\uuu getitem\uuu
方法来返回图像和目标:
class CustomDataset:
def __init__(self, ...):
...
def __getitem__(self, image_id):
....
return (
torch.tensor(image, dtype=torch.float),
torch.tensor(target, dtype=torch.long),
)
然而,当我使用这个类进行预测时,我没有任何要返回的目标。我目前的解决办法是
def __getitem__(self, image_id):
....
if predict:
return (
torch.tensor(image, dtype=torch.float),
np.nan,
)
else:
return (
torch.tensor(image, dtype=torch.float),
torch.tensor(target, dtype=torch.long),
)
然而,我想知道是否有更好的方法。同时,由于感觉有点不自然,我开始怀疑使用同一个课程进行培训和预测是否明智(应该是这样,但我的解决方案的笨重让我怀疑)。当然,我根本无法返回元组,只能返回第一个元素,但这仍然需要if-else。PyTorch的
DataSet
类非常简单。所以,不要想得太多。它只不过是访问数据的包装器
不必返回元组,甚至不必返回张量。您可以返回所需的任何数据。通常,它将采用以下样式之一:
- 对于非监督数据:
或Sample
(Sample,None)
- 对于监督数据:
(样本、标签)
- 对于具有多个目标的监控数据,例如目标检测:
或(样本[Label1,Label2,…])
(样本,Label1,Label2,…)
(sample,None)
,并相应地调整管道。我不建议使用np.nan
,因为它将无法通过简单的None检查(np.nan==None
)。另外,我鼓励您从torch.data.Dataset
继承
但是,如果管道强制您使用元组或有其他限制,我建议您重新表述您的问题。您必须编写代码来创建与您的数据和问题场景相匹配的数据集;没有两个数据集实现是完全相同的。另一方面,无论与哪个Dataset对象关联,DataLoader对象的使用基本相同。例如:
class MyDataSet(T.utils.data.Dataset):
# implement custom code to load data here
my_ds = MyDataset("my_train_data.txt")
my_ldr = torch.utils.data.DataLoader(my_ds, 10, True)
for (idx, batch) in enumerate(my_ldr):
. . .
我认为,如果您想要一个“纯”(=无if)解决方案,您可以定义一个“不在乎”类,并让您的损失以某种方式忽略它(可能通过内部掩蔽完成,从技术上讲它是一个“if”,但它是矢量化的)
例如,请参见hasignore_index
,以处理此类情况。这让我相信不在乎类索引是设计的方式
class CDiscountDataset:
self.ignore_index = self._preprocess_number_of_classes() + 1
def __getitem__(self, image_id):
target_tensor = torch.tensor(target, dtype=torch.long)
if predict:
return (
torch.tensor(image, dtype=torch.float),
torch.ones_like(target_tensor, dtype=torch.long) * self.ignore_index,
)
else:
return (
torch.tensor(image, dtype=torch.float),
target_tensor,
)
作为旁注,我正在使用它为训练管道提供了很好的抽象,它隐式地假设只有张量元组从数据加载器返回,这使我相信返回其他类型是“不那么规范的”,这加强了我的信念,即上面的“不在乎”路就是路。你能解释一下上面的预测函数要做什么吗?
predict
在上面的代码中是一个布尔参数,当我们使用数据集进行预测时设置为True
。好的,所以你使用它在测试和训练数据之间切换,对吗?如果您所说的测试数据是指数据的未标记部分(无y
)-是的,这正是我在这里所做的。是的,它可以做到,事实上在pytorch lightning模块中有一个设置函数,带有阶段变量,用于在测试数据(未标记部分)和列车数据之间切换,请查看:谢谢您的回复。我尝试了一下,并遵循了中的方法,在使用数据集进行预测时,将None分配给target
。然而,使用测试加载程序时,我得到了一个错误:TypeError:default\u collate:batch必须包含张量、numpy数组、数字、dict或列表;找到
。我不明白为什么它适用于上述torchvision的例子,但不适用于我。在我的代码中,Sample
被格式化为张量这一事实是否重要?(我认为没有)
class CDiscountDataset:
self.ignore_index = self._preprocess_number_of_classes() + 1
def __getitem__(self, image_id):
target_tensor = torch.tensor(target, dtype=torch.long)
if predict:
return (
torch.tensor(image, dtype=torch.float),
torch.ones_like(target_tensor, dtype=torch.long) * self.ignore_index,
)
else:
return (
torch.tensor(image, dtype=torch.float),
target_tensor,
)