为 spacy pipeline 创建组件

Create components for spacy pipeline

我目前正在使用 Spacy,我正在探索如何使用管道来更有效地工作。我正在尝试创建自己的组件以添加到管道中,但我每次都将 运行 保留在一些已发布的组件中。示例:

import spacy
nlp = spacy.blank("fr")

def lemmatizer(doc) :
    return " ".join([elt.lemma_ for elt in nlp(doc.text)])

nlp.add_pipe(lemmatizer) # add the lemmatizer to the pipeline

nlp("Hi, I'm new here.")

我收到以下错误:

    ---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
 in 
----> 1 nlp("Hi, I'm new here.")

/var/opt/data/dataiku/datadir/code-envs/python/recla_text_sci/lib64/python3.6/site-packages/spacy/language.py in __call__(self, text, disable, component_cfg)
    443             if not hasattr(proc, "__call__"):
    444                 raise ValueError(Errors.E003.format(component=type(proc), name=name))
--> 445             doc = proc(doc, **component_cfg.get(name, {}))
    446             if doc is None:
    447                 raise ValueError(Errors.E005.format(name=name))

 in lemmatizer(doc)
      1 def lemmatizer(doc) :
----> 2     return " ".join([elt.lemma_ for elt in nlp(doc.text)])

... last 2 frames repeated, from the frame below ...

/var/opt/data/dataiku/datadir/code-envs/python/recla_text_sci/lib64/python3.6/site-packages/spacy/language.py in __call__(self, text, disable, component_cfg)
    443             if not hasattr(proc, "__call__"):
    444                 raise ValueError(Errors.E003.format(component=type(proc), name=name))
--> 445             doc = proc(doc, **component_cfg.get(name, {}))
    446             if doc is None:
    447                 raise ValueError(Errors.E005.format(name=name))

RecursionError: maximum recursion depth exceeded

看起来您正在用 spaCy 编写一个简单的无状态组件。无状态组件可以定义为接受 Doc 和 returns 相同 Doc 的函数。您的代码有几个问题。

首先,关于管道的工作原理。您可以将 spaCy 管道(nlp() 调用)想象成这样工作:

def do_nlp(text):
    doc = tokenizer(text) # the tokenizer is special and comes before the pipeline
    for pipe in pipes:
        doc = pipe(doc)

所以基本上每个管道就像一个函数,它们在文档中按顺序调用。

因此,对于您的代码,您遇到错误的原因是在上面的循环中您再次调用了 nlp()。再次调用 nlp()。等等。您不能在组件内部调用 nlp(),也不应该这样做。

如果这是唯一的问题,您可以这样做:

return " ".join([elt.lemma_ for elt in doc])

但这也行不通 - 您正在 return 字符串,但您需要 return 文档。

您似乎正在尝试将 Doc 中的每个标记更改为其词元。但是您不能更改 Doc 的文本,这是 spaCy 中的设计决定,因此不会起作用。

你应该看看 docs on custom components

如果我对您尝试做的事情的理解是正确的,那么这作为管道组件似乎没有意义,可以只是 post-processing。