Spacy,匹配器具有跨越单个令牌的实体

时间:2019-08-13 12:35:25

标签: python-3.x nlp spacy

我正在尝试创建一个匹配器,以在文本中查找否定的自定义实体。对于跨越单个令牌的实体,它工作正常,但是我在尝试捕获跨越多个令牌的实体时遇到了麻烦。

例如,假设我的自定义实体是动物(并标记为IP_MULTICAST_LOOP

token.ent_type_ = "animal"(请注意,最后一个实体有两个词)。

现在,我想在文本中找到但被否定的那些实体,因此我可以使用以下模式创建一个简单的匹配器:

["cat", "dog", "artic fox"]

例如,我有以下文字:

[{'lower': 'no'}, {'ENT_TYPE': {'REGEX': 'animal', 'OP': '+'}}]

我可以成功捕获There is no cat in the house and no artic fox in the basementno cat,但是最后一场比赛是不正确的,因为完整比赛应该是no artic。这是由于模式中的no artic fox与单个自定义实体而不是两个匹配。如何修改模式以将较长的匹配优先于较短的匹配?

1 个答案:

答案 0 :(得分:1)

一种解决方案是使用doc retokenize method以便将每个多令牌实体的各个令牌合并为一个令牌:

import spacy
from spacy.pipeline import EntityRuler
nlp = spacy.load('en_core_web_sm', parse=True, tag=True, entity=True)

animal = ["cat", "dog", "artic fox"]
ruler = EntityRuler(nlp)
for a in animal:
    ruler.add_patterns([{"label": "animal", "pattern": a}])
nlp.add_pipe(ruler)


doc = nlp("There is no cat in the house and no artic fox in the basement")

with doc.retokenize() as retokenizer:
    for ent in doc.ents:
        retokenizer.merge(doc[ent.start:ent.end])


from spacy.matcher import Matcher
matcher = Matcher(nlp.vocab)
pattern =[{'lower': 'no'},{'ENT_TYPE': {'REGEX': 'animal', 'OP': '+'}}]
matcher.add('negated animal', None, pattern)
matches = matcher(doc)


for match_id, start, end in matches:
    span = doc[start:end]
    print(span)

现在输出为:

  

没有猫
  没有北极狐