Spacy 3.0 调用nlp.update方法触发E978 TypeError的问题排查
Spacy 3.0 训练接口类型报错定位与修复
根因定位
- 接口规则变更:Spacy 3.0 对
nlp.update的入参做了强校验重构,不再兼容2.x版本默认支持的「(原始文本, 标注字典)元组列表」格式,接口仅接受spacy.training.Example对象组成的列表作为入参。 - 调试误区说明:你检查到
type(batch)为list的判断只覆盖了外层容器类型,实际触发报错的是list内部的元素类型——你传入的batch里每个元素还是旧格式的元组(即('xxx文本', {'entities': [...]})结构),所以哪怕你把batch显式转成list,只要内部元素不符合要求,永远会触发E978类型不匹配报错。 - 版本行为差异:Spacy 2.x版本中,
nlp.update会在内部自动把传入的文本+标注元组隐式转换为Example对象,3.0版本移除了这层隐式转换逻辑,完全交由调用方完成对象构造。
修复实现
- 导入Example构造类:
from spacy.training import Example - 把原始训练数据逐行转换为合法的Example对象:
train_examples = [] for text, annotations in TRAIN_DATA: # 用当前nlp管道生成对应原文的基准Doc对象 base_doc = nlp.make_doc(text) # 搭配标注信息构造Example example = Example.from_dict(base_doc, annotations) train_examples.append(example) - 调整训练循环,使用转换后的Example列表作为minibatch的数据源,原有循环逻辑无需改动:
random.shuffle(train_examples) losses = {} for batch in minibatch(train_examples, size=8): nlp.update(batch, sgd=optimizer, drop=0.35, losses=losses)
补充提示:转换Example时必须使用
nlp.make_doc(text)生成基准Doc,不能直接用处理后的完整Doc(比如nlp(text))作为基准,否则会因为管道之前的预测结果和标注不匹配,导致训练梯度计算异常。
内容的提问来源于stack exchange,提问作者Nebukadnezar
相关产品推荐
相关产品推荐

