SpaCy v3.1中如何向预训练模型添加自定义NER标签?
SpaCy 3.x 基于预训练模型扩展NER自定义标签操作指引
首先纠正你之前的思路误区:不需要新增独立的EntityRecognizer管道组件,多个并行NER组件会出现实体重叠冲突问题,直接扩展原有预训练ner组件的标签体系即可,既可以保留原有默认实体的识别能力,又能支持自定义实体识别。
具体操作步骤
- 第一步:准备标注数据
你的训练/验证标注数据需要同时覆盖SpaCy默认实体(GPE/PERSON/MONEY等)和你新增的自定义实体,避免训练后原有实体识别能力出现灾难性遗忘。标注完成后用spacy convert命令将标注文件转成SpaCy 3要求的.spacy二进制格式。 - 第二步:修改训练配置文件
你原有的配置只需要做少量调整即可,修改后的参考配置如下:[paths] train = "./train.spacy" # 替换为你的训练数据集路径 dev = "./dev.spacy" # 替换为你的验证数据集路径 vectors = null init_tok2vec = null [system] gpu_allocator = null seed = 0 [nlp] lang = "en" pipeline = ["tok2vec","ner"] # 不需要新增管道,沿用原有pipeline即可 batch_size = 1000 disabled = [] before_creation = null after_creation = null after_pipeline_creation = null tokenizer = {"@tokenizers":"spacy.Tokenizer.v1"} [components] # 继承预训练模型的tok2vec权重,避免从零训练 [components.tok2vec] source = "en_core_web_sm" [components.ner] factory = "ner" source = "en_core_web_sm" # 继承预训练的ner权重,保留原有识别能力 incorrect_spans_key = null moves = null update_with_oracle_cut_size = 100 # 新增训练配置段 [training] frozen_components = ["tok2vec"] # 冻结tok2vec层权重,训练时只更新ner层,既快又能避免破坏预训练语义能力 dev_corpus = "corpora.dev" train_corpus = "corpora.train" max_steps = 2000 # 根据你的数据量调整步数 patience = 500 [corpora] [corpora.train] @readers = "spacy.Corpus.v1" path = ${paths.train} max_length = 0 [corpora.dev] @readers = "spacy.Corpus.v1" path = ${paths.dev} max_length = 0 - 第三步:执行CLI训练
直接在终端运行以下命令启动训练:
训练完成后,spacy train config.cfg --output ./trained_model./trained_model/model-best就是最终的模型,加载后可同时识别默认实体和自定义实体。 - 如果你确实需要添加独立的NER组件(比如两套标签体系完全独立),可以按以下方式调整:
- 配置文件中
[nlp]的pipeline改为["tok2vec","ner","ner_custom"] - 在
[components]下新增ner_custom配置:
[components.ner_custom] factory = "ner" spans_key = "custom_ner" # 指定独立的span存储key,避免和原有ner冲突- 训练时标注数据的实体对应到
custom_ner的span即可。
- 配置文件中
原有代码问题修正
你之前写的自定义工厂函数逻辑完全错误,返回的LanguageDetector是语言检测组件,和NER任务无关。如果仅扩展原有NER标签,不需要自定义任何工厂函数,直接用SpaCy自带的ner组件即可。
内容的提问来源于stack exchange,提问作者Zizzipupp
相关产品推荐
相关产品推荐

