【问题标题】:Saving KDTree object in Python?在 Python 中保存 KDTree 对象?
【发布时间】:2011-08-12 00:10:09
【问题描述】:

我正在使用 Scipy 的 KDTree 实现来读取 300 MB 的大文件。现在,有没有办法我可以将数据结构保存到磁盘并再次加载它,或者我是否坚持从文件中读取原始点并在每次启动程序时构建数据结构?我正在按如下方式构建 KDTree:

def buildKDTree(self):
        self.kdpoints = numpy.fromfile("All", sep=' ')
        self.kdpoints.shape = self.kdpoints.size / self.NDIM, NDIM
        self.kdtree = KDTree(self.kdpoints, leafsize = self.kdpoints.shape[0]+1)
        print "Preparing KDTree... Ready!"

有什么建议吗?

【问题讨论】:

  • 你试过酸洗吗?
  • 当我尝试在 KDTree 对象上使用 cPickle 时,我的机器上出现错误

标签: python serialization numpy scipy pickle


【解决方案1】:

KDtree 使用嵌套类来定义其节点类型(innernode、leafnode)。 Pickle 仅适用于模块级别的类定义,因此嵌套类会将其绊倒:

import cPickle

class Foo(object):
    class Bar(object):
        pass

obj = Foo.Bar()
print obj.__class__
cPickle.dumps(obj)

<class '__main__.Bar'>
cPickle.PicklingError: Can't pickle <class '__main__.Bar'>: attribute lookup __main__.Bar failed

但是,有一个(hacky)解决方法,将类定义猴子修补到模块范围内的scipy.spatial.kdtree 中,以便pickler 可以找到它们。如果所有读取和写入腌制 KDtree 对象的代码都安装了这些补丁,那么这个 hack 应该可以正常工作:

import cPickle
import numpy
from scipy.spatial import kdtree

# patch module-level attribute to enable pickle to work
kdtree.node = kdtree.KDTree.node
kdtree.leafnode = kdtree.KDTree.leafnode
kdtree.innernode = kdtree.KDTree.innernode

x, y = numpy.mgrid[0:5, 2:8]
t1 = kdtree.KDTree(zip(x.ravel(), y.ravel()))
r1 = t1.query([3.4, 4.1])
raw = cPickle.dumps(t1)

# read in the pickled tree
t2 = cPickle.loads(raw)
r2 = t2.query([3.4, 4.1])
print t1.tree.__class__
print repr(raw)[:70]
print t1.data[r1[1]], t2.data[r2[1]]

输出:

<class 'scipy.spatial.kdtree.innernode'>
"ccopy_reg\n_reconstructor\np1\n(cscipy.spatial.kdtree\nKDTree\np2\nc_
[3 4] [3 4]

【讨论】:

  • 你也有 cython cKDTree 的补丁吗?
  • @Denis 不幸的是我没有 cKDTree 的补丁。某种形式的保存/加载方法应该是可能的,但会更自定义,因为cKDTree 节点是 malloc 的结构,而不是类。
  • 不幸的是,我收到错误消息:“调用 Python 对象时超出了最大递归深度”公平地说,我的树是根据 1,000,000 长的 5d 坐标列表计算的,因为只需几分钟即可从该数组计算(数组本身我可以通过 numpy 保存和加载)我想我必须忍受它。
  • 非常好的解决方案,这适用于其他类型吗?以及如何研究以这种方式公开哪些类型?
猜你喜欢
  • 2021-05-11
  • 1970-01-01
  • 2017-12-09
  • 1970-01-01
  • 2021-02-11
  • 2016-02-21
  • 2016-03-18
  • 2011-12-30
  • 2019-12-29
相关资源
最近更新 更多