高效的 HDF5 / PyTables 布局,用于保存和操作大型张量
Efficient HDF5 / PyTables Layout for saving and operating on large tensors
我正在尝试找出适合我的用例(研究项目)的最佳数据布局。这不是我的专长,所以虽然我可以清楚地表达我想要什么,以及我认为可能有用的东西,但我正在努力避开失败路径。
现在,假设原始数据类似于分成序列(例如句子)的几个大型文本语料库,每个序列都包含许多标记(例如单词)。我在句子标记的基础上提取、处理和保存信息,但在接下来的分析中需要对其进行不同的操作。
具体来说,每个句子中的每个标记都与一个大向量(可以是数字)相关联,该向量由许多已经实现的操作准备。每个序列都与一些元数据相关联。此操作以及此数据的准备仅发生一次。
因此:初始操作的输出是三维张量 D[x,y,z] 加上与 x 维度关联的元数据。 x 维度表示序列,y 表示序列中的 token 位置(但不是唯一的 token-id,例如单词编码,它是序列元数据的一部分),z 是信息的列(数千)对于那个令牌。因此,每个序列都与一个以标记为行、以信息为列的矩阵相关联。如有必要,可以将元数据放入第一行。请注意,每个序列的长度相同。
Sequence 1
Meta-data: [..]
Column 1 | Column 2 | ...
Token 1 | [...] | [...] | ...
Token 2 | [...] | [...] | ...
...
Token N | [...] | [...] | ...
Sequence 2
Meta-data: [..]
Column 1 | Column 2 | ...
Token 1 | [...] | [...] | ...
Token 2 | [...] | [...] | ...
...
Token N | [...] | [...] | ...
此数据被不同的后续分析多次摄取。因此,我需要此数据的不同 "views",如下所示:
我需要能够查询每个序列并获得令牌-> 值的完整矩阵。那只是输出 3D 张量,我在其中沿第一个维度查询。能够一次 "slice" 多个序列(例如 ML 模型的随机批次等)
会很好
我需要能够通过唯一的 token-id 进行查询(例如单词 "hello"),注意每个 token 可能出现在多个序列中并出现在不同的位置。这不是对张量维度的查询,而是需要将唯一标记 ID 映射到它们在序列中的位置的数据(或每个序列中允许此类查询的元数据)。
我最终为每个序列的每个标记生成并保存了进一步的汇总值,我试图以极快的速度查询,而该序列中的其他信息不相关。
所有后续建模的共同点是
我需要尽可能多的RAM用于后续分析,或者换句话说,数据可能需要也可能不需要推送到磁盘。这就是为什么我正在寻找一种允许内存中和内存外访问的解决方案。特别是,整个张量可能根本不适合内存(它随后在 x 维度上构建)
鉴于固定结构,索引和切片相对简单,但我可能经常需要 select 不相邻的条目,例如来自不相关序列的标记。
整个事情应该不会成为后续分析的瓶颈。如果它有点 portable 并且不需要额外的软件,这也将是有益的,这样结果可以很容易地被其他研究人员分发和复制。事实上,如果事实证明可能(合法),我想让这些数据可供下载
由于这是一个输入,我主要对从 python 或其他语言访问这些数据的速度感兴趣。
基于此,我暂时决定使用 h5py 或 pyTables,但我对其他选项持开放态度。
虽然数据很大,但还没有大到磁盘 space 成为问题(在中等规模的服务器上)。我进一步迭代每个序列至少一次以执行初始操作。因此,我计划将每个必需的 "view" 保存到单独的数据集中,每个数据集的布局都是为了实现高效访问。
我的计划如下:
我把输出张量保存为pyTables中的多维数组。索引维度将是序列号。我可能会查询多个序列,但总是摄取整个序列的 2D table。我希望 pyTables 允许我将整个 3D 张量保存在磁盘上,并且只将所需的数据读入 RAM。
我将保存一个新的数据集,该数据集将唯一的标记 ID 作为索引,将序列 ID 作为第二列,然后将所需的信息作为数组。这样,我可以通过 token-id 查询并获取所有序列中关联的所有数据。这包括很多重复,但应该允许快速查询 (?)
我最终会制作一个较小的数据集,其中包含每个序列的每个标记 ID(作为索引)的相关摘要数据。
您认为这在计算时间方面是否有效?
我看到的另一条路线是关系数据库,例如SQL。在这里,我可以简单地为序列中的每个实际单词创建条目,以及相关的标记 ID、序列号和我需要的数据。然后可以使用 SQL 查询以我选择的任何方式获取数据。此外,任何元数据都可以按顺序或标记保存在其他 table 中,没有太多限制。
但是,我不确定这是否是最快的选择,因为我不需要 SQL 提供的很多东西,例如额外的灵活性(我的查询/视图是固定的,而 indexing/slicing 是始终沿固定维度)或所有访问保护等等。另外,如果只是一些数据集文件,可移植性会更好。
我也不确定 SQL 如何处理内存中和内存外问题。可能存在我的大部分数据实际上适合 RAM 的情况,因此我也希望那里具有灵活性。
问题:
您认为最佳方法是什么?我的计划可行吗?
SQL 显然更灵活,是不是更快?
我在 HDF5 中还不明白的是分块和分组是如何发挥作用的。看来我不能真正分块我的数据,因为我需要能够高频查询非连续数据。对于我的用例,我不应该分块是否正确?
同样,组和链接。我的数据结构不像树,因为每个标记可能出现在许多序列中,这就是为什么我选择只生成完全不同的数据集。尝试使用硬链接或组会更有效吗?
HDF5 的内存模型如何工作(在 python 中实现)?我真的可以查询 3D 张量,并且只将结果保存在内存中,而且还可以缓存经常查询的序列或标记吗?
如果我的描述不清楚,请告诉我。感谢您花时间阅读所有这些内容。
对于任何遇到这个问题的人,让我给你结果。
以上使用 pyTables 按预期工作。它可以做得相当快。但是,该逻辑会迅速生成滑稽的巨大比例的文件,所以我只能建议另辟蹊径。特别是,磁盘 space 比 RAM 使用问题更严重,尤其是事情可以被稀疏化。
将数据子集放入内存的自定义解决方案比使用 pyTables 分块更成功。所以实际上,除了刀刃之外的所有情况,以上可能不是一个好主意。
我正在尝试找出适合我的用例(研究项目)的最佳数据布局。这不是我的专长,所以虽然我可以清楚地表达我想要什么,以及我认为可能有用的东西,但我正在努力避开失败路径。
现在,假设原始数据类似于分成序列(例如句子)的几个大型文本语料库,每个序列都包含许多标记(例如单词)。我在句子标记的基础上提取、处理和保存信息,但在接下来的分析中需要对其进行不同的操作。 具体来说,每个句子中的每个标记都与一个大向量(可以是数字)相关联,该向量由许多已经实现的操作准备。每个序列都与一些元数据相关联。此操作以及此数据的准备仅发生一次。
因此:初始操作的输出是三维张量 D[x,y,z] 加上与 x 维度关联的元数据。 x 维度表示序列,y 表示序列中的 token 位置(但不是唯一的 token-id,例如单词编码,它是序列元数据的一部分),z 是信息的列(数千)对于那个令牌。因此,每个序列都与一个以标记为行、以信息为列的矩阵相关联。如有必要,可以将元数据放入第一行。请注意,每个序列的长度相同。
Sequence 1
Meta-data: [..]
Column 1 | Column 2 | ...
Token 1 | [...] | [...] | ...
Token 2 | [...] | [...] | ...
...
Token N | [...] | [...] | ...
Sequence 2
Meta-data: [..]
Column 1 | Column 2 | ...
Token 1 | [...] | [...] | ...
Token 2 | [...] | [...] | ...
...
Token N | [...] | [...] | ...
此数据被不同的后续分析多次摄取。因此,我需要此数据的不同 "views",如下所示:
我需要能够查询每个序列并获得令牌-> 值的完整矩阵。那只是输出 3D 张量,我在其中沿第一个维度查询。能够一次 "slice" 多个序列(例如 ML 模型的随机批次等)
会很好
我需要能够通过唯一的 token-id 进行查询(例如单词 "hello"),注意每个 token 可能出现在多个序列中并出现在不同的位置。这不是对张量维度的查询,而是需要将唯一标记 ID 映射到它们在序列中的位置的数据(或每个序列中允许此类查询的元数据)。
我最终为每个序列的每个标记生成并保存了进一步的汇总值,我试图以极快的速度查询,而该序列中的其他信息不相关。
所有后续建模的共同点是
我需要尽可能多的RAM用于后续分析,或者换句话说,数据可能需要也可能不需要推送到磁盘。这就是为什么我正在寻找一种允许内存中和内存外访问的解决方案。特别是,整个张量可能根本不适合内存(它随后在 x 维度上构建)
鉴于固定结构,索引和切片相对简单,但我可能经常需要 select 不相邻的条目,例如来自不相关序列的标记。
整个事情应该不会成为后续分析的瓶颈。如果它有点 portable 并且不需要额外的软件,这也将是有益的,这样结果可以很容易地被其他研究人员分发和复制。事实上,如果事实证明可能(合法),我想让这些数据可供下载
由于这是一个输入,我主要对从 python 或其他语言访问这些数据的速度感兴趣。
基于此,我暂时决定使用 h5py 或 pyTables,但我对其他选项持开放态度。
虽然数据很大,但还没有大到磁盘 space 成为问题(在中等规模的服务器上)。我进一步迭代每个序列至少一次以执行初始操作。因此,我计划将每个必需的 "view" 保存到单独的数据集中,每个数据集的布局都是为了实现高效访问。
我的计划如下:
我把输出张量保存为pyTables中的多维数组。索引维度将是序列号。我可能会查询多个序列,但总是摄取整个序列的 2D table。我希望 pyTables 允许我将整个 3D 张量保存在磁盘上,并且只将所需的数据读入 RAM。
我将保存一个新的数据集,该数据集将唯一的标记 ID 作为索引,将序列 ID 作为第二列,然后将所需的信息作为数组。这样,我可以通过 token-id 查询并获取所有序列中关联的所有数据。这包括很多重复,但应该允许快速查询 (?)
我最终会制作一个较小的数据集,其中包含每个序列的每个标记 ID(作为索引)的相关摘要数据。
您认为这在计算时间方面是否有效?
我看到的另一条路线是关系数据库,例如SQL。在这里,我可以简单地为序列中的每个实际单词创建条目,以及相关的标记 ID、序列号和我需要的数据。然后可以使用 SQL 查询以我选择的任何方式获取数据。此外,任何元数据都可以按顺序或标记保存在其他 table 中,没有太多限制。
但是,我不确定这是否是最快的选择,因为我不需要 SQL 提供的很多东西,例如额外的灵活性(我的查询/视图是固定的,而 indexing/slicing 是始终沿固定维度)或所有访问保护等等。另外,如果只是一些数据集文件,可移植性会更好。
我也不确定 SQL 如何处理内存中和内存外问题。可能存在我的大部分数据实际上适合 RAM 的情况,因此我也希望那里具有灵活性。
问题:
您认为最佳方法是什么?我的计划可行吗?
SQL 显然更灵活,是不是更快?
我在 HDF5 中还不明白的是分块和分组是如何发挥作用的。看来我不能真正分块我的数据,因为我需要能够高频查询非连续数据。对于我的用例,我不应该分块是否正确?
同样,组和链接。我的数据结构不像树,因为每个标记可能出现在许多序列中,这就是为什么我选择只生成完全不同的数据集。尝试使用硬链接或组会更有效吗?
HDF5 的内存模型如何工作(在 python 中实现)?我真的可以查询 3D 张量,并且只将结果保存在内存中,而且还可以缓存经常查询的序列或标记吗?
如果我的描述不清楚,请告诉我。感谢您花时间阅读所有这些内容。
对于任何遇到这个问题的人,让我给你结果。
以上使用 pyTables 按预期工作。它可以做得相当快。但是,该逻辑会迅速生成滑稽的巨大比例的文件,所以我只能建议另辟蹊径。特别是,磁盘 space 比 RAM 使用问题更严重,尤其是事情可以被稀疏化。
将数据子集放入内存的自定义解决方案比使用 pyTables 分块更成功。所以实际上,除了刀刃之外的所有情况,以上可能不是一个好主意。