【问题标题】:Spacy, matcher with entities spanning more than a single tokenSpacy,具有跨越多个令牌的实体的匹配器
【发布时间】:2019-08-13 12:35:25
【问题描述】:

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

例如,假设我的自定义实体是动物(并标记为 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 basement

我可以成功捕获no catno artic,但是最后一个匹配不正确,因为完整匹配应该是no artic fox。这是由于模式中的 OP: '+' 匹配单个自定义实体而不是两个。如何修改模式以优先考虑较长的匹配项而不是较短的匹配项?

【问题讨论】:

    标签: python-3.x nlp spacy


    【解决方案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)
    
    

    现在的输出是:

    没有猫
    没有北极狐

    【讨论】:

    • 有了这个解决方案,我什至不需要在自定义实体中添加...{'OP': '+'}
    猜你喜欢
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多