我的目录中有大约一百万个文件,而且它们的数量可能会增长。 对于机器学习,我想从这些文件中随机采样而不进行替换。我怎样才能很快地做到这一点? os.listdir(path) 对我来说太慢了。
我的目录中有大约一百万个文件... os.listdir(path) 对我来说太慢了。
这是您问题的核心,它可以通过我通常听到的一种称为“文件存储”的技术来解决,尽管对此进行网络搜索似乎并不是特别有帮助。 分桶通常由需要存储大量没有任何特定结构的文件的程序使用 - 例如,MediaWiki 实例(运行维基百科的软件)中的所有媒体文件(例如图像)。这是维基百科上的 Stack Overflow 徽标:
https://upload.wikimedia.org/wikipedia/commons/0/02/Stack_Overflow_logo.svg0/02
了吗?就是那个桶。维基百科中的所有文件都将通过某种算法进行
hashed- 例如 sha256,尽管不一定是这样 - 并且
02
将是该哈希的前两个十六进制数字。 (斜杠之前的 0
只是 02
的第一个数字;在本例中,它用作第二级分桶。)如果 MediaWiki 只是将每个文件存储在一个庞大的目录中,则访问该目录中的文件会非常慢,因为尽管操作系统文件夹可以容纳任意多个文件,但它们的设计目的是不能容纳超过几千个文件或者。通过散列文件的内容,您会得到看起来像该文件唯一的十六进制数字的随机字符串,如果您随后将所有以相同的前两个十六进制数字开头的文件(例如02
)放入名为
02
的文件夹,您将获得 256 个文件夹(前两个十六进制数字的每个可能值都有一个文件夹),并且至关重要的是,这 256 个文件夹中的每一个都包含大致相等数量的文件。 当您尝试查找特定文件(例如 MediaWiki)时,如果您以这种方式存储文件,您显然需要知道哈希值才能访问该文件。但就您而言,您只想加载随机
文件。所以这也同样有效:
对所有文件进行哈希处理并对其进行存储(可能具有附加级别,例如,您可能需要像12/34/1234xxxx.ext
hashlib或
sha256sum
等命令行工具来获取文件哈希值。您不需要重命名文件,只要根据其哈希值的前几个十六进制数字将它们分组到目录中即可。现在,每次您需要随机文件时,请选择一个随机存储桶(如果您使用其他级别,则可能是随机子存储桶),然后在该存储桶中选择一个随机文件。listdir
然后在其中随机选择要快得多。