首页 > 解决方案 > 加载训练的 en_core_web_trf spacyV3 NER 模型时出错

问题描述

在加载预训练的 spacy 模型以对自定义数据进行微调之后

spacy.require_gpu()
nlp = spacy.load("en_core_web_trf",exclude=['tagger', 'parser', 'attribute_ruler', 'lemmatizer'])

加载验证时出错

model=spacy.load(category_output_dir + "/%s" % itn,exclude=['tagger', 'parser', 'attribute_ruler', 'lemmatizer'])

文件“/usr/local/lib/python3.6/dist-packages/spacy/init.py”,第 47 行,在加载返回 util.load_model(name, disable=disable, exclude=exclude, config=config) 文件“/usr/local/lib/python3.6/dist-packages/spacy/util.py ",第 275 行,在 load_model 返回 load_model_from_path(Path(name), **kwargs) 文件 "/usr/local/lib/python3.6/dist-packages/spacy/util.py",第 341 行,在 load_model_from_path 返回 nlp .from_disk(model_path, exclude=exclude) File "/usr/local/lib/python3.6/dist-packages/spacy/language.py", line 1705, in from_disk util.from_disk(path, deserializers, exclude) File " /usr/local/lib/python3.6/dist-packages/spacy/util.py”,第 1085 行,在 from_disk 阅读器(路径/键)文件“/usr/local/lib/python3.6/dist-packages/ spacy/language.py",第 1700 行,在 p 中,exclude=["vocab"] 文件 "spacy/pipeline/transition_parser.pyx",第 479 行,在 spacy 中。pipeline.transition_parser.Parser.from_disk 文件“/usr/local/lib/python3.6/dist-packages/thinc/model.py”,第 529 行,from_bytes 返回 self.from_dict(msg) 文件“/usr/local/ lib/python3.6/dist-packages/thinc/model.py”,第 552 行,在 from_dict node.set_dim(dim, value) 文件“/usr/local/lib/python3.6/dist-packages/thinc/model .py”,第 188 行,在 set_dim 中引发 ValueError(err) ValueError:尝试将模型“precomputable_affine”的维度“nO”从 78 更改为 74py",第 188 行,在 set_dim 中引发 ValueError(err) ValueError:尝试将模型 'precomputable_affine' 的维度 'nO' 从 78 更改为 74py",第 188 行,在 set_dim 中引发 ValueError(err) ValueError:尝试将模型 'precomputable_affine' 的维度 'nO' 从 78 更改为 74

这是代码片段

import random
from tqdm import tqdm
import spacy
import os
import copy
from spacy.tokens import Doc
from spacy.training import Example
from spacy.util import minibatch, compounding, decaying

spacy.require_gpu()
nlp = spacy.load("en_core_web_trf",exclude=['tagger', 'parser', 
'attribute_ruler', 'lemmatizer'])

ner = nlp.get_pipe('ner')
for _, annotations in TRAIN_DATA:
    for ent in annotations.get('entities'):
        ner.add_label(ent[2])

for itn in range(n_iter):
    random.shuffle(TRAIN_DATA)
    losses = {}

for batch in tqdm(minibatch(TRAIN_DATA,size=compounding(4., 64., 1.01))):
    
    for text, annots in batch:
         examples = []
         try:
              examples.append(Example.from_dict(nlp.make_doc(text), annots))
              losses=nlp.update(examples,sgd=optimizer,losses=losses)
            except:
                continue
if use_optimizer_averages:
     with nlp.use_params(optimizer.averages):
         os.mkdir(output_dir + "/%s" % itn)
         nlp.to_disk(output_dir + "/%s" % itn)
         model=spacy.load(output_dir + "/%s" % itn,exclude=['tagger', 'parser', 'attribute_ruler', 'lemmatizer'])

火车数据格式:TRAIN_DATA = [["谁是沙卡汗?", {"entities": [(7, 17, "FRIENDS")]}],["我喜欢伦敦。", {"entities": [( 7, 13, "LOC")]}]]

标签: nlpspacy

解决方案


看起来您遇到了v3.0.0rc2spaCy 3 候选版本的错误。我们正在努力为最终的 3.0 版本修复此问题,请参见此处:https ://github.com/explosion/spaCy/pull/6460

同时,恐怕您将无法为基于转换器的预训练 NER 模型添加额外的标签。不过,我建议您从头开始训练一个新的 NER 组件。

在 spaCy 3 中,我们建议使用配置系统而不是编写自己的训练循环 ( https://nightly.spacy.io/usage/training#config )。在配置文件中,您可以从其他管道中获取组件,如下所示:

[components.transformer]
source = "en_core_web_trf"
component = "transformer"

这允许您重用预训练模型的转换器权重,并在此基础上创建一个新的 NER 模型(https://nightly.spacy.io/usage/embeddings-transformers):

[components.ner]
factory = "ner"

[nlp.pipeline.ner.model]
@architectures = "spacy.TransitionBasedParser.v1"
state_type = "ner"
extra_state_tokens = false
hidden_width = 128
maxout_pieces = 3
use_upper = false

[nlp.pipeline.ner.model.tok2vec]
@architectures = "spacy-transformers.TransformerListener.v1"
grad_factor = 1.0

[nlp.pipeline.ner.model.tok2vec.pooling]
@layers = "reduce_mean.v1"

您甚至可以从 NER 组件中获取旧的 NER 组件en_core_web_trf,只需将其命名不同,您的管道中就会运行两个 NER,每个用于一组不同的标签。

或者,您也可以使用非基于变压器的模型,例如en_core_web_lg. 像以前一样,向这样的预训练模型添加自定义标签应该可以正常工作。


推荐阅读