Python 建议使用相同的torch数据集类进行培训和预测吗?

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): ....

我最近开始使用PyTorch,我喜欢它的面向对象风格。然而,我想知道在预测模型时,什么是最好的和建议的工作流。我想使用我编写的自定义数据集类,用于培训和验证我的模型。该类是一个映射样式的数据集,因此我实现了
\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或tuple
(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”,但它是矢量化的)

例如,请参见has
ignore_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,
           )