当前位置: 首页 > 知识库问答 >
问题:

使用Mongo DB的PyTorch数据加载器

鱼渝
2023-03-14

我想知道使用连接到MongoDB的DataLoader是否是一件明智的事情,以及如何实现这一点。

出身背景

我在一个(本地)MongoDB中有大约2000万个文档。超过内存容量的文档太多了。我想在数据上训练一个深层次的神经网络。到目前为止,我一直在首先将数据导出到文件系统,子文件夹被命名为文档的类。但我觉得这种方法是荒谬的。如果数据库中的数据已经得到很好的维护,为什么要先导出(然后删除)。

问题1:

我说得对吗?直接连接到MongoDB有意义吗?或者是否有不这样做的理由(例如DBs通常太慢等)?如果DBs太慢(为什么?),一个人能以某种方式预取数据吗?

问题2:

如何实现PyTorch数据加载器?我在网上只找到了很少的代码片段([1]和[2]),这让我怀疑我的方法。

代码片段

我访问MongoDB的一般方法如下所示。我想这没什么特别的。

import pymongo
from pymongo import MongoClient

myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["xyz"]
mycol = mydb["xyz_documents"]

query = {
    # some filters
}

results = mycol.find(query)

# results is now a cursor that can run through all docs
# Assume, for the sake of this example, that each doc contains a class name and some image that I want to train a classifier on

共有1个答案

闻人高卓
2023-03-14

这是一个有点开放,但让我们尝试,也请纠正我,如果我错了什么地方。

到目前为止,我一直在首先将数据导出到文件系统,子文件夹被命名为文档的类。

海事组织,这是不明智的,因为:

  • 您实际上是在复制数据
  • 任何时候,如果您想训练一个新的给定代码和数据库,则必须重复此操作
  • 您可以一次访问多个数据点,并将它们缓存在RAM中以供以后重用,而无需多次从硬盘读取数据(这相当繁重)

我说得对吗?直接连接到MongoDB有意义吗?

如上所述,可能是的(特别是当涉及到清晰和可移植的实现时)

或者是否有不这样做的理由(例如DBs通常会减速等)?

在这种情况下,AFAIK DB应该不会变慢,因为它会缓存对它的访问,但不幸的是,我不是DB专家。许多更快访问的技巧都是为数据库实现的。

能以某种方式预取数据吗?

