Spacy - 保存自定义管道
Spacy - Save custom pipeline
我正在尝试将自定义 PhraseMatcher()
组件集成到我的 nlp 管道中,这样我就可以加载自定义 Spacy 模型,而无需将我的自定义组件重新添加到通用模型每个负载。
如何加载包含自定义管道组件的 Spacy 模型?
我创建了组件,将其添加到我的管道并使用以下内容保存:
import requests
from spacy.lang.en import English
from spacy.matcher import PhraseMatcher
from spacy.tokens import Doc, Span, Token
class RESTCountriesComponent(object):
name = 'countries'
def __init__(self, nlp, label='GPE'):
self.countries = [u'MyCountry', u'MyOtherCountry']
self.label = nlp.vocab.strings[label]
patterns = [nlp(c) for c in self.countries]
self.matcher = PhraseMatcher(nlp.vocab)
self.matcher.add('COUNTRIES', None, *patterns)
def __call__(self, doc):
matches = self.matcher(doc)
spans = []
for _, start, end in matches:
entity = Span(doc, start, end, label=self.label)
spans.append(entity)
doc.ents = list(doc.ents) + spans
for span in spans:
span.merge()
return doc
nlp = English()
rest_countries = RESTCountriesComponent(nlp)
nlp.add_pipe(rest_countries)
nlp.to_disk('myNlp')
然后我尝试加载我的模型,
nlp = spacy.load('myNlp')
但是得到这个错误信息:
KeyError: u"[E002] Can't find factory for 'countries'. This usually
happens when spaCy calls nlp.create_pipe
with a component name
that's not built in - for example, when constructing the pipeline from
a model's meta.json. If you're using a custom component, you can write
to Language.factories['countries']
or remove it from the model meta
and add it via nlp.add_pipe
instead."
我不能只将我的自定义组件添加到我的编程环境中的通用管道中。我怎样才能做我想做的事?
当您保存模型时,spaCy 将序列化所有数据并在模型的 meta.json
中存储对管道的引用。例如:["ner", "countries"]
。当您重新加载模型时,spaCy 将检查元数据并通过在所谓的 "factories": 函数中查找来初始化每个管道组件,这些函数告诉 spaCy 如何构建管道组件。 (原因是您通常不希望模型在重新加载时存储和评估任意代码——至少默认情况下不会。)
在您的例子中,spaCy 试图在工厂中查找组件名称 'countries'
但失败了,因为它不是内置的。 Language.factories
是一个简单的字典,因此您可以自定义它并添加您自己的条目:
from spacy.language import Language
Language.factories['countries'] = lambda nlp, **cfg: RESTCountriesComponent(nlp, **cfg)
工厂是一个接收共享 nlp
对象和可选关键字参数(配置参数)的函数。然后它初始化组件并 returns 它。如果您在加载模型 之前 添加上述代码,它应该会按预期加载。
更高级的方法
如果您希望自动处理此问题,您还可以将组件 与 模型一起发送。这需要使用 spacy package
命令将其包装为 Python 包,该命令会创建所有必需的 Python 文件。默认情况下,__init__.py
仅包含加载模型的函数——但您也可以向其添加自定义函数或使用它向 spaCy 的工厂添加条目。
从 v2.1.0
开始(目前以 nightly version for testing), spaCy will also support providing pipeline component factories via Python entry points 的形式提供。这对于生产设置特别有用 and/or 如果您想模块化您的各个组件并将它们拆分成自己的包. 例如,您可以为您的国家组件及其工厂创建一个 Python 包,将其上传到 PyPi,对其进行版本控制并单独测试。在其 setup.py
中,您的包可以定义它的 spaCy 工厂暴露以及在哪里找到它们。spaCy 将能够自动检测它们——您需要做的就是在相同的环境中安装包。您的模型包甚至可能需要您的组件包作为依赖项,因此它会在您安装时自动安装型号。
我遇到了同样的问题,这些是我使用的步骤:
- 1) 在包含所有不同 nlp 管道组件的 运行ning 笔记本之后保存管道,例如nlp.to_disc('pipeline_model_name')
- 2) 使用 Spacy 构建包保存管道:运行
python setup.py sdist
在此目录中。
- 3) pip 安装创建的包
- 4) 按照上述说明将自定义组件放入包的
__init__.py
文件中
- 4) 加载管道:
- 导入spacy
- nlp = spacy_package.load()
我正在尝试将自定义 PhraseMatcher()
组件集成到我的 nlp 管道中,这样我就可以加载自定义 Spacy 模型,而无需将我的自定义组件重新添加到通用模型每个负载。
如何加载包含自定义管道组件的 Spacy 模型?
我创建了组件,将其添加到我的管道并使用以下内容保存:
import requests
from spacy.lang.en import English
from spacy.matcher import PhraseMatcher
from spacy.tokens import Doc, Span, Token
class RESTCountriesComponent(object):
name = 'countries'
def __init__(self, nlp, label='GPE'):
self.countries = [u'MyCountry', u'MyOtherCountry']
self.label = nlp.vocab.strings[label]
patterns = [nlp(c) for c in self.countries]
self.matcher = PhraseMatcher(nlp.vocab)
self.matcher.add('COUNTRIES', None, *patterns)
def __call__(self, doc):
matches = self.matcher(doc)
spans = []
for _, start, end in matches:
entity = Span(doc, start, end, label=self.label)
spans.append(entity)
doc.ents = list(doc.ents) + spans
for span in spans:
span.merge()
return doc
nlp = English()
rest_countries = RESTCountriesComponent(nlp)
nlp.add_pipe(rest_countries)
nlp.to_disk('myNlp')
然后我尝试加载我的模型,
nlp = spacy.load('myNlp')
但是得到这个错误信息:
KeyError: u"[E002] Can't find factory for 'countries'. This usually happens when spaCy calls
nlp.create_pipe
with a component name that's not built in - for example, when constructing the pipeline from a model's meta.json. If you're using a custom component, you can write toLanguage.factories['countries']
or remove it from the model meta and add it vianlp.add_pipe
instead."
我不能只将我的自定义组件添加到我的编程环境中的通用管道中。我怎样才能做我想做的事?
当您保存模型时,spaCy 将序列化所有数据并在模型的 meta.json
中存储对管道的引用。例如:["ner", "countries"]
。当您重新加载模型时,spaCy 将检查元数据并通过在所谓的 "factories": 函数中查找来初始化每个管道组件,这些函数告诉 spaCy 如何构建管道组件。 (原因是您通常不希望模型在重新加载时存储和评估任意代码——至少默认情况下不会。)
在您的例子中,spaCy 试图在工厂中查找组件名称 'countries'
但失败了,因为它不是内置的。 Language.factories
是一个简单的字典,因此您可以自定义它并添加您自己的条目:
from spacy.language import Language
Language.factories['countries'] = lambda nlp, **cfg: RESTCountriesComponent(nlp, **cfg)
工厂是一个接收共享 nlp
对象和可选关键字参数(配置参数)的函数。然后它初始化组件并 returns 它。如果您在加载模型 之前 添加上述代码,它应该会按预期加载。
更高级的方法
如果您希望自动处理此问题,您还可以将组件 与 模型一起发送。这需要使用 spacy package
命令将其包装为 Python 包,该命令会创建所有必需的 Python 文件。默认情况下,__init__.py
仅包含加载模型的函数——但您也可以向其添加自定义函数或使用它向 spaCy 的工厂添加条目。
从 v2.1.0
开始(目前以 nightly version for testing), spaCy will also support providing pipeline component factories via Python entry points 的形式提供。这对于生产设置特别有用 and/or 如果您想模块化您的各个组件并将它们拆分成自己的包. 例如,您可以为您的国家组件及其工厂创建一个 Python 包,将其上传到 PyPi,对其进行版本控制并单独测试。在其 setup.py
中,您的包可以定义它的 spaCy 工厂暴露以及在哪里找到它们。spaCy 将能够自动检测它们——您需要做的就是在相同的环境中安装包。您的模型包甚至可能需要您的组件包作为依赖项,因此它会在您安装时自动安装型号。
我遇到了同样的问题,这些是我使用的步骤:
- 1) 在包含所有不同 nlp 管道组件的 运行ning 笔记本之后保存管道,例如nlp.to_disc('pipeline_model_name')
- 2) 使用 Spacy 构建包保存管道:运行
python setup.py sdist
在此目录中。 - 3) pip 安装创建的包
- 4) 按照上述说明将自定义组件放入包的
__init__.py
文件中 - 4) 加载管道:
- 导入spacy
- nlp = spacy_package.load()