【问题标题】:Dictionary-like efficient storing of scipy/numpy arraysscipy/numpy 数组的类似字典的高效存储
【发布时间】:2011-03-16 18:30:09
【问题描述】:

背景

我正在处理的问题如下:

    1234563 scipy.array 实例(空间增益/损失不是这里的问题)。
  • 这些数组中的每一个都必须与一个字符串(即一个词)配对才能使数据有意义,因为它们是表示该字符串含义的语义向量。 我需要保留这个配对。

  • 列表中每个单词的向量都是一个接一个地构建的,并在移动到下一个单词之前存储到磁盘中。

  • 它们必须以一种随后可以使用类似字典的语法检索的方式存储到磁盘。例如,如果所有单词都存储在类似 DB 的文件中,我需要能够打开此文件并执行 vector = wordDB[word] 之类的操作。

目前的方法

我目前在做什么:

  • 使用shelve打开一个名为wordDB的书架

  • 每次构建一个单词的向量(当前使用来自scipy.sparselil_matrix)时,将向量存储在架子中:wordDB[word] = vector

  • 当我需要在评估过程中使用向量时,我会做相反的事情:打开书架,然后根据需要对每个单词执行 vector = wordDB[word] 来调用向量,这样就不会全部向量需要保存在 RAM 中(这是不可能的)。

上述“解决方案”符合我在解决指定问题方面的需求。问题很简单,当我希望使用这种方法为大量单词构建和存储向量时,我只是用完了磁盘空间。

据我所知,这是因为shelve 腌制了正在存储的数据,这不是存储大型数组的有效方式,因此对于我的字数而言,shelve 难以解决这个存储问题需要处理。

问题

因此问题是:有没有一种方法可以序列化我的数组集:

  1. 以类似于.npyscipy.save生成的文件的压缩二进制格式保存数组本身?

  2. 满足我的要求,即数据可以作为字典从磁盘读取,保持单词和数组之间的关联?

【问题讨论】:

  • 只是为了确保您使用协议 2 进行酸洗(在您的货架上),对吗? docs.python.org/library/pickle.html#data-stream-format如果不指定协议,默认为0,效率最低。
  • 事实上...我不知道。我有点假设它会默认为最实用的。我只是测试一下协议 2 是否对我的数据有显着的空间增益。感谢您指出这一点!
  • 我还假设它默认使用最有利的协议并且之前被烧毁,这就是我想问的原因。我想默认是协议 0,而是出于遗留原因。
  • 如我的回答所示,您可以使用-1cPickle.HIGHEST_PROTOCOL 始终使用最新的(并且我假设未来,最有效的)酸洗协议。此外,cPicklePickle 相比,您将获得更好的性能。
  • 好的,使用协议二将所需的存储空间减半。遗憾的是,这还不够,但这是一个很好的进步。我得看看这个 hdf5 的东西......

标签: python serialization numpy scipy


【解决方案1】:

正如 JoshAdel 已经建议的那样,我会选择 HDF5,最简单的方法是使用 h5py:

http://h5py.alfven.org/

您可以使用像 sintax 这样的字典将多个属性附加到数组:

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

其中 dset 是您的数据集,可以完全按照 numpy 数组进行切片,但在后台它不会将所有数组加载到内存中。

【讨论】:

  • 这是我寻求的解决方案,除了使用 pytables。谢谢!
【解决方案2】:

我建议使用 scipy.save 并在单词和文件名之间建立一个字典。

【讨论】:

  • 这可能最终是我最终要做的解决方案,但感觉有点不雅,我很想在重新发明轮子之前看看是否有现有的解决方案。不过建议不错。谢谢。
【解决方案3】:

您是否尝试过直接使用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

【讨论】:

    【解决方案4】:

    避免使用shelve,它有很多错误并且存在跨平台问题。

    不过,内存问题与shelve 无关。 Numpy 数组提供了 pickle 协议的高效实现,与二进制 .npy 相比,cPickle.dumps(protocol=-1) 的内存开销很小(基本上只有 pickle 中的额外标头)。

    因此,如果二进制/pickle 还不够,您将不得不进行压缩。看看pytablesh5py (difference between the two)。

    如果在 pickle 中指定二进制协议足够,您可以考虑比 hdf5 更轻量级的东西:查看 sqlitedict 以替换 shelve。它没有额外的依赖。

    【讨论】:

    • shelve 漏洞百出 --- 你能再解释一下吗?
    • sqlitedict 似乎具有相似的字典语义。我也对shelve 错误的状态感到好奇,因为我遇到了问题。
    猜你喜欢
    • 2021-06-21
    • 1970-01-01
    • 2014-09-01
    • 2016-01-08
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 2015-11-08
    相关资源
    最近更新 更多