有没有一种更快的方法来循环一个集合并替换句子中的MWEpython
任务是对由多个单词组成的表达式进行分组(也称为有没有一种更快的方法来循环一个集合并替换句子中的MWEpython,python,loops,dictionary,set,nlp,Python,Loops,Dictionary,Set,Nlp,任务是对由多个单词组成的表达式进行分组(也称为多单词表达式) 给定一个MWE字典,我需要在检测到MWE的输入句子中添加破折号,例如 **Input:** i have got an ace of diamonds in my wet suit . **Output:** i have got an ace-of-diamonds in my wet-suit . 目前,我循环浏览已排序的词典,查看MWE是否出现在句子中,并在出现时替换它们。但是有很多浪费的迭代 有没有更好的办法?一种解决方案是
多单词表达式
)
给定一个MWE字典,我需要在检测到MWE的输入句子中添加破折号,例如
**Input:** i have got an ace of diamonds in my wet suit .
**Output:** i have got an ace-of-diamonds in my wet-suit .
目前,我循环浏览已排序的词典,查看MWE是否出现在句子中,并在出现时替换它们。但是有很多浪费的迭代
有没有更好的办法?一种解决方案是首先产生所有可能的n克,即chunker2()
我会尝试这样做:
- 对于每个句子,构造一组n-gram,长度不超过给定长度(列表中最长的MWE)
- 现在,只需执行
mwe\u nmgrams.intersection(句子图)
并搜索/替换它们
您不必通过迭代原始集合中的所有项来浪费时间
下面是一个稍微快一点的chunker2
:
def chunker3(sentence):
tokens = sentence.split(' ')
len_tokens = len(tokens)
nodes = set()
for i in xrange(0, len_tokens):
for j in xrange(i, len_tokens):
chunks = tokens[i:j]
if len(chunks) > 1:
nodes.add(' '.join(chunks))
intersect = mwe_list.intersection(n)
for i in intersect:
print i
sentence = sentence.replace(i, i.replace(' ', '-'))
return sentence
首先,一个2倍的改进:因为您要用连字符版本替换mwe,所以可以预处理字典(wn mwe en.dic)以消除集合中mwe中的所有连字符,从而消除一个字符串比较。如果您允许在句子中使用连字符,那么您还必须对其进行预处理,可能是在线处理,以获得较小的惩罚。这将把你的运行时间减少一半
接下来是一个小的改进:不可变元组通常比集合或列表更快(集合或列表是可变的,迭代器必须在每个步骤中检查内存中元素的移动)。set()转换将按照您的意愿消除重复项。元组位将把它固定在内存中,允许python解释器及其编译的LIB进行低级迭代优化
最后,在进行所有比较之前,您可能应该将句子和MWE解析为单词或标记,这将减少单词平均长度所需的字符串比较(如果单词平均长度为4个字符,则为4倍)。您还可以嵌套另一个循环来搜索MWE中的第一个单词,作为共享该第一个单词的所有MWE的锚点,从而减少所需字符串比较的长度。但我将把这大部分留给你们在真实数据上的实验。根据intepreter与编译库的效率,在python级别执行所有这些拆分嵌套循环实际上可能会降低速度
下面是前两个简单的“确定”赌注的结果。除非你的句子很短,否则尽管进行了预处理,速度还是应该快2倍
mwe_list = set(i.strip() for i in codecs.open("wn-mwe-en.dic", "r", "utf8").readlines())
mwe_list = tuple(mwe.replace('-', ' ').strip() for mwe in mwe_list)
sentence = sentence.replace('-', ' ').strip()
def chunker(sentence):
for item in mwe_list:
if item in sentence:
...
在我的系统中找不到.dic文件,或者我会为您分析它。是的,速度非常快,13个单词的句子的时间从11.04秒到0.74秒不等。但是对于较长的句子,这会慢得多,有没有修剪ngram的建议?@2er0:你可以考虑最长的MWE,只需确保for
的内部循环从i
到min(i+可能最长的\ngram,len\u标记)
。这应该会加快一点速度。再看看我的答案。我添加了一些细微的更改,这将使您的代码更快一些。谢谢!但这确实起到了更快的作用。希望服务器能够处理2000000个句子的负载,每个句子30-100个单词=)@2er0:没问题。如果您尚未使用它,请查看多处理
模块。这会给你一个巨大的鼓舞。很好。别忘了先用空格替换dic或句子中的任何连字符,这样你的块就可以拆分并匹配它们应该匹配的位置。我很乐意分享我的字典(我粘贴的内容不能超过500kb)。但字典是从下载、提取和下载的。请从参考文献中适当引用。看来我的答案是OBE。
mwe_list = set(i.strip() for i in codecs.open("wn-mwe-en.dic", "r", "utf8").readlines())
mwe_list = tuple(mwe.replace('-', ' ').strip() for mwe in mwe_list)
sentence = sentence.replace('-', ' ').strip()
def chunker(sentence):
for item in mwe_list:
if item in sentence:
...