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

问题描述

是否可以使用BERT的偏移量将实体添加到spacy doc对象?问题是我的整个渠道都依赖spacy,并且我正在使用spacy不提供支持的最新PUBMEDBERT。

由于分词化完全不同,因此有时pubmedbert给定的实体偏移量不会导致有效的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']设置为标签

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

非常感谢您提供任何帮助,谢谢。

解决方法

由于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)查看每个标记的字符开始和长度。