【问题标题】:Spacy - Save custom pipelineSpacy - 保存自定义管道
【发布时间】:2018-12-26 23:14:52
【问题描述】:

我正在尝试将自定义 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'。这通常 当 spaCy 使用组件名称调用 nlp.create_pipe 时发生 这不是内置的 - 例如,在构建管道时 模型的 meta.json。如果您使用的是自定义组件,则可以编写 到Language.factories['countries'] 或将其从模型元数据中删除 并改为通过nlp.add_pipe 添加。”

我不能只将我的自定义组件添加到我的编程环境中的通用管道中。我该怎么做?

【问题讨论】:

    标签: python nlp spacy


    【解决方案1】:

    当您保存模型时,spaCy 将序列化所有数据并将对您的管道的引用存储在模型的meta.json 中。例如:["ner", "countries"]。当您重新加载模型时,spaCy 将检查元数据并通过在所谓的“工厂”中查找来初始化每个管道组件:告诉 spaCy 如何构建管道组件的函数。 (这样做的原因是您通常不希望模型在重新加载时存储和评估任意代码 - 至少默认情况下不会。)

    在您的情况下,spaCy 试图在工厂中查找组件名称 'countries' 并失败,因为它不是内置的。不过,Language.factories 是一个简单的字典,因此您可以自定义它并添加自己的条目:

    from spacy.language import Language
    Language.factories['countries'] = lambda nlp, **cfg: RESTCountriesComponent(nlp, **cfg)
    

    工厂是一个函数,它接收共享的nlp 对象和可选的关键字参数(配置参数)。然后它初始化组件并返回它。如果您在加载模型之前添加上述代码,它应该会按预期加载。

    更高级的方法

    如果您希望自动处理此问题,您还可以将您的组件 一起发送到您的模型中。这需要使用 spacy package 命令将其包装为 Python 包,该命令会创建所有必需的 Python 文件。默认情况下,__init__.py 仅包含一个加载模型的函数——但您也可以向其添加自定义函数或使用它向 spaCy 的工厂添加条目。

    截至v2.1.0(目前可作为nightly version 用于测试),spaCy 还将支持提供管道组件工厂via Python entry points。这对于生产设置和/或如果您想模块化您的各个组件并将它们拆分到自己的包中特别有用。例如,您可以为您的国家组件及其工厂创建一个 Python 包,将其上传到 PyPi,对其进行版本化和单独测试。在其setup.py 中,您的包可以定义它公开的 spaCy 工厂以及在哪里可以找到它们。 spaCy 将能够自动检测它们——您需要做的就是在相同的环境中安装软件包。您的模型包甚至可能需要您的组件包作为依赖项,因此它会在您安装模型时自动安装。

    【讨论】:

      【解决方案2】:

      我也遇到了同样的问题,这些是我使用的步骤:

      • 1) 运行包含所有不同 nlp 管道组件的笔记本后保存管道,例如nlp.to_disc('pipeline_model_name')
      • 2) 使用 Spacy 构建包保存的管道:在此目录中运行 python setup.py sdist
      • 3) 点安装创建的包
      • 4) 按照上述说明将自定义组件放入包的__init__.py 文件中
      • 4) 加载管道:
        • 导入 spacy
        • nlp = spacy_package.load()

      【讨论】:

        猜你喜欢
        • 2021-04-21
        • 1970-01-01
        • 2021-06-02
        • 1970-01-01
        • 1970-01-01
        • 2020-06-17
        • 2014-09-18
        • 2016-12-24
        • 2019-10-12
        相关资源
        最近更新 更多