如何在SpaCy v3中使用BILUO schema更新NER模型并解决Example报错
问题修复方案
核心错误原因
- Example构造参数错误:SpaCy v3的
Example初始化仅接受2个位置参数,分别是预测Doc和参考Doc,不支持references关键字传参,且你直接传入BILUO标签列表作为第二个参数,类型不匹配。 - 输入参数对齐错误:你构建
Doc时直接将字符串传给words参数,会将每个字符拆分为独立token,和你标注的BILUO标签长度完全不匹配。 nlp.update传参错误:SpaCy v3的update方法仅需要传入Example对象列表,不需要额外传入原始文本序列。- 标注未转换为实体格式:BILUO标签需要先设置为参考Doc的实体属性,才能被训练逻辑识别。
修正后完整可运行代码
import spacy import random from spacy.util import minibatch, compounding from spacy.tokens import Doc, Span from spacy.training import Example # 你的标注数据 data = [('Nanette Barragán', list(['B-PERSON', 'L-PERSON'])), ('Jack Bergman', list(['B-PERSON', 'L-PERSON'])), ('Andy Biggs', list(['B-PERSON', 'L-PERSON'])), ('Lisa Blunt Rochester', list(['B-PERSON', 'I-PERSON', 'L-PERSON'])), ('Anthony Brown', list(['B-PERSON', 'L-PERSON'])), ('Ted Budd', list(['B-PERSON', 'L-PERSON'])), ('Troy Balderson', list(['B-PERSON', 'L-PERSON'])), ('James Baird', list(['B-PERSON', 'L-PERSON'])), ('Tim Burchett', list(['B-PERSON', 'L-PERSON']))] nlp = spacy.load("en_core_web_sm") ner = nlp.get_pipe("ner") # en_core_web_sm自带PERSON标签,无需重复添加,若新增自定义实体可保留此逻辑 # ner.add_label('PERSON') other_pipes = [pipe for pipe in nlp.pipe_names if pipe != 'ner'] with nlp.disable_pipes(*other_pipes): # 仅训练NER组件 optimizer = nlp.create_optimizer() for itn in range(10): print(f"Starting iteration {itn}") random.shuffle(data) losses = {} batches = minibatch(data, size=compounding(4.0, 16.0, 1.001)) for batch in batches: examples = [] for text, biluo_tags in batch: # 构造预测用Doc,使用模型自带分词逻辑保证对齐 pred_doc = nlp.make_doc(text) # 构造参考Doc,token和预测Doc完全对齐 ref_doc = Doc(pred_doc.vocab, words=[t.text for t in pred_doc]) # 从BILUO标签构造实体Span ents = [] for idx, tag in enumerate(biluo_tags): if tag == "O": continue label = tag.split("-")[-1] ents.append(Span(ref_doc, idx, idx+1, label=label)) ref_doc.set_ents(ents) # 按位置参数构造Example,不要关键字参数 examples.append(Example(pred_doc, ref_doc)) # update仅需传入examples列表,无需额外传texts nlp.update( examples, drop=0.4, losses=losses, sgd=optimizer ) print(f"Iteration {itn} losses: {losses['ner']}") # 测试训练效果 test_doc = nlp("Nanette Barragán and Lisa Blunt Rochester are both members of the US Congress.") print("识别结果:", [(ent.text, ent.label_) for ent in test_doc.ents])
验证说明
运行后会输出每轮的训练损失,测试环节会正确识别输入文本中的两个国会议员姓名为PERSON实体。
内容的提问来源于stack exchange,提问作者mjoy
相关产品推荐
相关产品推荐

