Как использовать пользовательский модуль EntityRecognizer при обучении EntityLinker - PullRequest
0 голосов
/ 10 января 2020

В примере сценария , предоставленном spaCy для обучения компонента EntityLinker, пользовательский объект EntityRuler инициализируется и добавляется в конвейер

# Add a custom component to recognize "Russ Cochran" as an entity for the example training data.
# Note that in a realistic application, an actual NER algorithm should be used instead.
ruler = EntityRuler(nlp)
patterns = [{"label": "PERSON", "pattern": [{"LOWER": "russ"}, {"LOWER": "cochran"}]}]
ruler.add_patterns(patterns)
nlp.add_pipe(ruler)

Мне интересно, как бы вы добавили вместо этого свой собственный обученный модуль EntityRecognizer. До сих пор я пытался модифицировать скрипт следующим образом:

@plac.annotations(
    kb_path=("Path to the knowledge base", "positional", None, Path),
    vocab_path=("Path to the vocab for the kb", "positional", None, Path),
    model=("Model name. Defaults to blank 'en' model.", "option", "m", str),
    output_dir=("Optional output directory", "option", "o", Path),
    n_iter=("Number of training iterations", "option", "n", int),
)
def main(kb_path, vocab_path=None, model=None, output_dir=None, n_iter=50):
    """Create a blank model with the specified vocab, set up the pipeline and train the entity linker.
    The `vocab` should be the one used during creation of the KB."""
    random.seed(0)
    if model is not None:
        nlp = spacy.load(model)  # load existing spaCy model
        print("Loaded model '%s'" % model)
    else:
        vocab = Vocab().from_disk(vocab_path)
        # create blank Language class with correct vocab
        nlp = spacy.blank("en", vocab=vocab)
        nlp.vocab.vectors.name = "spacy_pretrained_vectors"
        print("Created blank 'en' model with vocab from '%s'" % vocab_path)

        # Add a sentencizer component. Alternatively, add a dependency parser for higher accuracy.
        nlp.add_pipe(nlp.create_pipe('sentencizer'))

        # Add a custom component to recognize "Russ Cochran" as an entity for the example training data.
        # Note that in a realistic application, an actual NER algorithm should be used instead.
        ruler = EntityRuler(nlp)
        patterns = [{"label": "PERSON", "pattern": [{"LOWER": "russ"}, {"LOWER": "cochran"}]}]
        ruler.add_patterns(patterns)
        nlp.add_pipe(ruler)

и вызывать скрипт с:

python train_entity_linker.py ./tmp/kb ./tmp/vocab -m en_core_web_lg -o ./tmp -n 1

, поскольку en_core_web_lg имеет обученного EntityLinker в своем конвейере. Обратите внимание, что я создал объект базы знаний с помощью:

python pretrain_kb.py -m en_core_web_lg -n 1 -o ./tmp

Однако я получаю следующую ошибку:

  File "train_entity_linker.py", line 103, in main
    kb_ids = nlp.get_pipe("entity_linker").kb.get_entity_strings()
  File "kb.pyx", line 101, in spacy.kb.KnowledgeBase.get_entity_strings
  File "strings.pyx", line 136, in spacy.strings.StringStore.__getitem__
KeyError: "[E018] Can't retrieve string for hash '8150086140315095098'. This usually refers to an issue with the `Vocab` or `StringStore`."

Кто-то может объяснить, почему этот подход не работает, и какой правильный подход был бы для добавления и обучения компонента EntityLinker в обученную модель с EntityRecognizer уже в ее конвейере?

...