对于非常一般的标题感到抱歉,但我会尝试尽可能具体。
我正在开发一个文本挖掘应用程序。我有大量的形式的键值对((word,corpus) - > occurence_count)(一切都是整数),我存储在多个python词典中(tuple-> int)。这些值分布在磁盘上的多个文件中(我将它们腌制)。为了理解数据,我需要聚合这些词典。基本上,我需要找到一种方法来查找所有词典中特定键的所有出现次数,并将它们相加以获得总计数。
如果我一次加载多个字典,我的内存耗尽,这就是我必须首先拆分它们的原因。当我尝试时,我遇到了性能问题。我目前正在尝试将值存储在DB(mysql)中,一次处理多个字典,因为mysql提供行级锁定,这既好(因为它意味着我可以并行化此操作)又坏(因为它减慢了)插入查询)
我有什么选择?编写一个基于部分磁盘的字典是一个好主意,这样我就可以一次处理一个dicts?使用LRU替换策略?有什么我完全忘记了吗?
谢谢!
答案 0 :(得分:2)
存在基于磁盘的字典 - 请参阅shelve模块。架子上的键必须是字符串,但您只需在元组上使用str
即可获得等效的字符串键;另外,我读你的Q意思是你只想要word
作为关键,这样更容易(str
- 或者,对于词汇表< 4GB,一个struct.pack - 将是细)。
一个好的关系引擎(特别是PostgreSQL)可以很好地为你服务,但是一次处理一个字典以将所有语料库上的每个单词出现聚合成shelf
对象也应该没问题(不是那么快,但是更简单的代码,因为shelf
与dict
非常相似,除了键上的类型约束[[和可变值的警告,但是因为你的值是int
s需要不关心你。)
答案 1 :(得分:0)
如果我理解你的问题,那就是这样的话
from collections import defaultdict
import pickle
result = defaultdict(int)
for fn in filenames:
data_dict = pickle.load(open(fn))
for k,count in data_dict.items():
word,corpus = k
result[k]+=count
答案 2 :(得分:0)
如果我正确地理解了你的问题并且你有单词和语料库的整数id,那么你可以通过从dict切换到列表,甚至更好,一个numpy数组来获得一些性能。这可能很烦人!
基本上,你需要用一个整数替换元组,我们可以将其称为newid。你希望所有的newids都对应一个单词,语料库对,所以我会计算每个语料库中的单词,然后对每个语料库都有一个起始newid。 (word,corpus)的newid将是word + start_newid [corpus]。
如果我误解了您并且您没有这样的ID,那么我认为这个建议可能仍然有用,但您必须操纵您的数据才能将其转换为整数格式的元组。
您可以尝试的另一件事是重新整理数据。
假设您只能在内存中容纳1.1个这些怪物。然后,您可以加载一个,并创建一个较小的dict或数组,它只对应于(word,corpus)对的前10%。您可以扫描加载的dict,并处理前10%中的任何一个。完成后,您可以将结果写回磁盘,然后为第二个10%执行另一次传递。这将需要10次通过,但这可能适合你。
如果您根据内存中的内容选择了之前的分块,那么您将不得不随意将旧的分词分成两半,以便在保存结果dict / array时可以将其保留在内存中。