我写了一个python类,它使用一个简单的函数来计算文本中的单字节频率:
for listIndex in range(len(words)):
uniGramDict[words[listIndex]] = float(float(words.count(words[listIndex])) / float(len(words)))
我在 windows命令行中测试了包含6个令牌的语料库中的脚本,并取得了预期的结果:
{'a': 0.4, 'c': 0.2, 'b': 0.2, 'd': 0.2}
现在我在一个更大的语料库中运行这个脚本,在Windows命令行中有~750000个令牌,似乎需要花费太多时间,我现在等待40多分钟。
当我查看任务管理器中cmd.exe的CPU /内存使用情况时,我发现几乎没有使用任何资源:0.0%cpu,1.349K ram。
当我查看任务管理器中python.exe * 32的CPU /内存使用情况时,我发现使用的资源不多:25%cpu(我猜是4个核心中的一个)和43.544K ram。
我有什么办法可以加快任务吗?是import multithreading
并正确使用我要找的东西吗?
谢谢,
湾
答案 0 :(得分:0)
您不需要多线程来加速该过程。只是一个更好的算法。 在您的代码中 - 为了计算每个单词 - 您进行50000 * 50000 = 2,500,000,000比较!每当你再次看到它时,你就会数字。 (想象一下你的语料库是50000单词“foo”。所以你计算50000次单词“foo”,只保留最后一个结果丢弃其他49999.)
这是二次增长。对于两倍的令牌,你需要4倍的时间。
而是通过您的列表一次并计算您在途中看到的每个字词:
from collections import defaultdict
def goodcount(words):
wordcount = defaultdict(int)
for word in words:
wordcount[word] += 1
return {word:float(wordcount[word])/len(words) for word in wordcount}
您可以使用标准词典以及defaultdict
来执行此操作,但是您必须首先初始化每个条目:
def goodcount2(words):
wordcount = dict()
for word in words:
if wordcount.has_key(word):
wordcount[word] += 1
else:
wordcount[word] = 1
return {word:float(wordcount[word])/len(words) for word in wordcount}
让我们进行比较:
tokens: 50000
yourcount: 69.432s
goodcount: 0.016s
goodcount2: 0.031s
不确定为什么要等20分钟,但16秒的工作70秒已经有点太多了。
修改强>
我看到你现在使用750,000令牌。这是以前的五倍(50,000)。所以你的代码应该是以前的225倍!
在我的机器上大约4小时22分钟。 线性方法应该需要大约。 15 * 0.016s = 0.24 s
答案 1 :(得分:0)
我愿意。
from __future__ import division
for listIndex in xrange(len(words)):
try:
uniGramDict[words[listIndex]] += 1
except:
uniGramDict[words[listIndex]] = 1
我使用xrange
的原因是因为它比range
快得多
以及我使用__future__
导入的原因,因为它根本没有带您float
功能,因为/
现在代表真正的分割,而不是地板分割。
注意:__future__
导入应位于程序的第一行