在spacy中深度复制PhraseMatcher对象不起作用

时间:2018-09-21 04:43:20

标签: python python-3.x nltk spacy

我想运行一些多处理模块以在文档上并行运行短语匹配。为此,我想到了在一个进程中创建短语匹配对象,然后通过创建PhraseMatcher对象的副本在多个进程之间共享的方法。代码似乎没有给出任何错误就失败了。为了使事情变得更容易,我尝试过这样做以证明我正在努力实现的目标

import copy
import spacy
from spacy.matcher import PhraseMatcher


nlp = spacy.load('en')
color_patterns = [nlp(text) for text in ('red', 'green', 'yellow')]
product_patterns = [nlp(text) for text in ('boots', 'coats', 'bag')]
material_patterns = [nlp(text) for text in ('silk', 'yellow fabric')]

matcher = PhraseMatcher(nlp.vocab)
matcher.add('COLOR', None, *color_patterns)
matcher.add('PRODUCT', None, *product_patterns)
matcher.add('MATERIAL', None, *material_patterns)


matcher2 = copy.deepcopy(matcher)

doc = nlp("yellow fabric")
matches = matcher2(doc)
for match_id, start, end in matches:
    rule_id = nlp.vocab.strings[match_id]  # get the unicode ID, i.e. 'COLOR'
    span = doc[start : end]  # get the matched slice of the doc
    print(rule_id, span.text)

使用matcher2对象,它不提供任何输出,但是使用matcher对象,我可以得到结果。

COLOR yellow
MATERIAL yellow fabric

我坚持了几天。任何帮助将不胜感激。

谢谢。

1 个答案:

答案 0 :(得分:1)

问题的根源是PhraseMatcher是Cython类,在文件matcher.pyx中定义和实现。Cython无法与Deepcopy一起正常工作。

参考this StackOverflow问题的答案:

  

Cython不喜欢对具有函数/方法引用变量的类进行深度复制。这些可变副本将失败。

但是,还有其他选择。如果要对多个文档并行运行PhraseMatcher,则可以对PhraseMatcher的管道方法使用多线程。

您的问题的可能解决方法:

import copy
import spacy
from spacy.matcher import PhraseMatcher


nlp = spacy.load('en_core_web_sm')
color_patterns = [nlp(text) for text in ('red', 'green', 'yellow')]
product_patterns = [nlp(text) for text in ('boots', 'coats', 'bag')]
material_patterns = [nlp(text) for text in ('silk', 'yellow fabric')]

matcher = PhraseMatcher(nlp.vocab)
matcher.add('COLOR', None, *color_patterns)
matcher.add('PRODUCT', None, *product_patterns)
matcher.add('MATERIAL', None, *material_patterns)

doc1 = nlp('yellow fabric')
doc2 = nlp('red lipstick and big black boots')

for doc in matcher.pipe([doc1, doc2], n_threads=4):
    matches = matcher(doc)
    for match_id, start, end in matches:
        rule_id = nlp.vocab.strings[match_id]
        span = doc[start : end]
        print(rule_id, span.text)

希望有帮助!