有哪些方法可以加快Pytorch中大型稀疏阵列(约100万x 100万,密度约0.0001)的数据加载速度?
我正在研究一个二进制分类问题。我有150万个数据点,特征空间的维数是100万。此数据集存储为稀疏数组,密度为~0.0001。在这篇文章中,我将限制范围,假设该模型是一个浅层前馈神经网络,并且还假设维度已经过优化(因此不能降低到100万以下)。从这些数据中创建小批量以输入网络的任何方法都需要花费大量时间(例如,创建有哪些方法可以加快Pytorch中大型稀疏阵列(约100万x 100万,密度约0.0001)的数据加载速度?,pytorch,bigdata,sparse-matrix,Pytorch,Bigdata,Sparse Matrix,我正在研究一个二进制分类问题。我有150万个数据点,特征空间的维数是100万。此数据集存储为稀疏数组,密度为~0.0001。在这篇文章中,我将限制范围,假设该模型是一个浅层前馈神经网络,并且还假设维度已经过优化(因此不能降低到100万以下)。从这些数据中创建小批量以输入网络的任何方法都需要花费大量时间(例如,创建TensorDataset(地图样式)的基本方法)从输入数组的torch.sparse.FloatTensor表示,并在其周围包装一个DataLoader,意味着要20秒才能将一小批32
TensorDataset
(地图样式)的基本方法)从输入数组的torch.sparse.FloatTensor
表示,并在其周围包装一个DataLoader
,意味着要20秒才能将一小批32个数据发送到网络,而不是说要0.1秒才能执行实际训练)。我正在寻找加快速度的方法
我试过的
DataLoader
的每次迭代中,从如此大的稀疏数组中读取数据是计算密集型的,所以我将这个稀疏数组分解为更小的稀疏数组DataLoader
以迭代方式从这些多个稀疏数组中读取数据,我将DataLoader
中的映射样式数据集替换为IterableDataset
,并将这些较小的稀疏数组流化到这个IterableDataset中,如下所示:我知道但还需要尝试的一件事是通过在
DataLoader
中设置num\u workers
参数来使用多进程数据加载。不过,我相信这在iterable风格的数据集中也有自己的特点。此外,即使是10倍的加速,也意味着在装载小批量时,每一个历元大约需要300秒。我觉得我的速度太慢了!您还有其他方法/改进/最佳做法吗?您的非稀疏形式的数据集在uint8中为1.5M x 1M x 1字节=1.5TB,在浮动32中为1.5M x 1M x 4字节=6TB。在现代CPU上,仅从内存到CPU读取6TB数据可能需要5-10分钟(取决于体系结构),而从CPU到GPU的传输速度将略慢于此(PCIe上的NVIDIA V100的理论传输速度为32GB/s)
方法:
torch.sparse.FloatTensor
,但我很确定您的代码中没有生成稀疏张量-没有理由期望这些张量仅通过将scipy.sparse数组传递给常规张量构造函数来构造,因为它们通常不是这样生成的
如果你找到了一个很好的方法,我建议你把它作为一个项目或git发布在github上,这将非常有用
感谢您抽出时间回复!对于第2点,我没有将scipy.sparse数组传递到张量构造函数中,而是传递它的值和索引(这是推荐的方式)——为了简洁起见,我省略了这一点。你发布的链接看起来很有趣。在接下来的几天里,我将继续探讨这个问题。@AbhimanyuSahai-最重要的部分是如何构造
torch.sparse.FloatTensor
,请添加该代码。您显示的代码示例将稀疏转换为稠密,这听起来不像是您想要的。坦白说,这并不是太多的数据,而是150米的数值?最大的瓶颈将是toarray()
,它将不得不分配大量的内存来容纳所有这些零。你为什么不直接把coo指数推到一个火炬上。稀疏的coo张量?我看不出有任何理由要加密这个数组。
from itertools import chain
from scipy import sparse
class SparseIterDataset(torch.utils.data.IterableDataset):
def __init__(self, fpaths):
super(SparseIter).__init__()
self.fpaths = fpaths
def read_from_file(self, fpath):
data = sparse.load_npz(fpath).toarray()
for d in data:
yield torch.Tensor(d)
def get_stream(self, fpaths):
return chain.from_iterable(map(self.read_from_file, fpaths))
def __iter__(self):
return self.get_stream(self.fpaths)