新训练的spaCy NER模型无POS标签 如何正确启用tagger组件?
问题背景
参照spaCy训练快速入门流程训练NER模型,因仅持有NER标注数据,训练阶段仅针对ner管道开展优化。初始使用的核心配置如下:
[nlp] lang = "en" pipeline = ["tok2vec","ner","tagger"] batch_size = 1000 disabled = [] before_creation = null after_creation = null after_pipeline_creation = null tokenizer = {"@tokenizers":"spacy.Tokenizer.v1"} ... [components.tagger] source = "en_core_web_sm" component = "tagger" replace_listeners = ["model.tok2vec"] ... [training] ... frozen_components = ["tagger"]
训练完成后调用模型做实体预测时,发现实体对应token的pos_属性为空值,复现示例如下:
>>> ent Some Entity >>> ent.label_ 'LABEL_NAME' >>> [token.pos_ for token in ent] ['', '']
初始尝试通过frozen_components配置冻结从en_core_web_sm引入的tagger组件,希望直接复用预训练模型的tagger能力输出POS标签,自定义训练部分仅负责NER预测,但该配置未生效。
故障原因
配置存在两个核心问题:
- spaCy严格按照
pipeline列表的先后顺序执行组件,初始配置中ner排在tagger之前,NER组件执行时tagger还未对token做POS标注,自然读取不到pos_属性值 - tagger配置中的
replace_listeners = ["model.tok2vec"]会强制让引入的预训练tagger放弃自身配套的预训练tok2vec权重,改用当前pipeline中仅用NER数据训练的tok2vec作为特征输入,该tok2vec未经过POS任务适配,就算调整顺序也无法输出正确的POS结果
注:frozen_components仅控制训练阶段不更新对应组件的参数,不解决组件执行顺序、特征层依赖错误的问题。
修正方案
按以下步骤调整配置即可:
- 调整pipeline组件顺序,将tagger移动到ner之前,保证POS标注流程在实体抽取之前执行
- 删除tagger组件下的
replace_listeners = ["model.tok2vec"]配置,让引入的预训练tagger使用自带的配套特征层,不依赖自定义训练的tok2vec - 保留
frozen_components = ["tagger"]配置,确保训练阶段不会更新tagger的预训练参数
修正后的核心配置片段:
[nlp] lang = "en" pipeline = ["tok2vec","tagger","ner"] batch_size = 1000 disabled = [] before_creation = null after_creation = null after_pipeline_creation = null tokenizer = {"@tokenizers":"spacy.Tokenizer.v1"} ... [components.tagger] source = "en_core_web_sm" component = "tagger" ... [training] ... frozen_components = ["tagger"]
调整后重新训练模型,预测时pipeline会先通过预训练tagger完成POS标注,再执行自定义NER组件的实体抽取,此时读取实体对应token的pos_属性即可拿到正常的POS预测结果。
内容的提问来源于stack exchange,提问作者nmlq
相关产品推荐
相关产品推荐

