仅来自 PhraseMatcher 的 Spacy 实体

Spacy Entity from PhraseMatcher only

我正在使用 Spacy for a NLP project. I have a list of phrases I'd like to mark as a new entity type. I originally tried training a NER model but since there's a finite terminology list, I think simply using a Matcher should be easier. I see in the documentation,您可以将实体添加到基于匹配器的文档中。我的问题是:如何为 new 实体执行此操作,而不将 NER 管道标记为该实体的任何其他标记?理想情况下,只有通过我的匹配器找到的标记才应标记为实体,但我需要将其作为标签添加到 NER 模型中,然后最终将一些标记标记为实体。

关于如何最好地完成这项工作有什么建议吗?谢谢!

我认为您可能想要实现类似于 this example – i.e. a custom pipeline component 的东西,它使用 PhraseMatcher 并分配实体。 spaCy 的 built-in 实体识别器也只是一个管道组件——因此您可以将其从管道中删除并添加您的自定义组件:

nlp = spacy.load('en')               # load some model
nlp.remove_pipe('ner')               # remove the entity recognizer
entity_matcher = EntityMatcher(nlp)  # use your own entity matcher component
nlp.add_pipe(entity_matcher)         # add it to the pipeline

您的实体匹配器组件可能看起来像这样:

from spacy.matcher import PhraseMatcher
from spacy.tokens import Span

class EntityMatcher(object):
    name = 'entity_matcher'

    def __init__(self, nlp, terms, label):
        patterns = [nlp(term) for term in terms]
        self.matcher = PhraseMatcher(nlp.vocab)
        self.matcher.add(label, None, *patterns)

    def __call__(self, doc):
        matches = self.matcher(doc)
        spans = []
        for label, start, end in matches:
            span = Span(doc, start, end, label=label)
            spans.append(span)
        doc.ents = spans
        return doc

当您的组件初始化时,它会为您的术语创建匹配模式,并将它们添加到短语匹配器中。我的示例假设您有一个 terms 列表和一个 label 列表,您想要为这些术语分配:

entity_matcher = EntityMatcher(nlp, your_list_of_terms, 'SOME_LABEL')
nlp.add_pipe(entity_matcher)

print(nlp.pipe_names)  # see all components in the pipeline

当您在文本字符串上调用 nlp 时,spaCy 将标记文本文本以创建一个 Doc 对象并按顺序调用 Doc 上的各个管道组件。然后,自定义组件的 __call__ 方法会在文档中找到匹配项,为每个匹配项创建一个 Span(允许您分配自定义标签),最后将它们添加到 doc.ents 属性 和 returns Doc.

您可以根据自己的喜好构建您的管道组件——例如,您可以扩展它以从文件加载到您的术语列表中,或者让它为不同的标签添加多个规则到 PhraseMatcher

从 spacy v2.1 开始,spacy 提供了一个开箱即用的解决方案:EntityRuler class.

要仅匹配您关心的实体,您可以在添加自定义组件之前禁用实体管道组件,或者实例化一个空语言模型并向其中添加自定义组件,例如

from spacy.lang.en import English
from spacy.pipeline import EntityRuler

nlp = English()

my_patterns = [{"label": "ORG", "pattern": "spacy team"}]
ruler = EntityRuler(nlp)
ruler.add_patterns(my_patterns)
nlp.add_pipe(ruler)

doc = nlp("The spacy team are amazing!")
assert str(doc.ents[0]) == 'spacy team'

如果您只想对术语列表中的文档和完全匹配实体进行标记,那么实例化空语言模型可能是最简单的解决方案。