В настоящее время я работаю со 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. Компонент без состояния можно определить как функцию, которая принимает документ и возвращает тот же документ. В вашем коде есть несколько проблем.
Во-первых, о том, как работают пайплайны. Вы можете представить конвейер 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])
Но это тоже не сработает — вы возвращаете строку, а вам нужно вернуть Doc.
Похоже, вы пытаетесь изменить каждый токен в документе на его лемму. Но вы не можете изменить текст документа, это дизайнерское решение в spaCy, так что это не сработает.
Вероятно, вам следует взглянуть на файл документы по пользовательским компонентам.
Если мое понимание того, что вы пытаетесь сделать, верно, это не имеет смысла как компонент конвейера и может быть просто постобработкой.
Прочитав ссылку, которую вы предоставили, я понял, что шел по этому пути неправильно. Спасибо за помощь