首页 > 解决方案 > 如何通过规则合并 spaCy 中的实体

问题描述

我想使用 spaCy 3 的 en_core_web_lg 中的一些实体,但将一些标记为“ORG”的内容替换为“ANALYTIC”,因为它将我想要使用的 3 个字符代码(例如“P&L”和“VaR”)视为组织。该模型具有 DATE 实体,我可以保留这些实体。我已经阅读了所有文档,似乎我应该能够使用 EntityRuler,语法如下,但我没有得到任何结果。我现在已经接受了 2-3 次培训,阅读了所有用法和 API 文档,但我没有看到任何工作代码示例。我收到各种不同的错误消息,例如我需要装饰器或其他。楼主,真的有那么难吗?

我的代码:

analytics = [
    [{'LOWER':'risk'}],
    [{'LOWER':'pnl'}],
    [{'LOWER':'p&l'}],
    [{'LOWER':'return'}],
    [{'LOWER':'returns'}]
]


matcher = Matcher(nlp.vocab)
matcher.add("ANALYTICS", analytics)

doc = nlp(text)

# Iterate over the matches
for match_id, start, end in matcher(doc):
    # Create a Span with the label for "ANALYTIC"
    span = Span(doc, start, end, label="ANALYTIC")

    # Overwrite the doc.ents and add the span
    doc.ents = list(doc.ents) + [span]

    # Get the span's root head token
    span_root_head = span.root.head
    # Print the text of the span root's head token and the span text
    print(span_root_head.text, "-->", span.text)

当我的新 'ANALYTIC' 实体跨度与现有的 'ORG' 相冲突时,这当然会崩溃。但我不知道如何离线合并这些并将它们放回去,或者使用规则创建我自己的自定义管道。这是来自实体标尺的建议文本。没有线索。

# Construction via add_pipe
ruler = nlp.add_pipe("entity_ruler")

# Construction from class
from spacy.pipeline import EntityRuler
ruler = EntityRuler(nlp, overwrite_ents=True)

标签: nlpentityspacy

解决方案


所以当你说它“崩溃”时,发生的事情是你有冲突的跨度。具体来说doc.ents,每个令牌最多只能在一个跨度中。在您的情况下,您可以通过修改此行来解决此问题:

doc.ents = list(doc.ents) + [span]

在这里,您已经包含了旧跨度(您不想要的)和新跨度。如果您doc.ents没有旧跨度,这将起作用。

还有其他方法可以做到这一点。在这里,我将使用一个简化的示例,您总是希望更改长度为 3 的项目,但您可以修改它以使用您的特定单词列表或其他内容。

您可以直接修改实体标签,如下所示:

for ent in doc.ents:
    if len(ent.text) == 3:
        ent.label_ = "CHECK"
    print(ent.label_, ent, sep="\t")

如果你想使用 EntityRuler,它看起来像这样:

import spacy

nlp = spacy.load("en_core_web_sm")

ruler = nlp.add_pipe("entity_ruler", config={"overwrite_ents":True})

patterns = [
        {"label": "ANALYTIC", "pattern": 
            [{"ENT_TYPE": "ORG", "LENGTH": 3}]}]

ruler.add_patterns(patterns)

text = "P&L reported amazing returns this year."

doc = nlp(text)

for ent in doc.ents:
    print(ent.label_, ent, sep="\t")

还有一件事——你没有说你使用的是什么版本的 spaCy。我在这里使用 spaCy v3。添加管道的方式在 v3 中有所改变。


推荐阅读