是的,如果您只想获取数据,您可以一次性加载大部分数据(比如1024个记录),并从中返回数据批(比如batch\u size=128

如何实现PyTorch数据加载器?我在网上只找到了很少的代码片段([1]和[2]),这让我对我的方法产生了怀疑。

我不知道你为什么要这么做。你应该选择手电筒。乌提尔斯。数据数据集,如所列示例所示。

我将从与此处类似的简单非优化方法开始,因此:

  • \uuuu init\uuuuu中打开到db的连接,并在使用期间保持连接(我将从torch.utils.data.Dataset创建一个上下文管理器,以便在历元完成后关闭连接)
  • 我不会将结果转换为列表(特别是由于明显的原因,您无法将其放入RAM中),因为它忽略了生成器的要点
  • 我将在这个数据集中执行批处理(这里有一个参数batch\u size
  • 我不确定\uuu getitem\uuu函数,但它似乎可以一次返回多个数据点,因此我会使用它,它应该允许我们使用num\u worker

考虑到这一点,我会做一些类似的事情:

class DatabaseDataset(torch.utils.data.Dataset):
    def __init__(self, query, batch_size, path: str, database: str):
        self.batch_size = batch_size

        client = pymongo.MongoClient(path)
        self.db = client[database]
        self.query = query
        # Or non-approximate method, if the approximate method
        # returns smaller number of items you should be fine
        self.length = self.db.estimated_document_count()

        self.cursor = None

    def __enter__(self):
        # Ensure that this find returns the same order of query every time
        # If not, you might get duplicated data
        # It is rather unlikely (depending on batch size), shouldn't be a problem
        # for 20 million samples anyway
        self.cursor = self.db.find(self.query)
        return self

    def shuffle(self):
        # Find a way to shuffle data so it is returned in different order
        # If that happens out of the box you might be fine without it actually
        pass

    def __exit__(self, *_, **__):
        # Or anything else how to close the connection
        self.cursor.close()

    def __len__(self):
        return len(self.examples)

    def __getitem__(self, index):
        # Read takes long, hence if you can load a batch of documents it should speed things up
        examples = self.cursor[index * batch_size : (index + 1) * batch_size]
        # Do something with this data
        ...
        # Return the whole batch
        return data, labels

现在批处理由DatabaseDataset处理,因此torch。乌提尔斯。数据数据加载器可以具有批处理大小=1。您可能需要压缩其他维度

由于MongoDB使用锁(这并不奇怪,但请参见此处)num_worker

可能的用法(示意):

with DatabaseDataset(...) as e:
    dataloader = torch.utils.data.DataLoader(e, batch_size=1)
    for epoch in epochs:
        for batch in dataloader:
            # And all the stuff
            ...
        dataset.shuffle() # after each epoch

记住在这种情况下洗牌实现!(洗牌也可以在上下文管理器中完成,您可能需要手动关闭连接或类似的操作)。

 类似资料:
  • PyTorch包含一个名为的包,用于加载和准备数据集。它包括两个基本功能,即和,它们有助于数据集的转换和加载。 数据集 数据集用于从给定数据集读取和转换数据点。实现的基本语法如下所述 - 用于随机播放和批量处理数据。它可用于与多处理工作程序并行加载数据。 示例:加载CSV文件 使用Python包Panda来加载csv文件。原始文件具有以下格式:(图像名称,68个标记 - 每个标记具有,坐标)。

  • 我以前做过一些预处理和特征选择,我有一个pickle训练输入数据,由列表列表组成,例如(但pickle) 是一个填充标记,但我认为这并不重要。 因为这个文件有大量的千兆字节,所以我希望节省内存,并使用生成器逐行(逐列表)读取pickle。我已经找到了这个可能有用的答案。这方面的工作如下: 接下来,我希望在PyTorch(1.0.1)数据加载器中使用这些数据。根据我在其他答案中发现的,我必须向它提供

  • 我想知道如何在Pytorch中创建一个支持多种标签类型的数据加载器。我该怎么做?

  • 对于在时间序列数据上实现PyTorch数据管道的“最佳实践”,我有点困惑。 我有一个HD5文件,我使用自定义DataLoader读取。似乎我应该返回数据样本作为一个(特征,目标)元组,每个元组的形状是(L,C),其中L是seq_len,C是通道数-即不要在数据加载器中预制批处理,只需返回一个表。 PyTorch模块似乎需要一个批处理暗淡,即。Conv1D期望(N,C,L)。 我的印象是,类将预先处

  • 本文向大家介绍pytorch 自定义数据集加载方法,包括了pytorch 自定义数据集加载方法的使用技巧和注意事项,需要的朋友参考一下 pytorch 官网给出的例子中都是使用了已经定义好的特殊数据集接口来加载数据,而且其使用的数据都是官方给出的数据。如果我们有自己收集的数据集,如何用来训练网络呢?此时需要我们自己定义好数据处理接口。幸运的是pytroch给出了一个数据集接口类(torch.uti

  • 我有多个数据集,每个数据集中有不同数量的图像(和不同的图像维度)。在训练循环中,我想从所有数据集中随机加载一批图像,但每个批次只包含单个数据集中的图像。例如,我有数据集A、B、C、D,每个数据集都有图像01。jpg,02。jpg,…n.jpg(其中n取决于数据集),假设批量大小为3。例如,在第一个加载的批次中,我可能会在下一个批次[D/01.jpg,D/05.jpg,D/12.jpg]中获得图像[