【发布时间】:2016-03-01 03:06:54
【问题描述】:
我正在尝试加速我的应用程序,我发现下面的简单小函数 (compute_ave_freq) 实际上是最耗费时间的函数之一。罪魁祸首似乎是当它解开 NLTK FreqDist 时;这需要大量的时间。
当然,即使是这么长的时间也不到重新计算 FreqDist 所需时间的一半。有没有更好的方法来保存 NLTK FreqDist 对象?我尝试将它序列化为 JSON,但这会将它保存为一个简单的字典,从而丢失了我需要的许多 NLTK 功能。
代码如下:
def compute_ave_freq(word_forms):
fd = pickle.load(open("data/fd.txt", 'rb'))
total_freq = 0
for form in word_forms:
freq = fd.freq(form)
total_freq += freq
try:
ave_freq = total_freq/len(word_forms)
except ZeroDivisionError:
ave_freq = 0
return ave_freq
这是 LineProfiler 的输出:
Total time: 0.197121 s
File: /home/username/development/appname/filename.py
Function: compute_ave_freq at line 25
Line # Hits Time Per Hit % Time Line Contents
==============================================================
25 def compute_ave_freq(word_forms, debug=False):
26 # word_forms is a list of morphological variations of a word, such as
27 # ['كتبوا', 'كتبو', 'كتبنا', 'كتبت']
28
29 1 78580 78580.0 79.1 fd = pickle.load(open("data/fd.txt", 'rb'))
30 1 3 3.0 0.0 total_freq = 0
31 5 10 2.0 0.0 for form in word_forms:
32 4 20676 5169.0 20.8 freq = fd.freq(form)
33 4 9 2.2 0.0 if debug==True:
34 print(form, '\n', freq)
35 4 6 1.5 0.0 total_freq += freq
36 1 1 1.0 0.0 try:
37 1 3 3.0 0.0 ave_freq = total_freq/len(word_forms)
38 except ZeroDivisionError:
39 ave_freq = 0
40 1 1 1.0 0.0 return ave_freq
谢谢!
【问题讨论】:
-
Unpickling 正在加载到 RAM 中,这是一个相当难以处理的问题,但是一旦加载它就可以了。可能将其放入某些数据库(例如 SQL/Mongo)中会是处理更大数据集的更好方法。否则,请稍等片刻,让它加载到 RAM 中。
-
我认为一般规则可以是“如果您有一个数据集可以完全加载到 RAM 上而没有太大的压力,那么它并没有那么大,而且在索引/查询数据库上节省的时间可能不会是实质性的”。
-
将
fd = pickle.load(open("data/fd.txt", 'rb'))移到函数外,如果fd发生变化,只需将其传递给函数,即def compute_ave_freq(word_forms, fd):。否则,如果fd不变,只需将fd设为全局变量并加载一次即可。 -
谢谢@alvas——我认为这可能是最好的解决方案!
-
这确实奏效了——我将
fd设为全局变量,这将我的例句的解析时间从 7.2 秒提高到了 2.0 秒。我不知道为什么我以前没有想到这一点!
标签: python json serialization nltk pickle