#python-3.x #spacy #spacy-3
Вопрос:
Я пытаюсь реализовать свой собственный анализатор зависимостей с нуля в Spacy 3. Я создаю пустую модель, создаю пустой анализатор зависимостей, обучаю его и сохраняю его конфигурацию. Но когда я снова пытаюсь загрузить конфигурацию пользовательского синтаксического анализатора, я могу сделать это успешно только в том случае, если модель пуста. Если я использую непустую модель, то я продолжаю получать эту ошибку-ошибка значения: не удалось передать входной массив из формы (106,64) в форму (27,64).
import spacy
import random
from spacy.tokens import Doc
from spacy.training import Example
from spacy.pipeline import DependencyParser
from typing import List, Tuple
PARSER_CONFIG = 'parser.cfg'
TRAINING_DATA = [
('find a high paying job with no experience', {
'heads': [0, 4, 4, 4, 0, 7, 7, 4],
'deps': ['ROOT', '-', 'QUALITY', 'QUALITY', 'ACTIVITY', '-', 'QUALITY', 'ATTRIBUTE']
}),
('find good workout classes near home', {
'heads': [0, 3, 3, 0, 5, 3],
'deps': ['ROOT', 'QUALITY', 'QUALITY', 'ACTIVITY', 'QUALITY', 'ATTRIBUTE']
})
]
def create_training_examples(training_data: List[Tuple]) -> List[Example]:
""" Create list of training examples """
examples = []
nlp = spacy.load('en_core_web_md')
for text, annotations in training_data:
print(f"{text} - {annotations}")
examples.append(Example.from_dict(nlp(text), annotations))
return examples
def save_parser_config(parser: DependencyParser):
print(f"Save parser config to '{PARSER_CONFIG}' ... ", end='')
parser.to_disk(PARSER_CONFIG)
print("DONE")
def load_parser_config(parser: DependencyParser):
print(f"Load parser config from '{PARSER_CONFIG}' ... ", end='')
parser.from_disk(PARSER_CONFIG)
print("DONE")
def main():
nlp = spacy.blank('en')
# Create new parser
parser = nlp.add_pipe('parser', first=True)
for text, annotations in TRAINING_DATA:
for label in annotations['deps']:
if label not in parser.labels:
parser.add_label(label)
print(f"Added labels: {parser.labels}")
examples = create_training_examples(TRAINING_DATA)
# Training
# NOTE: The 'lambda: examples' part is mandatory in Spacy 3 - https://spacy.io/usage/v3#migrating-training-python
optimizer = nlp.initialize(lambda: examples)
print(f"Training ... ", end='')
for i in range(25):
print(f"{i} ", end='')
random.shuffle(examples)
nlp.update(examples, sgd=optimizer)
print(f"... DONE")
save_parser_config(parser)
# I can load parser config to blank model ...
nlp = spacy.blank('en')
parser = nlp.add_pipe('parser')
# ... but I cannot load parser config to already existing model
# Return -> ValueError: could not broadcast input array from shape (106,64) into shape (27,64)
# nlp = spacy.load('en_core_web_md')
# parser = nlp.get_pipe('parser')
load_parser_config(parser)
print(f"Current pipeline is {nlp.meta['pipeline']}")
doc = nlp(u'find a high paid job with no degree')
print(f"Arcs: {[(w.text, w.dep_, w.head.text) for w in doc if w.dep_ != '-']}")
if __name__ == '__main__':
main()
Сам пользовательский синтаксический анализатор работает так, как ожидалось. Вы можете проверить это, закомментировав весь код от save_parser_config(parser)
до load_parser_config(parser)
(включительно) и запустив код снова. Вы увидите, что новые метки назначаются по мере необходимости. Вот почему я думаю, что корень проблемы заключается в невозможности загрузить конфигурацию анализатора пустой модели в непустую модель. Но как это обойти?
Комментарии:
1. То же самое на форумах spaCy github.com/explosion/spaCy/discussions/9239
Ответ №1:
Я связался с разработчиками, и вот что они ответили — https://github.com/explosion/spaCy/discussions/9239