【问题标题】:Replace entity with its label in SpaCy用 SpaCy 中的标签替换实体
【发布时间】:2019-11-05 13:31:11
【问题描述】:

SpaCy 是否有用其标签替换 SpaCy NER 检测到的实体? 例如: 我一边玩 Apple Macbook,一边吃苹果。

我已经使用 SpaCy 训练了 NER 模型来检测“FRUITS”实体,该模型成功地将第一个“apple”检测为“FRUITS”,而不是第二个“Apple”。

我想通过用标签替换每个实体来对数据进行后处理,所以我想用“FRUITS”替换第一个“apple”。句子将是“我在玩 Apple Macbook 时正在吃水果。

如果我只是使用正则表达式,它也会将第二个“Apple”替换为“FRUITS”,这是不正确的。有什么聪明的方法可以做到这一点吗?

谢谢!

【问题讨论】:

  • 请发布您的代码!

标签: nlp spacy named-entity-recognition


【解决方案1】:

实体标签是令牌的一个属性(参见here

import spacy
from spacy import displacy
nlp = spacy.load('en_core_web_lg')

s = "His friend Nicolas is here."
doc = nlp(s)

print([t.text if not t.ent_type_ else t.ent_type_ for t in doc])
# ['His', 'friend', 'PERSON', 'is', 'here', '.']

print(" ".join([t.text if not t.ent_type_ else t.ent_type_ for t in doc]) )
# His friend PERSON is here .

编辑:

为了处理实体可以跨越多个单词的情况,可以使用以下代码:

s = "His friend Nicolas J. Smith is here with Bart Simpon and Fred."
doc = nlp(s)
newString = s
for e in reversed(doc.ents): #reversed to not modify the offsets of other entities when substituting
    start = e.start_char
    end = start + len(e.text)
    newString = newString[:start] + e.label_ + newString[end:]
print(newString)
#His friend PERSON is here with PERSON and PERSON.

更新:

Jinhua Wang 让我注意到,现在有一种更内置、更简单的方法可以使用 merge_entities 管道来执行此操作。 请参阅下面的金华回答。

【讨论】:

  • 谢谢!无论如何,如果实体文本是短语,我怎样才能使它不重复?例如:“他的朋友尼古拉斯布朗特来了。”我需要让它“他的朋友 PERSON 在这里”。而不是“他的朋友 PERSON PERSON 在这里。”。谢谢!
  • 我添加了一个编辑来处理这种情况,即实体可以跨越多个单词。希望有帮助!
  • 这个解决方案太棒了!
  • @DBaker 请参阅下面的解决方案以获取更新。
【解决方案2】:

当实体可以跨越多个单词时,对上述@DBaker 的解决方案进行更优雅的修改:

import spacy
from spacy import displacy
nlp = spacy.load('en_core_web_lg')
nlp.add_pipe("merge_entities")

s = "His friend Nicolas J. Smith is here with Bart Simpon and Fred."
doc = nlp(s)

print([t.text if not t.ent_type_ else t.ent_type_ for t in doc])
# ['His', 'friend', 'PERSON', 'is', 'here', 'with', 'PERSON', 'and', 'PERSON', '.']

print(" ".join([t.text if not t.ent_type_ else t.ent_type_ for t in doc]) )
# His friend PERSON is here with PERSON and PERSON .

您可以查看 Spacy here 上的文档。它使用内置的管道来完成这项工作,并且对多处理有很好的支持。我相信这是官方支持的用标签替换实体的方式。

【讨论】:

  • 有时是打印数字,为什么? print([t.text if not t.ent_type_ else t.ent_type_ for t in doc]) 给出类似:[A, quick, 1501522819326771872, fox]
  • t.ent_type_ 在使用xx_ent_wiki_sm 模型时打印这样的数字。
【解决方案3】:

@DBaker 答案的稍短版本,它使用 end_char 而不是计算它:

for ent in reversed(doc.ents):
    text = text[:ent.start_char] + ent.label_ + text[ent.end_char:]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-05
    • 2021-11-01
    • 2020-11-04
    • 1970-01-01
    • 2022-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多