减少语料库中计算词频的计算时间(python)

减少语料库中计算词频的计算时间(python),python,nlp,Python,Nlp,我的函数基本上返回单词列表,如果一个单词出现在至少n个句子中,那么它就在列表中。我要做的是遍历self.all句子是一个单词列表(句子),遍历self.wordSet(语料库中所有唯一的单词),并将每个单词的频率添加到字典(wordFreqDict) 然后循环遍历单词freqdict并将频率>=n的单词添加到结果列表中 我假设这会起作用,但检查结果要花太长时间 有没有一种方法可以提高效率并缩短计算时间 编辑: 下面是self.all句子的计算方法 def foo(self, n): wo

我的函数基本上返回单词列表,如果一个单词出现在至少n个句子中,那么它就在列表中。我要做的是遍历self.all句子是一个单词列表(句子),遍历self.wordSet(语料库中所有唯一的单词),并将每个单词的频率添加到字典(wordFreqDict)

然后循环遍历单词freqdict并将频率>=n的单词添加到结果列表中

我假设这会起作用,但检查结果要花太长时间

有没有一种方法可以提高效率并缩短计算时间

编辑:

下面是self.all句子的计算方法

def foo(self, n):
    wordFreqDict = defaultdict(int)
    resultList = []

    for sentence in self.allSentences:
        for word in self.wordSet:
            if word in sentence:
                wordFreqDict[word] += 1

    for candidateWord in wordFreqDict:
        if wordFreqDict[candidateWord] >= n:
            resultList.append(candidateWord)

    return resultList
以及self.wordSet:

def storeAllSentences(self, corpus):
    for sentence in corpus:
        self.allSentences.append(sentence)

这里的一个假设是,如果一个词在至少
n
个句子中唯一出现,则选择该词。所以,即使它在一个句子中出现10次,那仍然是一次


两个突出的问题是嵌套循环和对字符串的
in
检查。这实际上是立方复杂性。应该可以使用
设置
+
计数器
来大幅减少这种情况

def getUniqueWordSet(self, corpus):
    for sentence in self.allSentences:
        for word in sentence:
            self.wordSet.append(word)

    self.wordSet = set(self.wordSet)
在这里,我使用正则表达式删除特殊字符和标点符号,然后拆分并检索句子中所有唯一的单词。然后更新
计数器

最后,使用
itertools.takewhile
提取所需频率(或更多)的所有单词并返回


如果
sent
是一个字符串句子,您可以使用基于
re
的过滤删除标点符号,然后拆分:

from collections import Counter
from itertools import takewhile

def foo(self, n):
    c = Counter()
    for sent in self.allSentences:
        c.update(set(sent))

    resultSet = list(itertools.takewhile(lambda x: x[1] >= n, c.most_common()))

    return resultSet
这并不考虑单词是否属于
self.wordSet
。因此,如果您也想这样做,您可以稍微修改第一个循环,以包含
过滤器
步骤:

import re

tempWordSet = set(re.sub('[^\w\s]+', '', sent).split())  
c.update(tempWordSet)
或者,使用第二种技术:

 c.update(set(filter(lambda x: x in self.wordSet, sent)))


另一方面,您是否正在尝试执行文本挖掘?您可能有兴趣研究。

这里的一个假设是,如果一个词在至少
n
个句子中唯一出现,则选择该词。所以,即使它在一个句子中出现10次,那仍然是一次


两个突出的问题是嵌套循环和对字符串的
in
检查。这实际上是立方复杂性。应该可以使用
设置
+
计数器
来大幅减少这种情况

def getUniqueWordSet(self, corpus):
    for sentence in self.allSentences:
        for word in sentence:
            self.wordSet.append(word)

    self.wordSet = set(self.wordSet)
在这里,我使用正则表达式删除特殊字符和标点符号,然后拆分并检索句子中所有唯一的单词。然后更新
计数器

最后,使用
itertools.takewhile
提取所需频率(或更多)的所有单词并返回


如果
sent
是一个字符串句子,您可以使用基于
re
的过滤删除标点符号,然后拆分:

from collections import Counter
from itertools import takewhile

def foo(self, n):
    c = Counter()
    for sent in self.allSentences:
        c.update(set(sent))

    resultSet = list(itertools.takewhile(lambda x: x[1] >= n, c.most_common()))

    return resultSet
这并不考虑单词是否属于
self.wordSet
。因此,如果您也想这样做,您可以稍微修改第一个循环,以包含
过滤器
步骤:

import re

tempWordSet = set(re.sub('[^\w\s]+', '', sent).split())  
c.update(tempWordSet)
或者,使用第二种技术:

 c.update(set(filter(lambda x: x in self.wordSet, sent)))

另一方面,您是否正在尝试执行文本挖掘?您可能有兴趣研究。

集合词集可能比单个句子中的词至少大两个数量级。因此,在一个句子中通过单词循环是有意义的。然而,这要求拆分一个句子并不是一个真正缓慢的操作。如果是,您应该在getUniqueWordSet中完成整个过程。这里仅更改了第一个for循环:

 tempWordSet = set(filter(lambda x: x in self.wordSet, 
                         re.sub('[^\w\s]+', '', sent).split()))
集合词集可能比单个句子中的词至少大两个数量级。因此,在一个句子中通过单词循环是有意义的。然而,这要求拆分一个句子并不是一个真正缓慢的操作。如果是,您应该在getUniqueWordSet中完成整个过程。这里仅更改了第一个for循环:

 tempWordSet = set(filter(lambda x: x in self.wordSet, 
                         re.sub('[^\w\s]+', '', sent).split()))


使用线程怎么样?
设置
+
计数器
应该能真正提高这一点。@堆栈,不。如果算法在单个处理环境中不能很好地工作,那么将其并行化是没有意义的。@cᴏʟᴅsᴘᴇᴇᴅ 你能详细说明一下吗?@user6792790在做这件事之前,我需要一些信息。您的函数的输入是什么?文档在哪里,如何标记句子?使用线程如何?
set
+
Counter
应该能真正提高这一点。@Stack,不是。如果算法在单个处理环境中不能很好地工作,那么并行化它就没有意义了。@cᴏʟᴅsᴘᴇᴇᴅ 你能详细说明一下吗?@user6792790在做这件事之前,我需要一些信息。您的函数的输入是什么?文档在哪里?您如何标记句子?谢谢,但它在以下行上给了我一个“TypeError:预期的字符串或类似字节的对象”:tempWordSet=set(re.sub('[^\w\s]+','',sent).split()@user6792790噢,
sent
不是字符串吗?这是一张字表吗?是的。snet是一个单词列表。对不起,我应该clarified@user6792790没问题,我已经编辑了我的答案。现在应该可以工作了。还可以使用
filter
查看选项,并在需要时使用它。@user6792790没问题!现在的表演怎么样?我打赌现在应该好多了。谢谢,但它在以下行上给了我一个“TypeError:预期的字符串或类似字节的对象”:tempWordSet=set(re.sub('[^\w\s]+','',sent).split()@user6792790噢,
sent
不是字符串吗?这是一张字表吗?是的。snet是一个单词列表。对不起,我应该clarified@user6792790没问题,我已经编辑了我的答案。现在应该可以工作了。还可以使用
filter
查看选项,并在需要时使用它。@user6792790没问题!现在的表演怎么样?我敢打赌现在应该好多了。