使用 BERT 的偏移量将实体添加到 spacy doc 对象

Posted

技术标签:

【中文标题】使用 BERT 的偏移量将实体添加到 spacy doc 对象【英文标题】:Adding entites to spacy doc object using BERT's offsets 【发布时间】:2021-01-04 00:37:48 【问题描述】:

有没有办法?问题是我的整个管道依赖于 spacy,我使用的是 spacy 不提供支持的最新 PUBMEDBERT。

因此,有时 pubmedbert 给出的实体偏移量不会导致 spacy 的有效 SPAN,因为标记化完全不同。

到目前为止,我做了哪些工作来解决我的问题? 我通过要求 spacy 在标点符号上拆分来制作自定义标记器,类似于 bert,但在某些情况下我无法制定规则。例如:-

text = '''assessment
Exdtve age-rel mclr degn, left eye, with actv chrdl neovas
Mar-10-2020
assessment'''

Pubmedbert 预测 13:17 是一个实体,即 dtve 但是在 spacy doc 对象中添加跨度作为实体时,它会导致 NONE,因为它不是有效的跨度。

span = doc.char_span(row['start'], row['end'], row['ent'])
doc.ents = list(doc.ents) + [span]
TypeError: object of type 'NoneType' has no len()

考虑 row['start'] 为 13, row['end'] 为 17, row['ent'] 为 label

我该如何解决这个问题?无论如何我可以使用 pubmedbert 给出的开始和结束偏移量在 spacy doc 对象中添加实体

非常感谢您对此的任何帮助,谢谢。

【问题讨论】:

【参考方案1】:

由于 spacy 在内部将实体存储为文档中标记上的 IOB 标记,因此您只能在下面添加与完整标记对应的实体跨度。

如果您仅使用此 doc 来存储这些实体(不使用任何其他组件,例如来自另一个模型的标记器或解析器,需要不同的分词器),您可以创建一个与 BERT 具有相同分词的文档型号:

import spacy
from spacy.tokens import Doc

nlp = spacy.blank("en")
# bert_tokens = [..., "Ex", "dtve", ...]
words, spaces = spacy.util.get_words_and_spaces(bert_tokens, text)
doc = Doc(nlp.vocab, words=words, spaces=spaces)

然后您应该能够将实体跨度添加到文档中。

如果您需要原始 spacy 标记化 + 基于不同标记化的实体,那么您必须调整实体字符偏移以匹配 spacy 标记边界才能添加它们。由于这在很大程度上取决于数据/任务(如果dtve 是一个实体,那么Exdtve 是否也一定是同一类型的实体?),您可能需要基于您的数据的自定义解决方案。如果您尝试调整实体跨度以与当前标记对齐,您可以使用token.idxlen(token) 查看每个标记的字符开头和长度。

【讨论】:

另一种方法是将 spacy 的标记器修改为字符明智,然后添加你想要的任何内容作为跨度:D

以上是关于使用 BERT 的偏移量将实体添加到 spacy doc 对象的主要内容,如果未能解决你的问题,请参考以下文章

Spacy 2.0 NER培训

spacy 提取实体关系解析深度树

Spacy 从训练模型中提取命名实体关系

使用使用nltk 和 spacy进行命名实体提取/识别

将自定义 NER 模型添加到 spaCy 管道

Spacy NER将实体拆分为两个独立的实体