训练spaCy SpanCat模型遇E143标签未初始化错误,求解决方案
解决spaCy SpanCat训练时的[E143]标签未初始化错误
问题详情
训练spaCy SpanCat模型时触发错误:
ValueError: [E143] Labels for component 'spancat' not initialized. This can be fixed by calling add_label, or by providing a representative batch of examples to the component's 'initialize' method.
已将NER ents转换为spans,转换代码:
def main(loc: Path, lang: str, span_key: str): """ Set the NER data into the doc.spans, under a given key. The SpanCategorizer component uses the doc.spans, so that it can work with overlapping or nested annotations, which can't be represented on the per-token level. """ nlp = spacy.blank(lang) docbin = DocBin().from_disk(loc) docs = list(docbin.get_docs(nlp.vocab)) for doc in docs: doc.spans[span_key] = list(doc.ents) DocBin(docs=docs).to_disk(loc)
使用的配置文件:
[paths] train = null dev = null vectors = null init_tok2vec = null [system] gpu_allocator = null seed = 444 [nlp] lang = "en" pipeline = ["tok2vec","spancat"] batch_size = 1000 disabled = [] before_creation = null after_creation = null after_pipeline_creation = null tokenizer = {"@tokenizers":"spacy.Tokenizer.v1"} [components] [components.spancat] factory = "spancat" max_positive = null scorer = {"@scorers":"spacy.spancat_scorer.v1"} spans_key = "sc" threshold = 0.5 [components.spancat.model] @architectures = "spacy.SpanCategorizer.v1" [components.spancat.model.reducer] @layers = "spacy.mean_max_reducer.v1" hidden_size = 128 [components.spancat.model.scorer] @layers = "spacy.LinearLogistic.v1" nO = null nI = null [components.spancat.model.tok2vec] @architectures = "spacy.Tok2VecListener.v1" width = ${components.tok2vec.model.encode.width} upstream = "*" [components.spancat.suggester] @misc = "spacy.ngram_suggester.v1" sizes = [1,2,3] [components.tok2vec] factory = "tok2vec" [components.tok2vec.model] @architectures = "spacy.Tok2Vec.v2" [components.tok2vec.model.embed] @architectures = "spacy.MultiHashEmbed.v2" width = ${components.tok2vec.model.encode.width} attrs = ["NORM","PREFIX","SUFFIX","SHAPE"] rows = [5000,1000,2500,2500] include_static_vectors = true [components.tok2vec.model.encode] @architectures = "spacy.MaxoutWindowEncoder.v2" width = 256 depth = 8 window_size = 1 maxout_pieces = 3 [corpora] [corpora.dev] @readers = "spacy.Corpus.v1" path = ${paths.dev} max_length = 0 gold_preproc = false limit = 0 augmenter = null [corpora.train] @readers = "spacy.Corpus.v1" path = ${paths.train} max_length = 0 gold_preproc = false limit = 0 augmenter = null [training] dev_corpus = "corpora.dev" train_corpus = "corpora.train" max_epochs = 70 seed = ${system.seed} gpu_allocator = ${system.gpu_allocator} dropout = 0.1 accumulate_gradient = 1 patience = 1600 max_steps = 20000 eval_frequency = 200 frozen_components = [] annotating_components = [] before_to_disk = null [training.batcher] @batchers = "spacy.batch_by_words.v1" discard_oversize = false tolerance = 0.2 get_length = null [training.batcher.size] @schedules = "compounding.v1" start = 100 stop = 1000 compound = 1.001 t = 0.0 [training.logger] @loggers = "spacy.ConsoleLogger.v1" progress_bar = false [training.optimizer] @optimizers = "Adam.v1" beta1 = 0.9 beta2 = 0.999 L2_is_weight_decay = true L2 = 0.01 grad_clip = 1.0 use_averages = false eps = 0.00000001 learn_rate = 0.001 [training.score_weights] spans_sc_f = 1.0 spans_sc_p = 0.0 spans_sc_r = 0.0 [pretraining] [initialize] vectors = ${paths.vectors} init_tok2vec = ${paths.init_tok2vec} vocab_data = null lookups = null before_init = null after_init = null [initialize.components] [initialize.tokenizer]
使用的span键为"sc"。
解决方案
方法一:配置自动从训练数据初始化标签(推荐)
修改配置文件的[initialize.components]部分,添加spancat的初始化设置,让spaCy自动从训练数据的doc.spans["sc"]中提取标签:
[initialize.components] [initialize.components.spancat] @initialize = "spacy.initialize_spancat.v1" spans_key = "sc"
添加后,spaCy在初始化阶段会自动扫描训练数据,获取所有span标签并完成组件初始化。
方法二:手动添加标签(适用于已知所有标签的场景)
如果已经明确所有需要识别的span标签,可以在代码中手动添加:
import spacy from spacy.tokens import DocBin # 加载配置并禁用spancat组件先 nlp = spacy.load("your_config.cfg", disable=["spancat"]) # 添加spancat组件,指定span_key spancat = nlp.add_pipe("spancat", config={"spans_key": "sc"}) # 替换为你的实际标签列表,比如从原NER数据中获取的标签 labels = ["PERSON", "ORG", "LOC"] for label in labels: spancat.add_label(label) # 读取训练数据用于初始化 docbin = DocBin().from_disk("your_train_data_path") train_docs = list(docbin.get_docs(nlp.vocab)) # 初始化组件 spacy.util.initialize_bigram_suggester(nlp.vocab, sizes=[1,2,3]) spancat.initialize(lambda: nlp.pipe(train_docs), nlp=nlp) # 保存初始化后的模型或直接开始训练 nlp.to_disk("initialized_model")
额外验证步骤
确保转换后的数据集确实包含正确的span标签:
import spacy from spacy.tokens import DocBin nlp = spacy.blank("en") docbin = DocBin().from_disk("your_train_data_path") docs = list(docbin.get_docs(nlp.vocab)) # 打印前5个文档的span信息,确认标签存在 for doc in docs[:5]: spans = doc.spans.get("sc", []) print(f"文档内容: {doc.text}") print(f"Span标签: {[(span.text, span.label_) for span in spans]}")
如果输出中没有标签或spans为空,说明数据转换步骤存在问题,需要检查原NER数据是否正确。
内容的提问来源于stack exchange,提问作者SteveS
相关产品推荐
相关产品推荐

