Python 如何在Spacy中创建具有多个模型的NER管道

Python 如何在Spacy中创建具有多个模型的NER管道,python,spacy,ner,Python,Spacy,Ner,我正在尝试为spacy NER培训新的实体。我尝试将我的新实体添加到现有spacy“en”模型中。但是,这影响了'en'和我的新实体的预测模型。 一、 因此,创建一个空白模型并训练实体识别。这很有效。然而,它只能预测我训练过的对象,而不能预测常规的空间实体识别 比如说我把“马”训练成动物实体 对于给定的文本 txt ='Did you know that George bought those horses for 10000 dollars?' 我希望能够识别以下实体 George - PE

我正在尝试为spacy NER培训新的实体。我尝试将我的新实体添加到现有spacy“en”模型中。但是,这影响了
'en'
和我的新实体的预测模型。

一、 因此,创建一个空白模型并训练实体识别。这很有效。然而,它只能预测我训练过的对象,而不能预测常规的空间实体识别

比如说我把“马”训练成动物实体

对于给定的文本

txt ='Did you know that George bought those horses for 10000 dollars?'
我希望能够识别以下实体

George - PERSON
horses - ANIMAL
10000 dollars - MONEY.
根据我目前的设置,它只识别马

nlp = spacy.load('en')
hsnlp = spacy.load('models/spacy/animal/')
nlp.add_pipe(hsnlp.pipeline[-1][-1], 'hsner')

nlp.pipe_names
这给

----------------------
['tagger', 'parser', 'ner', 'hsner']
----------------------
然而,当我试图执行

doc = nlp(txt)  *<-- Gives me kernel error and stops working*

doc=nlp(txt)*主要问题是如何加载和组合管道组件,以便它们使用相同的
Vocab
nlp.Vocab
),因为管道假定所有组件共享相同的Vocab,否则可能会出现与
StringStore
相关的错误

您不应该尝试组合使用不同单词向量训练的管道组件,但只要向量相同,就存在如何从具有相同词汇的单独模型加载组件的问题

使用
spacy.load()
无法做到这一点,因此我认为最简单的方法是使用所需的vocab初始化新的管道组件,并通过临时序列化将现有组件重新加载到新组件中

要使用易于访问的模型进行简短的工作演示,我将演示如何将德语NER模型从
de_core\u news\u sm
添加到英语模型
en_core\u web\u sm
,即使这不是您通常想要做的事情:

import spacy#使用v2.2.3进行测试
从spacy.pipeline导入实体识别器
text=“简住在波士顿。简住在不来梅。”
#加载英语和德语模型
nlp_en=spacy.load('en_core_web_sm')#NER标签PERSON,GPE。。。
nlp_de=spacy.load('de_core_news_sm')#NER标签PER,LOC。。。
#Vocab对象不同
断言nlp_en.vocab!=nlp_de.vocab
#但是向量是相同的(因为两个模型都没有向量)
断言nlp_en.vocab.vectors.to_bytes()=nlp_de.vocab.vectors.to_bytes()
#英文原稿
doc1=nlp_en(文本)
打印([(ent.text,ent.label)用于doc1.ents中的ent])
#[('Jane','PERSON'),('Boston','GPE'),('Breme','GPE')]
#原始德语输出(德语模型对英语文本做出奇怪的预测)
doc2=nlp_de(文本)
打印([(ent.text,ent.label)用于doc2.ents中的ent])
#[('Jane lives','PER'),('Boston','LOC'),('Jan lives','PER'),('Breme','LOC')]
#使用英语管道中的vocab初始化新的NER组件
ner_de=实体识别器(nlp_en.vocab)
#通过序列化从德国模型重新加载NER组件
#没有vocab和使用新的NER组件反序列化
ner_de.from_字节(nlp_de.get_pipe(“ner”)。到_字节(排除=[“vocab”]))
#将德语NER组件添加到英语管道的末尾
nlp_en.添加管道(ner_de,name=“ner_de”)
#检查他们是否有相同的词汇B
断言nlp_en.vocab==ner_de.vocab
#组合输出(英语第一,德语第二)
doc3=nlp_en(文本)
打印([(ent.text,ent.label)用于doc3.ents中的ent])
#[('Jane','PERSON'),('Boston','GPE'),('Jan lives','PER'),('Breme','GPE')]
Spacy的NER组件(
EntityRuler
EntityRecognizer
)旨在保留任何现有实体,因此新组件仅添加带有德语NER标记的
Jan lives
,并保留英语NER预测的所有其他实体

您可以使用
add_pipe()
的选项来确定组件插入管道的位置。要将德语NER添加到默认英语NER之前,请执行以下操作:

nlp_en.添加管道(ner_de,name=“ner_de”,before=“ner”)
#[('Jane lives','PER'),('Boston','LOC'),('Jan lives','PER'),('Breme','LOC')]
所有
添加管道()
选项都在文档中:

您可以将扩展管道保存到磁盘作为单个模型,以便下次使用
spacy.load()
在一行中加载:

nlp文件到磁盘(“/path/to/model”)
nlp_reload=spacy.load(“/path/to/model”)
打印(nlp_重新加载。管道名称)#['tagger'、'parser'、'ner'、'ner_de']

此错误可能有助于解决此问题:希望在所有
spaCy
的错误修复之后,看到将多个
spaCy
NER模型加载到一个文本的正确方法。这似乎至少对我来说是错误的,在本地(spaCy 2.1.8),如果
是正确的,则行为似乎是“不要运行NER”。特别是,我使用两个不同的序列化NER模型运行了这段代码,第三组实体与第一组实体完全相同。