从预保存的DocBin中提取实体失败,寻求技术解决方案
问题:从spaCy的DocBin中无法提取实体
我有大约700k份文档,用spaCy处理后存入DocBin,之前用PhraseMatcher做关键词搜索没问题,现在想基于这个DocBin构建知识图谱,但访问不到实体。虽然听说DocBin不保存这类信息,但打印DocBin.tokens能得到非空值。
加载DocBin的代码
import spacy from spacy.tokens import DocBin from spacy.vocab import Vocab nlp = spacy.load('fr_dep_news_trf') DocBinPath = r'C:\[Redacted]\FRdocBin.nlp' loadedDocBin = DocBin(Vocab()).from_disk(DocBinPath) DocList=list(loadedDocBin.get_docs(nlp.vocab)) for doc in DocList People = list(set([ent.text for ent in doc.ents if ent.label_=='PERSON']))
这段代码无报错,但doc.ents始终为空。
保存DocBin的代码
FRdoc_bin = DocBin (store_user_data=True,attrs=['ENT_TYPE','LEMMA','LIKE_EMAIL','LIKE_URL','LIKE_NUM','ORTH','POS','HEAD','DEP']) doc = frNLP(text) FRdoc_bin.add(doc) FRdoc_bin.to_disk(CreatedModelPath+r'\FRdocBin'+'.nlp')
原因分析
你保存DocBin时指定了ENT_TYPE属性,但**doc.ents是由完整的实体跨度(span)信息组成的,而ENT_TYPE只是单个token的实体类型标记**,两者不是同一概念。DocBin不会自动保存实体跨度,必须明确添加重建doc.ents所需的属性。
解决方法
修改保存代码,在attrs中添加ENT_IOB属性——它记录了每个token在实体中的位置(B=实体起始、I=实体中间、O=无实体),这是spaCy重建实体跨度的核心依据:
# 新增ENT_IOB属性,用于恢复实体的完整跨度 FRdoc_bin = DocBin(store_user_data=True, attrs=['ENT_TYPE','ENT_IOB','LEMMA','LIKE_EMAIL','LIKE_URL','LIKE_NUM','ORTH','POS','HEAD','DEP']) doc = frNLP(text) FRdoc_bin.add(doc) FRdoc_bin.to_disk(CreatedModelPath+r'\FRdocBin'+'.nlp')
加载时使用和处理文档时相同的nlp.vocab初始化DocBin,确保标签映射正确:
import spacy from spacy.tokens import DocBin nlp = spacy.load('fr_dep_news_trf') DocBinPath = r'C:\[Redacted]\FRdocBin.nlp' # 直接用nlp.vocab初始化,无需单独创建Vocab() loadedDocBin = DocBin().from_disk(DocBinPath) DocList = list(loadedDocBin.get_docs(nlp.vocab)) for doc in DocList: People = list(set([ent.text for ent in doc.ents if ent.label_=='PERSON'])) print(People) # 现在可以正常提取PERSON实体
补充说明
- 若需要实体ID信息,可在
attrs中额外添加ENT_ID,但构建知识图谱一般仅需ENT_TYPE和ENT_IOB。 - 加载DocBin时必须使用处理文档时的同一个nlp实例的vocab,否则会出现标签不匹配的问题。
内容的提问来源于stack exchange,提问作者user21419267
相关产品推荐
相关产品推荐

