类字典高效存储scipy/numpy数组

7 投票
4 回答
3521 浏览
提问于 2025-04-16 13:50

背景

我正在处理的问题如下:

  • 在我为研究设计的实验中,我需要生成大量的数组,这些数组很大(长度为4M),而且大部分元素都是空的,因此可以用 scipy.sparse.lil_matrix 来存储,或者直接用 scipy.array 来存储(这里的空间节省与否不是重点)。

  • 每个数组都必须和一个字符串(也就是一个单词)配对,这样数据才有意义,因为这些数组是表示该字符串含义的语义向量。我需要保持这种配对关系。

  • 每个单词的向量都是一个一个构建的,并在处理下一个单词之前存储到磁盘上。

  • 这些向量必须以一种可以用字典方式检索的方式存储到磁盘上。比如说,如果所有的单词都存储在一个类似数据库的文件中,我需要能够打开这个文件,然后通过 vector = wordDB[word] 的方式来获取向量。

当前方法

我现在的做法是:

  • 使用 shelve 打开一个名为 wordDB 的存储空间。

  • 每当构建一个单词的向量(目前使用的是 scipy.sparse 中的 lil_matrix)时,就把这个向量存储到这个空间里: wordDB[word] = vector

  • 当我在评估时需要使用这些向量时,我会反向操作:打开存储空间,然后通过 vector = wordDB[word] 的方式来获取每个单词的向量,这样就不需要把所有的向量都放在内存中(这几乎是不可能的)。

以上的“解决方案”在解决我所指定的问题上是有效的。问题在于,当我想用这种方法为大量单词构建和存储向量时,我的磁盘空间就不够用了。

据我所知,这是因为 shelve 会将存储的数据进行序列化,这种方式并不适合存储大数组,因此对于我需要处理的单词数量来说,使用 shelve 存储就变得很困难。

问题

所以问题是:有没有一种方法可以序列化我的数组集合,使得:

  1. 将数组本身以类似 .npy 文件的压缩二进制格式保存,这种文件是通过 scipy.save 生成的?

  2. 满足我从磁盘读取数据时能够像字典一样使用,同时保持单词和数组之间的关联?

4 个回答

2

你有没有试过直接用 cPickle 来把字典保存起来呢?可以这样做:

import cPickle
DD = dict()
f = open('testfile.pkl','wb')
cPickle.dump(DD,f,-1)
f.close()

另外,如果需要的话,我建议把向量保存在一个大的多维数组里,使用 hdf5 或 netcdf。这样做的好处是,你可以在不一次性把整个数组加载到内存中的情况下打开一个大数组,然后根据需要获取部分数据。你还可以把单词作为 netcdf4/hdf5 文件中的一个额外组来关联,然后用共同的索引快速找到每个组中对应的部分,或者直接把组命名为单词,然后让数据就是那个向量。你需要自己试试看哪种方法更高效。

http://netcdf4-python.googlecode.com/svn/trunk/docs/netCDF4-module.html

Pytables 也可能是一个很有用的存储层,可以在 HDF5 之上使用:

http://www.pytables.org

2

我建议使用scipy.save,并建立一个字典,把单词和文件名对应起来。

5

正如JoshAdel已经提到的,我推荐使用HDF5,最简单的方法是用h5py这个库:

http://h5py.alfven.org/

你可以用字典的方式给一个数组添加多个属性:

dset.attrs["Name"] = "My Dataset"

这里的dset就是你的数据集,它可以像numpy数组一样进行切片操作,但在后台,它并不会把整个数组都加载到内存中。

撰写回答