微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

python – 概率解析器的内存使用

我正在为Range Concatenation Grammar编写一个CKY解析器.我想使用树库作为语法,所以语法会很大.我用Python编写了一个原型1,当我模拟几十个句子的树库时它看起来效果很好,但是内存使用是不可接受的.我尝试用C语言编写,但到目前为止,由于我之前从未使用过C,所以非常令人沮丧.这是一些数据(n是语法所基于的句子数):

n    mem
9    173M
18   486M
36   836M

这种增长模式是给出最佳优先算法的预期,但是开销量是我所关心的.根据heapy的内存使用量比这些数字小十倍,valgrind报告了类似的内容.导致这种差异的原因是什么,我可以用Python(或Cython)做些什么呢?也许是因为碎片?或许它是python词典的开销?

一些背景:两个重要的数据结构是将边缘映射到概率的议程,以及图表,它是将非终结符和位置映射到边的字典.议程使用heapdict(内部使用dict和heapq列表)实现,图表中包含将非终结符号和位置映射到边缘的字典.议程经常插入和删除,图表只能插入和查找.我用这样的元组表示边缘:

(("S", 111), ("NP", 010), ("VP", 100, 001))

字符串是语法中的非终结符号,位置编码为位掩码.当成分不连续时,可以有多个位置.因此,这个边缘可以代表对“是玛丽快乐”的分析,其中“是”和“快乐”都属于VP.图表字典由此边缘的第一个元素(“S”,111)索引.在新版本中,我尝试转换此表示形式,希望它可以因重用而节省内存:

(("S", "NP", "VP), (111, 100, 011))

我认为Python只会在第一部分存储一次,如果它与不同的位置组合发生,虽然我不确定这是真的.在任何一种情况下,它似乎没有任何区别.

所以基本上我想知道的是,是否值得继续我的Python实现,包括使用Cython和不同的数据结构做事,或者从头开始用C编写它是唯一可行的选择.

更新:经过一些改进后,我不再遇到内存使用问题.我正在研究优化的Cython版本.我会将赏金奖励给提高代码效率的最有用的建议.在http://student.science.uva.nl/~acranenb/plcfrs_cython.html一个带注释的版本

1 https://github.com/andreasvc/disco-dop/
– 运行test.py来解析一些句子.需要python 2.6,nltkheapdict

解决方法:

I figured that Python would store the first part only once if it would occur in combination with different positions

不必要:

>>> ("S", "NP", "VP") is ("S", "NP", "VP")
False

你可能想要intern所有引用非终端的字符串,因为你似乎在rcgrules.py中创建了很多这些字符串.如果你想实习一个元组,那么先把它变成一个字符串:

>>> intern("S NP VP") is intern(' '.join('S', 'NP', 'VP'))
True

否则,你将不得不“复制”元组而不是重新构造它们.

(如果您是C新手,那么在其中重写这样的算法不太可能提供很多内存优势.您必须首先评估各种哈希表实现,并了解其容器中的复制行为.我已经发现boost :: unordered_map非常浪费很多小哈希表.)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