使用en_core_web_trf训练自定义NER时触发无消息ValueError的解决方法
解决使用
en_core_web_trf训练NER模型时的ValueError问题 问题根源
你的代码存在几个关键问题,导致了无消息的ValueError:
- 函数调用时传入了未定义的
no_verlaps_dataset,应该使用你定义好的TRAIN_DATA - 使用
nlp.initialize()重置了整个预训练transformer模型,这在微调场景下完全没必要,反而会破坏模型的共享组件机制 - 错误地禁用其他管道,导致transformer组件无法正常工作
- 优化器创建方式不符合微调预训练模型的要求
修正后的代码
import random from spacy.training import Example from spacy.util import minibatch def train_spacy_model(data, model='en_core_web_trf', n_iter=10): # 加载预训练transformer模型 nlp = spacy.load(model) print(f"Loaded model '{model}'") # 获取NER组件 ner = nlp.get_pipe("ner") # 向NER组件添加新标签(如果有的话) for text, annotations in data: for ent in annotations.get("entities", []): ner.add_label(ent[2]) # 准备训练样本 examples = [] for text, annotations in data: doc = nlp.make_doc(text) example = Example.from_dict(doc, annotations) examples.append(example) # 启动训练,只更新NER组件 optimizer = nlp.resume_training() for itn in range(n_iter): print(f"Starting iteration {itn}") random.shuffle(examples) losses = {} # 小批量训练,batch size不宜过大 batches = minibatch(examples, size=2) for batch in batches: nlp.update( batch, drop=0.2, sgd=optimizer, losses=losses, exclude=["transformer", "tagger", "parser"] # 只训练NER ) print(f"Iteration {itn} Losses: {losses}") return nlp # 训练数据 TRAIN_DATA = [ ("Who is Shaka Khan?", {"entities": [(7, 17, "PERSON")]}), ("I like London.", {"entities": [(7, 13, "LOC")]}), ] # 调用训练函数 nlp = train_spacy_model(data=TRAIN_DATA, n_iter=10)
关键说明
- 不要初始化预训练模型:
nlp.initialize()会重置整个模型,包括transformer的预训练权重,这在微调时是错误的操作 - 正确指定训练范围:通过
exclude参数告诉模型只更新NER组件,保留其他预训练组件的权重 - 使用resume_training:
nlp.resume_training()会保留原有模型的优化器状态,适合微调场景 - 控制batch size:transformer模型对显存要求高,batch size建议设为2-4
- 减少迭代次数:预训练模型微调不需要太多迭代,10-20次足够避免过拟合
内容的提问来源于stack exchange,提问作者mCs
相关产品推荐
相关产品推荐

